aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorubit2012-12-03 21:26:36 +0100
committerubit2012-12-03 21:26:36 +0100
commit5d4b7d537d872d27c394402d3483c2a9bd2153f0 (patch)
tree39aae50386555bf024700314fb7bee5121a9d683 /OpenSim
parentMerge branch 'ubitwork' of ssh://3dhosting.de/var/git/careminster into ubitwork (diff)
parentMerge branch 'avination' into ubitwork (diff)
downloadopensim-SC_OLD-5d4b7d537d872d27c394402d3483c2a9bd2153f0.zip
opensim-SC_OLD-5d4b7d537d872d27c394402d3483c2a9bd2153f0.tar.gz
opensim-SC_OLD-5d4b7d537d872d27c394402d3483c2a9bd2153f0.tar.bz2
opensim-SC_OLD-5d4b7d537d872d27c394402d3483c2a9bd2153f0.tar.xz
Merge branch 'ubitwork' of ssh://3dhosting.de/var/git/careminster into ubitwork
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs15
-rw-r--r--OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs4
-rw-r--r--OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs2
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs95
-rw-r--r--OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs30
-rw-r--r--OpenSim/ApplicationPlugins/Rest/RestPlugin.cs14
-rw-r--r--OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs162
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs24
-rw-r--r--OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Capabilities/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/ConsoleClient/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Data/IRegionData.cs15
-rw-r--r--OpenSim/Data/IXInventoryData.cs27
-rw-r--r--OpenSim/Data/MSSQL/MSSQLRegionData.cs1
-rw-r--r--OpenSim/Data/MSSQL/MSSQLXInventoryData.cs175
-rw-r--r--OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/MySQL/MySQLGenericTableHandler.cs6
-rw-r--r--OpenSim/Data/MySQL/MySQLRegionData.cs4
-rw-r--r--OpenSim/Data/MySQL/MySQLSimulationData.cs457
-rw-r--r--OpenSim/Data/MySQL/MySQLXInventoryData.cs138
-rw-r--r--OpenSim/Data/MySQL/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/MySQL/Resources/GridUserStore.migrations5
-rw-r--r--OpenSim/Data/Null/NullRegionData.cs1
-rw-r--r--OpenSim/Data/Null/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/SQLite/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/SQLite/SQLiteAssetData.cs14
-rw-r--r--OpenSim/Data/SQLite/SQLiteAuthenticationData.cs145
-rw-r--r--OpenSim/Data/SQLite/SQLiteAvatarData.cs22
-rw-r--r--OpenSim/Data/SQLite/SQLiteEstateData.cs206
-rw-r--r--OpenSim/Data/SQLite/SQLiteFramework.cs9
-rw-r--r--OpenSim/Data/SQLite/SQLiteFriendsData.cs25
-rw-r--r--OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs116
-rw-r--r--OpenSim/Data/SQLite/SQLiteSimulationData.cs25
-rw-r--r--OpenSim/Data/SQLite/SQLiteUserAccountData.cs25
-rw-r--r--OpenSim/Data/SQLite/SQLiteXInventoryData.cs182
-rw-r--r--OpenSim/Framework/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Framework/AssetPermissions.cs84
-rw-r--r--OpenSim/Framework/AvatarAppearance.cs3
-rw-r--r--OpenSim/Framework/Cache.cs83
-rw-r--r--OpenSim/Framework/ChildAgentDataUpdate.cs18
-rw-r--r--OpenSim/Framework/Client/IClientChat.cs7
-rw-r--r--OpenSim/Framework/Communications/Properties/AssemblyInfo.cs8
-rw-r--r--OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Framework/Console/AssemblyInfo.cs4
-rw-r--r--OpenSim/Framework/Console/CommandConsole.cs36
-rwxr-xr-xOpenSim/Framework/Console/ConsoleBase.cs10
-rw-r--r--OpenSim/Framework/Console/ConsoleUtil.cs228
-rw-r--r--OpenSim/Framework/Console/MockConsole.cs7
-rw-r--r--OpenSim/Framework/Constants.cs1
-rw-r--r--OpenSim/Framework/EstateSettings.cs10
-rw-r--r--OpenSim/Framework/GridInstantMessage.cs9
-rw-r--r--OpenSim/Framework/IClientAPI.cs50
-rw-r--r--OpenSim/Framework/ICommandConsole.cs5
-rw-r--r--OpenSim/Framework/IConsole.cs2
-rw-r--r--OpenSim/Framework/IMoneyModule.cs2
-rw-r--r--OpenSim/Framework/InventoryFolderBase.cs18
-rw-r--r--OpenSim/Framework/InventoryItemBase.cs22
-rw-r--r--OpenSim/Framework/LandData.cs385
-rw-r--r--OpenSim/Framework/Monitoring/BaseStatsCollector.cs23
-rw-r--r--OpenSim/Framework/Monitoring/MemoryWatchdog.cs10
-rw-r--r--OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs19
-rw-r--r--OpenSim/Framework/Monitoring/Stats/PercentageStat.cs88
-rw-r--r--OpenSim/Framework/Monitoring/Stats/Stat.cs238
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs239
-rw-r--r--OpenSim/Framework/Monitoring/Watchdog.cs39
-rw-r--r--OpenSim/Framework/Pool.cs (renamed from OpenSim/Services/InventoryService/InventoryServiceBase.cs)89
-rw-r--r--OpenSim/Framework/RegionFlags.cs53
-rw-r--r--OpenSim/Framework/RegionInfo.cs72
-rw-r--r--OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Framework/Serialization/ArchiveConstants.cs5
-rw-r--r--OpenSim/Framework/Serialization/External/OspResolver.cs14
-rw-r--r--OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs431
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs277
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs22
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs3
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Framework/Servers/MainServer.cs148
-rw-r--r--OpenSim/Framework/Servers/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs566
-rw-r--r--OpenSim/Framework/Servers/VersionInfo.cs2
-rw-r--r--OpenSim/Framework/TaskInventoryDictionary.cs4
-rw-r--r--OpenSim/Framework/TaskInventoryItem.cs19
-rw-r--r--OpenSim/Framework/Util.cs51
-rw-r--r--OpenSim/Framework/WebUtil.cs81
-rw-r--r--OpenSim/Region/Application/ConfigurationLoader.cs1
-rw-r--r--OpenSim/Region/Application/OpenSim.cs326
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs233
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs96
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs446
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs190
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs117
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs6
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs7
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs198
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs468
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs101
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs (renamed from OpenSim/Framework/PacketPool.cs)109
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs7
-rw-r--r--OpenSim/Region/ClientStack/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/ClientStack/RegionApplicationBase.cs2
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs138
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs13
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs253
-rw-r--r--OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs26
-rw-r--r--OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs71
-rw-r--r--OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs33
-rw-r--r--OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs2
-rw-r--r--OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs2
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs51
-rw-r--r--OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs2
-rw-r--r--OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs1
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs36
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs76
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs40
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs38
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs29
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs144
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs61
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs33
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs52
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs50
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs5
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs15
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs43
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs30
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs68
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs290
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs78
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs226
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs79
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs211
-rwxr-xr-xOpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs331
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/InterGrid/OGSRadmin.cs150
-rw-r--r--OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs1297
-rw-r--r--OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs38
-rw-r--r--OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml90
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs61
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs315
-rw-r--r--OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs110
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs34
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs22
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs87
-rw-r--r--OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs (renamed from OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs)99
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs281
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs213
-rw-r--r--OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs375
-rw-r--r--OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs82
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs28
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs9
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs136
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/RemoteAuthenticationServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/LocalAuthorizationServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/RemoteAvatarServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs10
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs19
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs48
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs5
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/RemoteNeighourServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs137
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs113
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs91
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs3
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs12
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs8
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Access/AccessModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs434
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs176
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs634
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs153
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs438
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs27
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs232
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs404
-rw-r--r--OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs57
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs28
-rw-r--r--OpenSim/Region/CoreModules/World/Land/DwellModule.cs112
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/LightShare/EnvironmentModule.cs (renamed from OpenSim/Region/CoreModules/LightShare/EnvironmentModule.cs)20
-rw-r--r--OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs (renamed from OpenSim/Region/CoreModules/LightShare/LightShareModule.cs)125
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs522
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs267
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs313
-rw-r--r--OpenSim/Region/CoreModules/World/Sun/SunModule.cs64
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs63
-rw-r--r--OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/WindModule.cs183
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs68
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs2
-rw-r--r--OpenSim/Region/DataSnapshot/DataSnapshotManager.cs168
-rw-r--r--OpenSim/Region/DataSnapshot/Interfaces/IDataSnapshot.cs1
-rw-r--r--OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/ICloudModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IDialogModule.cs157
-rw-r--r--OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs69
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ILightShareModule.cs (renamed from OpenSim/Region/Framework/Interfaces/IRegionModule.cs)26
-rw-r--r--OpenSim/Region/Framework/Interfaces/INPCModule.cs114
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs73
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISoundModule.cs93
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISunModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUrlModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserManagement.cs29
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWindModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWorldComm.cs26
-rw-r--r--OpenSim/Region/Framework/ModuleLoader.cs263
-rw-r--r--OpenSim/Region/Framework/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs13
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs534
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs22
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs699
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs80
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs35
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs62
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs106
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs302
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs58
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs99
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs35
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs (renamed from OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs)37
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs90
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs36
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs138
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs54
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs13
-rw-r--r--OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs3
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs18
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs6
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs7
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs88
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs33
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Example/BareBonesShared/BareBonesSharedModule.cs3
-rw-r--r--OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs37
-rw-r--r--OpenSim/Region/OptionalModules/Resources/OptionalModules.addin.xml18
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs16
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs91
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs7
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs36
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs49
-rw-r--r--OpenSim/Region/OptionalModules/ServiceConnectorsIn/Freeswitch/FreeswitchServiceInConnectorModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs26
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs124
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs11
-rw-r--r--OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs33
-rw-r--r--OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs2
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs4
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs717
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs51
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs (renamed from OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs)67
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs (renamed from OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs)112
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs1169
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs437
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs275
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs327
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs104
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs263
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs4
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs1392
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs1000
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs1001
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapes.cs208
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs170
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs419
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs256
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs791
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/Manager/AssemblyInfo.cs4
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsActor.cs6
-rw-r--r--OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs4
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs20
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs25
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs17
-rw-r--r--OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs4
-rw-r--r--OpenSim/Region/Physics/UbitMeshing/Mesh.cs23
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs377
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs12
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs69
-rw-r--r--OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs23
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs2
-rw-r--r--OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml14
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs7
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs1636
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs40
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs439
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs139
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs64
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs56
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs28
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs77
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/ScriptException.cs44
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs134
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs70
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs184
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/EventManager.cs29
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs57
-rw-r--r--OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Region/UserStatistics/WebStatsModule.cs225
-rw-r--r--OpenSim/Server/Base/HttpServerBase.cs2
-rw-r--r--OpenSim/Server/Base/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Server/Base/ServicesServerBase.cs138
-rw-r--r--OpenSim/Server/Handlers/Asset/AssetServerConnector.cs20
-rw-r--r--OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs47
-rw-r--r--OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs15
-rw-r--r--OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs110
-rw-r--r--OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs18
-rw-r--r--OpenSim/Server/Handlers/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Server/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Server/ServerMain.cs22
-rw-r--r--OpenSim/Services/AssetService/AssetService.cs17
-rw-r--r--OpenSim/Services/AssetService/AssetServiceBase.cs4
-rw-r--r--OpenSim/Services/AssetService/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/AssetService/XAssetService.cs18
-rw-r--r--OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/Base/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs8
-rw-r--r--OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs6
-rw-r--r--OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs9
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs2
-rw-r--r--OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs8
-rw-r--r--OpenSim/Services/Connectors/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs2
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs2
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs2
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs8
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs3
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs2
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs2
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs2
-rw-r--r--OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/Friends/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/GridService/GridService.cs99
-rw-r--r--OpenSim/Services/GridService/HypergridLinker.cs6
-rw-r--r--OpenSim/Services/GridService/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/HypergridService/GatekeeperService.cs116
-rw-r--r--OpenSim/Services/HypergridService/HGAssetService.cs26
-rw-r--r--OpenSim/Services/HypergridService/HGFriendsService.cs2
-rw-r--r--OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs76
-rw-r--r--OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/HypergridService/UserAgentService.cs105
-rw-r--r--OpenSim/Services/Interfaces/IAssetService.cs6
-rw-r--r--OpenSim/Services/Interfaces/IGridService.cs13
-rw-r--r--OpenSim/Services/Interfaces/IGridUserService.cs3
-rw-r--r--OpenSim/Services/Interfaces/IPresenceService.cs38
-rw-r--r--OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/InventoryService/InventoryService.cs700
-rw-r--r--OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/InventoryService/Tests/XInventoryServiceTests.cs177
-rw-r--r--OpenSim/Services/InventoryService/XInventoryService.cs116
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginService.cs2
-rw-r--r--OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/UserAccountService/GridUserService.cs13
-rw-r--r--OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Tests/Common/Helpers/SceneHelpers.cs44
-rw-r--r--OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs4
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs24
-rw-r--r--OpenSim/Tests/Common/Mock/TestScene.cs6
-rw-r--r--OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs132
-rw-r--r--OpenSim/Tests/Common/TestHelpers.cs1
-rw-r--r--OpenSim/Tests/Performance/NPCPerformanceTests.cs (renamed from OpenSim/Tests/Torture/NPCTortureTests.cs)6
-rw-r--r--OpenSim/Tests/Performance/ObjectPerformanceTests.cs (renamed from OpenSim/Tests/Torture/ObjectTortureTests.cs)6
-rw-r--r--OpenSim/Tests/Performance/ScriptPerformanceTests.cs (renamed from OpenSim/Tests/Torture/ScriptTortureTests.cs)6
-rw-r--r--OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs132
-rw-r--r--OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Tools/Configger/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs33
475 files changed, 26841 insertions, 12743 deletions
diff --git a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs
index 0065702..fcb6991 100644
--- a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs
+++ b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs
@@ -99,12 +99,12 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
99 RegionInfo[] regionsToLoad = regionLoader.LoadRegions(); 99 RegionInfo[] regionsToLoad = regionLoader.LoadRegions();
100 100
101 m_log.Info("[LOAD REGIONS PLUGIN]: Loading specific shared modules..."); 101 m_log.Info("[LOAD REGIONS PLUGIN]: Loading specific shared modules...");
102 m_log.Info("[LOAD REGIONS PLUGIN]: DynamicTextureModule..."); 102 //m_log.Info("[LOAD REGIONS PLUGIN]: DynamicTextureModule...");
103 m_openSim.ModuleLoader.LoadDefaultSharedModule(new DynamicTextureModule()); 103 //m_openSim.ModuleLoader.LoadDefaultSharedModule(new DynamicTextureModule());
104 m_log.Info("[LOAD REGIONS PLUGIN]: LoadImageURLModule..."); 104 //m_log.Info("[LOAD REGIONS PLUGIN]: LoadImageURLModule...");
105 m_openSim.ModuleLoader.LoadDefaultSharedModule(new LoadImageURLModule()); 105 //m_openSim.ModuleLoader.LoadDefaultSharedModule(new LoadImageURLModule());
106 m_log.Info("[LOAD REGIONS PLUGIN]: XMLRPCModule..."); 106 //m_log.Info("[LOAD REGIONS PLUGIN]: XMLRPCModule...");
107 m_openSim.ModuleLoader.LoadDefaultSharedModule(new XMLRPCModule()); 107 //m_openSim.ModuleLoader.LoadDefaultSharedModule(new XMLRPCModule());
108// m_log.Info("[LOADREGIONSPLUGIN]: AssetTransactionModule..."); 108// m_log.Info("[LOADREGIONSPLUGIN]: AssetTransactionModule...");
109// m_openSim.ModuleLoader.LoadDefaultSharedModule(new AssetTransactionModule()); 109// m_openSim.ModuleLoader.LoadDefaultSharedModule(new AssetTransactionModule());
110 m_log.Info("[LOAD REGIONS PLUGIN]: Done."); 110 m_log.Info("[LOAD REGIONS PLUGIN]: Done.");
@@ -136,9 +136,6 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
136 } 136 }
137 } 137 }
138 } 138 }
139
140 m_openSim.ModuleLoader.PostInitialise();
141 m_openSim.ModuleLoader.ClearCache();
142 } 139 }
143 140
144 public void Dispose() 141 public void Dispose()
diff --git a/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
index 59b8dda..57615ea 100644
--- a/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
+++ b/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
@@ -60,7 +60,7 @@ using System.Runtime.InteropServices;
60// 60//
61// You can specify all the values or you can default the Build and Revision Numbers 61// You can specify all the values or you can default the Build and Revision Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63// [assembly: AssemblyVersion("0.6.5.*")] 63// [assembly: AssemblyVersion("0.7.5.*")]
64 64
65[assembly : AssemblyVersion("0.6.5.*")] 65[assembly : AssemblyVersion("0.7.5.*")]
66[assembly : AssemblyFileVersion("0.6.5.0")] \ No newline at end of file 66[assembly : AssemblyFileVersion("0.6.5.0")] \ No newline at end of file
diff --git a/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..14527d9
--- /dev/null
+++ b/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.ApplicationPlugins.RegionModulesController")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("c023816d-194e-40c1-9195-a0f281d4ac5d")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs b/OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs
index 49bd911..633d005 100644
--- a/OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs
@@ -215,7 +215,7 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
215 } 215 }
216 } 216 }
217 217
218#region IRegionModulesController implementation 218#region Region Module interfacesController implementation
219 219
220 /// <summary> 220 /// <summary>
221 /// Check that the given module is no disabled in the [Modules] section of the config files. 221 /// Check that the given module is no disabled in the [Modules] section of the config files.
diff --git a/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8ad948c
--- /dev/null
+++ b/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.ApplicationPlugins.RemoteController")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("Copyright OpenSimulator developers © 2012")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("efec6e69-fc4a-4e21-86e6-4a261c12d4db")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index 437d150..3d80eb6 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
@@ -696,7 +696,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
696 696
697 region.ExternalHostName = (string) requestData["external_address"]; 697 region.ExternalHostName = (string) requestData["external_address"];
698 698
699 bool persist = Convert.ToBoolean((string) requestData["persist"]); 699 bool persist = Convert.ToBoolean(requestData["persist"]);
700 if (persist) 700 if (persist)
701 { 701 {
702 // default place for region configuration files is in the 702 // default place for region configuration files is in the
@@ -852,7 +852,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
852 responseData["success"] = true; 852 responseData["success"] = true;
853 responseData["region_name"] = region.RegionName; 853 responseData["region_name"] = region.RegionName;
854 responseData["region_id"] = region.RegionID.ToString(); 854 responseData["region_id"] = region.RegionID.ToString();
855 responseData["region_uuid"] = region.RegionID.ToString(); //Deprecate July 2012
856 855
857 m_log.Info("[RADMIN]: CreateRegion: request complete"); 856 m_log.Info("[RADMIN]: CreateRegion: request complete");
858 } 857 }
@@ -1106,8 +1105,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1106 string lastName = (string) requestData["user_lastname"]; 1105 string lastName = (string) requestData["user_lastname"];
1107 string password = (string) requestData["user_password"]; 1106 string password = (string) requestData["user_password"];
1108 1107
1109 uint regionXLocation = Convert.ToUInt32((Int32) requestData["start_region_x"]); 1108 uint regionXLocation = Convert.ToUInt32(requestData["start_region_x"]);
1110 uint regionYLocation = Convert.ToUInt32((Int32) requestData["start_region_y"]); 1109 uint regionYLocation = Convert.ToUInt32(requestData["start_region_y"]);
1111 1110
1112 string email = ""; // empty string for email 1111 string email = ""; // empty string for email
1113 if (requestData.Contains("user_email")) 1112 if (requestData.Contains("user_email"))
@@ -1304,9 +1303,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1304 1303
1305 if (requestData.ContainsKey("user_password")) password = (string) requestData["user_password"]; 1304 if (requestData.ContainsKey("user_password")) password = (string) requestData["user_password"];
1306 if (requestData.ContainsKey("start_region_x")) 1305 if (requestData.ContainsKey("start_region_x"))
1307 regionXLocation = Convert.ToUInt32((Int32) requestData["start_region_x"]); 1306 regionXLocation = Convert.ToUInt32(requestData["start_region_x"]);
1308 if (requestData.ContainsKey("start_region_y")) 1307 if (requestData.ContainsKey("start_region_y"))
1309 regionYLocation = Convert.ToUInt32((Int32) requestData["start_region_y"]); 1308 regionYLocation = Convert.ToUInt32(requestData["start_region_y"]);
1310 1309
1311 // if (requestData.ContainsKey("start_lookat_x")) 1310 // if (requestData.ContainsKey("start_lookat_x"))
1312 // ulaX = Convert.ToUInt32((Int32) requestData["start_lookat_x"]); 1311 // ulaX = Convert.ToUInt32((Int32) requestData["start_lookat_x"]);
@@ -1493,6 +1492,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1493 /// <description>profile url</description></item> 1492 /// <description>profile url</description></item>
1494 /// <item><term>noassets</term> 1493 /// <item><term>noassets</term>
1495 /// <description>true if no assets should be saved</description></item> 1494 /// <description>true if no assets should be saved</description></item>
1495 /// <item><term>all</term>
1496 /// <description>true to save all the regions in the simulator</description></item>
1496 /// <item><term>perm</term> 1497 /// <item><term>perm</term>
1497 /// <description>C and/or T</description></item> 1498 /// <description>C and/or T</description></item>
1498 /// </list> 1499 /// </list>
@@ -1549,6 +1550,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1549 options["checkPermissions"] = (string)requestData["perm"]; 1550 options["checkPermissions"] = (string)requestData["perm"];
1550 } 1551 }
1551 1552
1553 if ((string)requestData["all"] == "true")
1554 {
1555 options["all"] = (string)requestData["all"];
1556 }
1557
1552 IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>(); 1558 IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
1553 1559
1554 if (archiver != null) 1560 if (archiver != null)
@@ -2008,29 +2014,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2008 { 2014 {
2009 return; 2015 return;
2010 } 2016 }
2011 #region Deprecate July 2012
2012 //region_ID, regionid, region_uuid will be deprecated in July 2012!!!!!!
2013 else if (requestData.ContainsKey("regionid") &&
2014 !String.IsNullOrEmpty((string)requestData["regionid"]))
2015 {
2016 m_log.WarnFormat("[RADMIN]: Use of parameter regionid will be deprecated as of July 2012. Use region_id instead");
2017 }
2018 else if (requestData.ContainsKey("region_ID") &&
2019 !String.IsNullOrEmpty((string)requestData["region_ID"]))
2020 {
2021 m_log.WarnFormat("[RADMIN]: Use of parameter region_ID will be deprecated as of July 2012. Use region_id instead");
2022 }
2023 else if (requestData.ContainsKey("regionID") &&
2024 !String.IsNullOrEmpty((string)requestData["regionID"]))
2025 {
2026 m_log.WarnFormat("[RADMIN]: Use of parameter regionID will be deprecated as of July 2012. Use region_id instead");
2027 }
2028 else if (requestData.ContainsKey("region_uuid") &&
2029 !String.IsNullOrEmpty((string)requestData["region_uuid"]))
2030 {
2031 m_log.WarnFormat("[RADMIN]: Use of parameter region_uuid will be deprecated as of July 2012. Use region_id instead");
2032 }
2033 #endregion
2034 else 2017 else
2035 { 2018 {
2036 responseData["accepted"] = false; 2019 responseData["accepted"] = false;
@@ -2052,56 +2035,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2052 throw new Exception(String.Format("Region ID {0} not found", regionID)); 2035 throw new Exception(String.Format("Region ID {0} not found", regionID));
2053 } 2036 }
2054 } 2037 }
2055 #region Deprecate July 2012
2056 else if (requestData.ContainsKey("regionid") &&
2057 !String.IsNullOrEmpty((string)requestData["regionid"]))
2058 {
2059 m_log.WarnFormat("[RADMIN]: Use of parameter regionid will be deprecated as of July 2012. Use region_id instead");
2060
2061 UUID regionID = (UUID)(string)requestData["regionid"];
2062 if (!m_application.SceneManager.TryGetScene(regionID, out scene))
2063 {
2064 responseData["error"] = String.Format("Region ID {0} not found", regionID);
2065 throw new Exception(String.Format("Region ID {0} not found", regionID));
2066 }
2067 }
2068 else if (requestData.ContainsKey("region_ID") &&
2069 !String.IsNullOrEmpty((string)requestData["region_ID"]))
2070 {
2071 m_log.WarnFormat("[RADMIN]: Use of parameter region_ID will be deprecated as of July 2012. Use region_id instead");
2072
2073 UUID regionID = (UUID)(string)requestData["region_ID"];
2074 if (!m_application.SceneManager.TryGetScene(regionID, out scene))
2075 {
2076 responseData["error"] = String.Format("Region ID {0} not found", regionID);
2077 throw new Exception(String.Format("Region ID {0} not found", regionID));
2078 }
2079 }
2080 else if (requestData.ContainsKey("regionID") &&
2081 !String.IsNullOrEmpty((string)requestData["regionID"]))
2082 {
2083 m_log.WarnFormat("[RADMIN]: Use of parameter regionID will be deprecated as of July 2012. Use region_id instead");
2084
2085 UUID regionID = (UUID)(string)requestData["regionID"];
2086 if (!m_application.SceneManager.TryGetScene(regionID, out scene))
2087 {
2088 responseData["error"] = String.Format("Region ID {0} not found", regionID);
2089 throw new Exception(String.Format("Region ID {0} not found", regionID));
2090 }
2091 }
2092 else if (requestData.ContainsKey("region_uuid") &&
2093 !String.IsNullOrEmpty((string)requestData["region_uuid"]))
2094 {
2095 m_log.WarnFormat("[RADMIN]: Use of parameter region_uuid will be deprecated as of July 2012. Use region_id instead");
2096
2097 UUID regionID = (UUID)(string)requestData["region_uuid"];
2098 if (!m_application.SceneManager.TryGetScene(regionID, out scene))
2099 {
2100 responseData["error"] = String.Format("Region ID {0} not found", regionID);
2101 throw new Exception(String.Format("Region ID {0} not found", regionID));
2102 }
2103 }
2104 #endregion
2105 else if (requestData.ContainsKey("region_name") && 2038 else if (requestData.ContainsKey("region_name") &&
2106 !String.IsNullOrEmpty((string)requestData["region_name"])) 2039 !String.IsNullOrEmpty((string)requestData["region_name"]))
2107 { 2040 {
@@ -2515,7 +2448,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2515 destinationItem.Description = item.Description; 2448 destinationItem.Description = item.Description;
2516 destinationItem.InvType = item.InvType; 2449 destinationItem.InvType = item.InvType;
2517 destinationItem.CreatorId = item.CreatorId; 2450 destinationItem.CreatorId = item.CreatorId;
2518 destinationItem.CreatorIdAsUuid = item.CreatorIdAsUuid;
2519 destinationItem.CreatorData = item.CreatorData; 2451 destinationItem.CreatorData = item.CreatorData;
2520 destinationItem.NextPermissions = item.NextPermissions; 2452 destinationItem.NextPermissions = item.NextPermissions;
2521 destinationItem.CurrentPermissions = item.CurrentPermissions; 2453 destinationItem.CurrentPermissions = item.CurrentPermissions;
@@ -2570,7 +2502,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2570 destinationItem.Description = item.Description; 2502 destinationItem.Description = item.Description;
2571 destinationItem.InvType = item.InvType; 2503 destinationItem.InvType = item.InvType;
2572 destinationItem.CreatorId = item.CreatorId; 2504 destinationItem.CreatorId = item.CreatorId;
2573 destinationItem.CreatorIdAsUuid = item.CreatorIdAsUuid;
2574 destinationItem.CreatorData = item.CreatorData; 2505 destinationItem.CreatorData = item.CreatorData;
2575 destinationItem.NextPermissions = item.NextPermissions; 2506 destinationItem.NextPermissions = item.NextPermissions;
2576 destinationItem.CurrentPermissions = item.CurrentPermissions; 2507 destinationItem.CurrentPermissions = item.CurrentPermissions;
@@ -2683,7 +2614,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2683 destinationItem.Description = item.Description; 2614 destinationItem.Description = item.Description;
2684 destinationItem.InvType = item.InvType; 2615 destinationItem.InvType = item.InvType;
2685 destinationItem.CreatorId = item.CreatorId; 2616 destinationItem.CreatorId = item.CreatorId;
2686 destinationItem.CreatorIdAsUuid = item.CreatorIdAsUuid;
2687 destinationItem.CreatorData = item.CreatorData; 2617 destinationItem.CreatorData = item.CreatorData;
2688 destinationItem.NextPermissions = item.NextPermissions; 2618 destinationItem.NextPermissions = item.NextPermissions;
2689 destinationItem.CurrentPermissions = item.CurrentPermissions; 2619 destinationItem.CurrentPermissions = item.CurrentPermissions;
@@ -2989,7 +2919,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2989 inventoryItem.Description = GetStringAttribute(item,"desc",""); 2919 inventoryItem.Description = GetStringAttribute(item,"desc","");
2990 inventoryItem.InvType = GetIntegerAttribute(item,"invtype",-1); 2920 inventoryItem.InvType = GetIntegerAttribute(item,"invtype",-1);
2991 inventoryItem.CreatorId = GetStringAttribute(item,"creatorid",""); 2921 inventoryItem.CreatorId = GetStringAttribute(item,"creatorid","");
2992 inventoryItem.CreatorIdAsUuid = (UUID)GetStringAttribute(item,"creatoruuid","");
2993 inventoryItem.CreatorData = GetStringAttribute(item, "creatordata", ""); 2922 inventoryItem.CreatorData = GetStringAttribute(item, "creatordata", "");
2994 inventoryItem.NextPermissions = GetUnsignedAttribute(perms, "next", 0x7fffffff); 2923 inventoryItem.NextPermissions = GetUnsignedAttribute(perms, "next", 0x7fffffff);
2995 inventoryItem.CurrentPermissions = GetUnsignedAttribute(perms,"current",0x7fffffff); 2924 inventoryItem.CurrentPermissions = GetUnsignedAttribute(perms,"current",0x7fffffff);
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs
index cb88695..072bd6f 100644
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs
@@ -312,14 +312,16 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
312 // Now that everything is setup we can proceed to 312 // Now that everything is setup we can proceed to
313 // add THIS agent to the HTTP server's handler list 313 // add THIS agent to the HTTP server's handler list
314 314
315 if (!AddAgentHandler(Rest.Name,this)) 315 // FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will
316 { 316 // have to be handled through the AddHttpHandler interface.
317 Rest.Log.ErrorFormat("{0} Unable to activate handler interface", MsgId); 317// if (!AddAgentHandler(Rest.Name,this))
318 foreach (IRest handler in handlers) 318// {
319 { 319// Rest.Log.ErrorFormat("{0} Unable to activate handler interface", MsgId);
320 handler.Close(); 320// foreach (IRest handler in handlers)
321 } 321// {
322 } 322// handler.Close();
323// }
324// }
323 325
324 } 326 }
325 catch (Exception e) 327 catch (Exception e)
@@ -342,11 +344,13 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
342 { 344 {
343 Rest.Log.InfoFormat("{0} Plugin is terminating", MsgId); 345 Rest.Log.InfoFormat("{0} Plugin is terminating", MsgId);
344 346
345 try 347 // FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will
346 { 348 // have to be handled through the AddHttpHandler interface.
347 RemoveAgentHandler(Rest.Name, this); 349// try
348 } 350// {
349 catch (KeyNotFoundException){} 351// RemoveAgentHandler(Rest.Name, this);
352// }
353// catch (KeyNotFoundException){}
350 354
351 foreach (IRest handler in handlers) 355 foreach (IRest handler in handlers)
352 { 356 {
diff --git a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs b/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
index eb16750..a2425b5 100644
--- a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
+++ b/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
@@ -297,7 +297,9 @@ namespace OpenSim.ApplicationPlugins.Rest
297 { 297 {
298 if (!IsEnabled) return false; 298 if (!IsEnabled) return false;
299 _agents.Add(agentName, handler); 299 _agents.Add(agentName, handler);
300 return _httpd.AddAgentHandler(agentName, handler); 300// return _httpd.AddAgentHandler(agentName, handler);
301
302 return false;
301 } 303 }
302 304
303 /// <summary> 305 /// <summary>
@@ -316,7 +318,7 @@ namespace OpenSim.ApplicationPlugins.Rest
316 if (_agents[agentName] == handler) 318 if (_agents[agentName] == handler)
317 { 319 {
318 _agents.Remove(agentName); 320 _agents.Remove(agentName);
319 return _httpd.RemoveAgentHandler(agentName, handler); 321// return _httpd.RemoveAgentHandler(agentName, handler);
320 } 322 }
321 return false; 323 return false;
322 } 324 }
@@ -358,10 +360,10 @@ namespace OpenSim.ApplicationPlugins.Rest
358 _httpd.RemoveStreamHandler(h.HttpMethod, h.Path); 360 _httpd.RemoveStreamHandler(h.HttpMethod, h.Path);
359 } 361 }
360 _handlers = null; 362 _handlers = null;
361 foreach (KeyValuePair<string, IHttpAgentHandler> h in _agents) 363// foreach (KeyValuePair<string, IHttpAgentHandler> h in _agents)
362 { 364// {
363 _httpd.RemoveAgentHandler(h.Key, h.Value); 365// _httpd.RemoveAgentHandler(h.Key, h.Value);
364 } 366// }
365 _agents = null; 367 _agents = null;
366 } 368 }
367 369
diff --git a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
index 720640e..ec574a3 100644
--- a/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetMesh/GetMeshHandler.cs
@@ -45,16 +45,54 @@ namespace OpenSim.Capabilities.Handlers
45{ 45{
46 public class GetMeshHandler 46 public class GetMeshHandler
47 { 47 {
48// private static readonly ILog m_log = 48 private static readonly ILog m_log =
49// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 private IAssetService m_assetService; 51 private IAssetService m_assetService;
52 52
53 public const string DefaultFormat = "vnd.ll.mesh";
54
53 public GetMeshHandler(IAssetService assService) 55 public GetMeshHandler(IAssetService assService)
54 { 56 {
55 m_assetService = assService; 57 m_assetService = assService;
56 } 58 }
59 public Hashtable Handle(Hashtable request)
60 {
61 Hashtable ret = new Hashtable();
62 ret["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
63 ret["content_type"] = "text/plain";
64 ret["keepalive"] = false;
65 ret["reusecontext"] = false;
66 ret["int_bytes"] = 0;
67 ret["int_lod"] = 0;
68 string MeshStr = (string)request["mesh_id"];
69
70
71 //m_log.DebugFormat("[GETMESH]: called {0}", MeshStr);
72
73 if (m_assetService == null)
74 {
75 m_log.Error("[GETMESH]: Cannot fetch mesh " + MeshStr + " without an asset service");
76 }
77
78 UUID meshID;
79 if (!String.IsNullOrEmpty(MeshStr) && UUID.TryParse(MeshStr, out meshID))
80 {
81 // m_log.DebugFormat("[GETMESH]: Received request for mesh id {0}", meshID);
57 82
83
84 ret = ProcessGetMesh(request, UUID.Zero, null);
85
86
87 }
88 else
89 {
90 m_log.Warn("[GETMESH]: Failed to parse a mesh_id from GetMesh request: " + (string)request["uri"]);
91 }
92
93
94 return ret;
95 }
58 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap) 96 public Hashtable ProcessGetMesh(Hashtable request, UUID AgentId, Caps cap)
59 { 97 {
60 Hashtable responsedata = new Hashtable(); 98 Hashtable responsedata = new Hashtable();
@@ -62,6 +100,9 @@ namespace OpenSim.Capabilities.Handlers
62 responsedata["content_type"] = "text/plain"; 100 responsedata["content_type"] = "text/plain";
63 responsedata["keepalive"] = false; 101 responsedata["keepalive"] = false;
64 responsedata["str_response_string"] = "Request wasn't what was expected"; 102 responsedata["str_response_string"] = "Request wasn't what was expected";
103 responsedata["reusecontext"] = false;
104 responsedata["int_lod"] = 0;
105 responsedata["int_bytes"] = 0;
65 106
66 string meshStr = string.Empty; 107 string meshStr = string.Empty;
67 108
@@ -77,6 +118,7 @@ namespace OpenSim.Capabilities.Handlers
77 responsedata["content_type"] = "text/plain"; 118 responsedata["content_type"] = "text/plain";
78 responsedata["keepalive"] = false; 119 responsedata["keepalive"] = false;
79 responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh."; 120 responsedata["str_response_string"] = "The asset service is unavailable. So is your mesh.";
121 responsedata["reusecontext"] = false;
80 return responsedata; 122 return responsedata;
81 } 123 }
82 124
@@ -86,9 +128,100 @@ namespace OpenSim.Capabilities.Handlers
86 { 128 {
87 if (mesh.Type == (SByte)AssetType.Mesh) 129 if (mesh.Type == (SByte)AssetType.Mesh)
88 { 130 {
89 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data); 131
90 responsedata["content_type"] = "application/vnd.ll.mesh"; 132 Hashtable headers = new Hashtable();
91 responsedata["int_response_code"] = 200; 133 responsedata["headers"] = headers;
134
135 string range = String.Empty;
136
137 if (((Hashtable)request["headers"])["range"] != null)
138 range = (string)((Hashtable)request["headers"])["range"];
139
140 else if (((Hashtable)request["headers"])["Range"] != null)
141 range = (string)((Hashtable)request["headers"])["Range"];
142
143 if (!String.IsNullOrEmpty(range)) // Mesh Asset LOD // Physics
144 {
145 // Range request
146 int start, end;
147 if (TryParseRange(range, out start, out end))
148 {
149 // Before clamping start make sure we can satisfy it in order to avoid
150 // sending back the last byte instead of an error status
151 if (start >= mesh.Data.Length)
152 {
153 responsedata["int_response_code"] = 404; //501; //410; //404;
154 responsedata["content_type"] = "text/plain";
155 responsedata["keepalive"] = false;
156 responsedata["str_response_string"] = "This range doesnt exist.";
157 responsedata["reusecontext"] = false;
158 responsedata["int_lod"] = 3;
159 return responsedata;
160 }
161 else
162 {
163 end = Utils.Clamp(end, 0, mesh.Data.Length - 1);
164 start = Utils.Clamp(start, 0, end);
165 int len = end - start + 1;
166
167 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
168
169 if (start > 20000)
170 {
171 responsedata["int_lod"] = 3;
172 }
173 else if (start < 4097)
174 {
175 responsedata["int_lod"] = 1;
176 }
177 else
178 {
179 responsedata["int_lod"] = 2;
180 }
181
182
183 if (start == 0 && len == mesh.Data.Length) // well redudante maybe
184 {
185 responsedata["int_response_code"] = (int) System.Net.HttpStatusCode.OK;
186 responsedata["bin_response_data"] = mesh.Data;
187 responsedata["int_bytes"] = mesh.Data.Length;
188 responsedata["reusecontext"] = false;
189 responsedata["int_lod"] = 3;
190
191 }
192 else
193 {
194 responsedata["int_response_code"] =
195 (int) System.Net.HttpStatusCode.PartialContent;
196 headers["Content-Range"] = String.Format("bytes {0}-{1}/{2}", start, end,
197 mesh.Data.Length);
198
199 byte[] d = new byte[len];
200 Array.Copy(mesh.Data, start, d, 0, len);
201 responsedata["bin_response_data"] = d;
202 responsedata["int_bytes"] = len;
203 responsedata["reusecontext"] = false;
204 }
205 }
206 }
207 else
208 {
209 m_log.Warn("[GETMESH]: Failed to parse a range from GetMesh request, sending full asset: " + (string)request["uri"]);
210 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
211 responsedata["content_type"] = "application/vnd.ll.mesh";
212 responsedata["int_response_code"] = 200;
213 responsedata["reusecontext"] = false;
214 responsedata["int_lod"] = 3;
215 }
216 }
217 else
218 {
219 responsedata["str_response_string"] = Convert.ToBase64String(mesh.Data);
220 responsedata["content_type"] = "application/vnd.ll.mesh";
221 responsedata["int_response_code"] = 200;
222 responsedata["reusecontext"] = false;
223 responsedata["int_lod"] = 3;
224 }
92 } 225 }
93 // Optionally add additional mesh types here 226 // Optionally add additional mesh types here
94 else 227 else
@@ -97,6 +230,8 @@ namespace OpenSim.Capabilities.Handlers
97 responsedata["content_type"] = "text/plain"; 230 responsedata["content_type"] = "text/plain";
98 responsedata["keepalive"] = false; 231 responsedata["keepalive"] = false;
99 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh."; 232 responsedata["str_response_string"] = "Unfortunately, this asset isn't a mesh.";
233 responsedata["reusecontext"] = false;
234 responsedata["int_lod"] = 1;
100 return responsedata; 235 return responsedata;
101 } 236 }
102 } 237 }
@@ -106,11 +241,28 @@ namespace OpenSim.Capabilities.Handlers
106 responsedata["content_type"] = "text/plain"; 241 responsedata["content_type"] = "text/plain";
107 responsedata["keepalive"] = false; 242 responsedata["keepalive"] = false;
108 responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!"; 243 responsedata["str_response_string"] = "Your Mesh wasn't found. Sorry!";
244 responsedata["reusecontext"] = false;
245 responsedata["int_lod"] = 0;
109 return responsedata; 246 return responsedata;
110 } 247 }
111 } 248 }
112 249
113 return responsedata; 250 return responsedata;
114 } 251 }
252 private bool TryParseRange(string header, out int start, out int end)
253 {
254 if (header.StartsWith("bytes="))
255 {
256 string[] rangeValues = header.Substring(6).Split('-');
257 if (rangeValues.Length == 2)
258 {
259 if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end))
260 return true;
261 }
262 }
263
264 start = end = 0;
265 return false;
266 }
115 } 267 }
116} \ No newline at end of file 268} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index b3a4d61..6437d0b 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Capabilities.Handlers
68 ret["content_type"] = "text/plain"; 68 ret["content_type"] = "text/plain";
69 ret["keepalive"] = false; 69 ret["keepalive"] = false;
70 ret["reusecontext"] = false; 70 ret["reusecontext"] = false;
71 71 ret["int_bytes"] = 0;
72 string textureStr = (string)request["texture_id"]; 72 string textureStr = (string)request["texture_id"];
73 string format = (string)request["format"]; 73 string format = (string)request["format"];
74 74
@@ -200,11 +200,25 @@ namespace OpenSim.Capabilities.Handlers
200 int start, end; 200 int start, end;
201 if (TryParseRange(range, out start, out end)) 201 if (TryParseRange(range, out start, out end))
202 { 202 {
203
204 // Before clamping start make sure we can satisfy it in order to avoid 203 // Before clamping start make sure we can satisfy it in order to avoid
205 // sending back the last byte instead of an error status 204 // sending back the last byte instead of an error status
206 if (start >= texture.Data.Length) 205 if (start >= texture.Data.Length)
207 { 206 {
207// m_log.DebugFormat(
208// "[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
209// texture.ID, start, texture.Data.Length);
210
211 // Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
212 // Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations
213 // of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously
214 // received a very small texture may attempt to fetch bytes from the server past the
215 // range of data that it received originally. Whether this happens appears to depend on whether
216 // the viewer's estimation of how large a request it needs to make for certain discard levels
217 // (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard
218 // level 2. If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable
219 // here will cause the viewer to treat the texture as bad and never display the full resolution
220 // However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
221
208// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; 222// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
209 // viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters 223 // viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters
210 response["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound; 224 response["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
@@ -215,7 +229,7 @@ namespace OpenSim.Capabilities.Handlers
215 start = Utils.Clamp(start, 0, end); 229 start = Utils.Clamp(start, 0, end);
216 int len = end - start + 1; 230 int len = end - start + 1;
217 231
218 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); 232// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
219 233
220 response["content-type"] = texture.Metadata.ContentType; 234 response["content-type"] = texture.Metadata.ContentType;
221 235
@@ -223,6 +237,7 @@ namespace OpenSim.Capabilities.Handlers
223 { 237 {
224 response["int_response_code"] = (int)System.Net.HttpStatusCode.OK; 238 response["int_response_code"] = (int)System.Net.HttpStatusCode.OK;
225 response["bin_response_data"] = texture.Data; 239 response["bin_response_data"] = texture.Data;
240 response["int_bytes"] = texture.Data.Length;
226 } 241 }
227 else 242 else
228 { 243 {
@@ -232,6 +247,7 @@ namespace OpenSim.Capabilities.Handlers
232 byte[] d = new byte[len]; 247 byte[] d = new byte[len];
233 Array.Copy(texture.Data, start, d, 0, len); 248 Array.Copy(texture.Data, start, d, 0, len);
234 response["bin_response_data"] = d; 249 response["bin_response_data"] = d;
250 response["int_bytes"] = len;
235 } 251 }
236// response.Body.Write(texture.Data, start, len); 252// response.Body.Write(texture.Data, start, len);
237 } 253 }
@@ -252,6 +268,8 @@ namespace OpenSim.Capabilities.Handlers
252 response["content_type"] = "image/" + format; 268 response["content_type"] = "image/" + format;
253 269
254 response["bin_response_data"] = texture.Data; 270 response["bin_response_data"] = texture.Data;
271 response["int_bytes"] = texture.Data.Length;
272
255// response.Body.Write(texture.Data, 0, texture.Data.Length); 273// response.Body.Write(texture.Data, 0, texture.Data.Length);
256 } 274 }
257 275
diff --git a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..a681fb6
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Capabilities.Handlers")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("32350823-e1df-45e3-b7fa-0a58b4372433")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Capabilities/Properties/AssemblyInfo.cs b/OpenSim/Capabilities/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..26254f2
--- /dev/null
+++ b/OpenSim/Capabilities/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Capabilities")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("7d1a55b1-8fab-42ff-9c83-066a9cc34d76")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/ConsoleClient/Properties/AssemblyInfo.cs b/OpenSim/ConsoleClient/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c240f90
--- /dev/null
+++ b/OpenSim/ConsoleClient/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.ConsoleClient")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("8945df94-2e5e-475b-88fa-35a7cdde6fd7")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Data/IRegionData.cs b/OpenSim/Data/IRegionData.cs
index 546b5e8..70e1065 100644
--- a/OpenSim/Data/IRegionData.cs
+++ b/OpenSim/Data/IRegionData.cs
@@ -85,21 +85,6 @@ namespace OpenSim.Data
85 List<RegionData> GetHyperlinks(UUID scopeID); 85 List<RegionData> GetHyperlinks(UUID scopeID);
86 } 86 }
87 87
88 [Flags]
89 public enum RegionFlags : int
90 {
91 DefaultRegion = 1, // Used for new Rez. Random if multiple defined
92 FallbackRegion = 2, // Regions we redirect to when the destination is down
93 RegionOnline = 4, // Set when a region comes online, unset when it unregisters and DeleteOnUnregister is false
94 NoDirectLogin = 8, // Region unavailable for direct logins (by name)
95 Persistent = 16, // Don't remove on unregister
96 LockedOut = 32, // Don't allow registration
97 NoMove = 64, // Don't allow moving this region
98 Reservation = 128, // This is an inactive reservation
99 Authenticate = 256, // Require authentication
100 Hyperlink = 512 // Record represents a HG link
101 }
102
103 public class RegionDataDistanceCompare : IComparer<RegionData> 88 public class RegionDataDistanceCompare : IComparer<RegionData>
104 { 89 {
105 private Vector2 m_origin; 90 private Vector2 m_origin;
diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs
index 85a5c08..ca47506 100644
--- a/OpenSim/Data/IXInventoryData.cs
+++ b/OpenSim/Data/IXInventoryData.cs
@@ -40,6 +40,11 @@ namespace OpenSim.Data
40 public UUID folderID; 40 public UUID folderID;
41 public UUID agentID; 41 public UUID agentID;
42 public UUID parentFolderID; 42 public UUID parentFolderID;
43
44 public XInventoryFolder Clone()
45 {
46 return (XInventoryFolder)MemberwiseClone();
47 }
43 } 48 }
44 49
45 public class XInventoryItem 50 public class XInventoryItem
@@ -64,6 +69,11 @@ namespace OpenSim.Data
64 public UUID avatarID; 69 public UUID avatarID;
65 public UUID parentFolderID; 70 public UUID parentFolderID;
66 public int inventoryGroupPermissions; 71 public int inventoryGroupPermissions;
72
73 public XInventoryItem Clone()
74 {
75 return (XInventoryItem)MemberwiseClone();
76 }
67 } 77 }
68 78
69 public interface IXInventoryData 79 public interface IXInventoryData
@@ -106,7 +116,22 @@ namespace OpenSim.Data
106 /// <returns>true if the delete was successful, false if it was not</returns> 116 /// <returns>true if the delete was successful, false if it was not</returns>
107 bool DeleteItems(string[] fields, string[] vals); 117 bool DeleteItems(string[] fields, string[] vals);
108 118
109 bool MoveItem(string id, string newParent); 119 /// <summary>
120 /// Move an item to another folder.
121 /// </summary>
122 /// <returns>/returns>
123 /// <param name='id'>UUID of the item</param>
124 /// <param name='newParent'>UUID of the new parent folder.</param>
125 bool MoveItem(string id, string newParentFolderID);
126
127 /// <summary>
128 /// Move a folder to another folder.
129 /// </summary>
130 /// <returns>/returns>
131 /// <param name='id'>UUID of the item</param>
132 /// <param name='newParent'>UUID of the new parent folder.</param>
133 bool MoveFolder(string id, string newParentFolderID);
134
110 XInventoryItem[] GetActiveGestures(UUID principalID); 135 XInventoryItem[] GetActiveGestures(UUID principalID);
111 int GetAssetPermissions(UUID principalID, UUID assetID); 136 int GetAssetPermissions(UUID principalID, UUID assetID);
112 } 137 }
diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
index 3ae87c3..0d89706 100644
--- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
@@ -37,6 +37,7 @@ using OpenMetaverse;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
40using RegionFlags = OpenSim.Framework.RegionFlags;
40 41
41namespace OpenSim.Data.MSSQL 42namespace OpenSim.Data.MSSQL
42{ 43{
diff --git a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs
index a1069c6..e261aba 100644
--- a/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLXInventoryData.cs
@@ -43,12 +43,12 @@ namespace OpenSim.Data.MSSQL
43 private static readonly ILog m_log = LogManager.GetLogger( 43 private static readonly ILog m_log = LogManager.GetLogger(
44 MethodBase.GetCurrentMethod().DeclaringType); 44 MethodBase.GetCurrentMethod().DeclaringType);
45 45
46 private MSSQLGenericTableHandler<XInventoryFolder> m_Folders; 46 private MSSQLFolderHandler m_Folders;
47 private MSSQLItemHandler m_Items; 47 private MSSQLItemHandler m_Items;
48 48
49 public MSSQLXInventoryData(string conn, string realm) 49 public MSSQLXInventoryData(string conn, string realm)
50 { 50 {
51 m_Folders = new MSSQLGenericTableHandler<XInventoryFolder>( 51 m_Folders = new MSSQLFolderHandler(
52 conn, "inventoryfolders", "InventoryStore"); 52 conn, "inventoryfolders", "InventoryStore");
53 m_Items = new MSSQLItemHandler( 53 m_Items = new MSSQLItemHandler(
54 conn, "inventoryitems", String.Empty); 54 conn, "inventoryitems", String.Empty);
@@ -85,6 +85,7 @@ namespace OpenSim.Data.MSSQL
85 { 85 {
86 return m_Folders.Delete(field, val); 86 return m_Folders.Delete(field, val);
87 } 87 }
88
88 public bool DeleteFolders(string[] fields, string[] vals) 89 public bool DeleteFolders(string[] fields, string[] vals)
89 { 90 {
90 return m_Folders.Delete(fields, vals); 91 return m_Folders.Delete(fields, vals);
@@ -94,15 +95,22 @@ namespace OpenSim.Data.MSSQL
94 { 95 {
95 return m_Items.Delete(field, val); 96 return m_Items.Delete(field, val);
96 } 97 }
98
97 public bool DeleteItems(string[] fields, string[] vals) 99 public bool DeleteItems(string[] fields, string[] vals)
98 { 100 {
99 return m_Items.Delete(fields, vals); 101 return m_Items.Delete(fields, vals);
100 } 102 }
103
101 public bool MoveItem(string id, string newParent) 104 public bool MoveItem(string id, string newParent)
102 { 105 {
103 return m_Items.MoveItem(id, newParent); 106 return m_Items.MoveItem(id, newParent);
104 } 107 }
105 108
109 public bool MoveFolder(string id, string newParent)
110 {
111 return m_Folders.MoveFolder(id, newParent);
112 }
113
106 public XInventoryItem[] GetActiveGestures(UUID principalID) 114 public XInventoryItem[] GetActiveGestures(UUID principalID)
107 { 115 {
108 return m_Items.GetActiveGestures(principalID); 116 return m_Items.GetActiveGestures(principalID);
@@ -114,7 +122,7 @@ namespace OpenSim.Data.MSSQL
114 } 122 }
115 } 123 }
116 124
117 public class MSSQLItemHandler : MSSQLGenericTableHandler<XInventoryItem> 125 public class MSSQLItemHandler : MSSQLInventoryHandler<XInventoryItem>
118 { 126 {
119 public MSSQLItemHandler(string c, string t, string m) : 127 public MSSQLItemHandler(string c, string t, string m) :
120 base(c, t, m) 128 base(c, t, m)
@@ -123,70 +131,163 @@ namespace OpenSim.Data.MSSQL
123 131
124 public bool MoveItem(string id, string newParent) 132 public bool MoveItem(string id, string newParent)
125 { 133 {
134 XInventoryItem[] retrievedItems = Get(new string[] { "inventoryID" }, new string[] { id });
135 if (retrievedItems.Length == 0)
136 return false;
137
138 UUID oldParent = retrievedItems[0].parentFolderID;
139
126 using (SqlConnection conn = new SqlConnection(m_ConnectionString)) 140 using (SqlConnection conn = new SqlConnection(m_ConnectionString))
127 using (SqlCommand cmd = new SqlCommand())
128 { 141 {
142 using (SqlCommand cmd = new SqlCommand())
143 {
144
145 cmd.CommandText = String.Format("update {0} set parentFolderID = @ParentFolderID where inventoryID = @InventoryID", m_Realm);
146 cmd.Parameters.Add(m_database.CreateParameter("@ParentFolderID", newParent));
147 cmd.Parameters.Add(m_database.CreateParameter("@InventoryID", id));
148 cmd.Connection = conn;
149 conn.Open();
129 150
130 cmd.CommandText = String.Format("update {0} set parentFolderID = @ParentFolderID where inventoryID = @InventoryID", m_Realm); 151 if (cmd.ExecuteNonQuery() == 0)
131 cmd.Parameters.Add(m_database.CreateParameter("@ParentFolderID", newParent)); 152 return false;
132 cmd.Parameters.Add(m_database.CreateParameter("@InventoryID", id)); 153 }
133 cmd.Connection = conn;
134 conn.Open();
135 return cmd.ExecuteNonQuery() == 0 ? false : true;
136 } 154 }
155
156 IncrementFolderVersion(oldParent);
157 IncrementFolderVersion(newParent);
158
159 return true;
137 } 160 }
138 161
139 public XInventoryItem[] GetActiveGestures(UUID principalID) 162 public XInventoryItem[] GetActiveGestures(UUID principalID)
140 { 163 {
141 using (SqlConnection conn = new SqlConnection(m_ConnectionString)) 164 using (SqlConnection conn = new SqlConnection(m_ConnectionString))
142 using (SqlCommand cmd = new SqlCommand())
143 { 165 {
144 cmd.CommandText = String.Format("select * from inventoryitems where avatarId = @uuid and assetType = @type and flags = 1", m_Realm); 166 using (SqlCommand cmd = new SqlCommand())
167 {
168 cmd.CommandText = String.Format("select * from inventoryitems where avatarId = @uuid and assetType = @type and flags = 1", m_Realm);
145 169
146 cmd.Parameters.Add(m_database.CreateParameter("@uuid", principalID.ToString())); 170 cmd.Parameters.Add(m_database.CreateParameter("@uuid", principalID.ToString()));
147 cmd.Parameters.Add(m_database.CreateParameter("@type", (int)AssetType.Gesture)); 171 cmd.Parameters.Add(m_database.CreateParameter("@type", (int)AssetType.Gesture));
148 cmd.Connection = conn; 172 cmd.Connection = conn;
149 conn.Open(); 173 conn.Open();
150 return DoQuery(cmd); 174 return DoQuery(cmd);
175 }
151 } 176 }
152 } 177 }
153 178
154 public int GetAssetPermissions(UUID principalID, UUID assetID) 179 public int GetAssetPermissions(UUID principalID, UUID assetID)
155 { 180 {
156 using (SqlConnection conn = new SqlConnection(m_ConnectionString)) 181 using (SqlConnection conn = new SqlConnection(m_ConnectionString))
157 using (SqlCommand cmd = new SqlCommand())
158 { 182 {
159 cmd.CommandText = String.Format("select bit_or(inventoryCurrentPermissions) as inventoryCurrentPermissions from inventoryitems where avatarID = @PrincipalID and assetID = @AssetID group by assetID", m_Realm); 183 using (SqlCommand cmd = new SqlCommand())
160 cmd.Parameters.Add(m_database.CreateParameter("@PrincipalID", principalID.ToString()));
161 cmd.Parameters.Add(m_database.CreateParameter("@AssetID", assetID.ToString()));
162 cmd.Connection = conn;
163 conn.Open();
164 using (SqlDataReader reader = cmd.ExecuteReader())
165 { 184 {
185 cmd.CommandText = String.Format("select bit_or(inventoryCurrentPermissions) as inventoryCurrentPermissions from inventoryitems where avatarID = @PrincipalID and assetID = @AssetID group by assetID", m_Realm);
186 cmd.Parameters.Add(m_database.CreateParameter("@PrincipalID", principalID.ToString()));
187 cmd.Parameters.Add(m_database.CreateParameter("@AssetID", assetID.ToString()));
188 cmd.Connection = conn;
189 conn.Open();
190 using (SqlDataReader reader = cmd.ExecuteReader())
191 {
166 192
167 int perms = 0; 193 int perms = 0;
168 194
169 if (reader.Read()) 195 if (reader.Read())
170 { 196 {
171 perms = Convert.ToInt32(reader["inventoryCurrentPermissions"]); 197 perms = Convert.ToInt32(reader["inventoryCurrentPermissions"]);
198 }
199
200 return perms;
172 } 201 }
173 202
174 return perms;
175 } 203 }
176
177 } 204 }
178 } 205 }
206
179 public override bool Store(XInventoryItem item) 207 public override bool Store(XInventoryItem item)
180 { 208 {
181 if (!base.Store(item)) 209 if (!base.Store(item))
182 return false; 210 return false;
183 string sql = "update inventoryfolders set version=version+1 where folderID = @folderID"; 211
212 IncrementFolderVersion(item.parentFolderID);
213
214 return true;
215 }
216 }
217
218 public class MSSQLFolderHandler : MSSQLInventoryHandler<XInventoryFolder>
219 {
220 public MSSQLFolderHandler(string c, string t, string m) :
221 base(c, t, m)
222 {
223 }
224
225 public bool MoveFolder(string id, string newParentFolderID)
226 {
227 XInventoryFolder[] folders = Get(new string[] { "folderID" }, new string[] { id });
228
229 if (folders.Length == 0)
230 return false;
231
232 UUID oldParentFolderUUID = folders[0].parentFolderID;
233
234 using (SqlConnection conn = new SqlConnection(m_ConnectionString))
235 {
236 using (SqlCommand cmd = new SqlCommand())
237 {
238
239 cmd.CommandText = String.Format("update {0} set parentFolderID = @ParentFolderID where folderID = @folderID", m_Realm);
240 cmd.Parameters.Add(m_database.CreateParameter("@ParentFolderID", newParentFolderID));
241 cmd.Parameters.Add(m_database.CreateParameter("@folderID", id));
242 cmd.Connection = conn;
243 conn.Open();
244
245 if (cmd.ExecuteNonQuery() == 0)
246 return false;
247 }
248 }
249
250 IncrementFolderVersion(oldParentFolderUUID);
251 IncrementFolderVersion(newParentFolderID);
252
253 return true;
254 }
255
256 public override bool Store(XInventoryFolder folder)
257 {
258 if (!base.Store(folder))
259 return false;
260
261 IncrementFolderVersion(folder.parentFolderID);
262
263 return true;
264 }
265 }
266
267 public class MSSQLInventoryHandler<T> : MSSQLGenericTableHandler<T> where T: class, new()
268 {
269 public MSSQLInventoryHandler(string c, string t, string m) : base(c, t, m) {}
270
271 protected bool IncrementFolderVersion(UUID folderID)
272 {
273 return IncrementFolderVersion(folderID.ToString());
274 }
275
276 protected bool IncrementFolderVersion(string folderID)
277 {
278// m_log.DebugFormat("[MYSQL ITEM HANDLER]: Incrementing version on folder {0}", folderID);
279// Util.PrintCallStack();
280
281 string sql = "update inventoryfolders set version=version+1 where folderID = ?folderID";
282
184 using (SqlConnection conn = new SqlConnection(m_ConnectionString)) 283 using (SqlConnection conn = new SqlConnection(m_ConnectionString))
185 using (SqlCommand cmd = new SqlCommand(sql, conn))
186 { 284 {
187 conn.Open(); 285 using (SqlCommand cmd = new SqlCommand(sql, conn))
286 {
287 conn.Open();
288
289 cmd.Parameters.AddWithValue("@folderID", folderID);
188 290
189 cmd.Parameters.AddWithValue("@folderID", item.parentFolderID.ToString());
190 try 291 try
191 { 292 {
192 cmd.ExecuteNonQuery(); 293 cmd.ExecuteNonQuery();
@@ -194,9 +295,11 @@ namespace OpenSim.Data.MSSQL
194 catch (Exception) 295 catch (Exception)
195 { 296 {
196 return false; 297 return false;
197 } 298 }
299 }
198 } 300 }
301
199 return true; 302 return true;
200 } 303 }
201 } 304 }
202} 305} \ No newline at end of file
diff --git a/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs b/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs
index e045d75..1a67e70 100644
--- a/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.6.5.*")] 64[assembly : AssemblyVersion("0.7.5.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65[assembly : AssemblyFileVersion("0.6.5.0")]
diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
index 86367a1..f6731c0 100644
--- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
+++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
@@ -224,6 +224,8 @@ namespace OpenSim.Data.MySQL
224 224
225 public virtual bool Store(T row) 225 public virtual bool Store(T row)
226 { 226 {
227// m_log.DebugFormat("[MYSQL GENERIC TABLE HANDLER]: Store(T row) invoked");
228
227 using (MySqlCommand cmd = new MySqlCommand()) 229 using (MySqlCommand cmd = new MySqlCommand())
228 { 230 {
229 string query = ""; 231 string query = "";
@@ -278,6 +280,10 @@ namespace OpenSim.Data.MySQL
278 280
279 public virtual bool Delete(string[] fields, string[] keys) 281 public virtual bool Delete(string[] fields, string[] keys)
280 { 282 {
283// m_log.DebugFormat(
284// "[MYSQL GENERIC TABLE HANDLER]: Delete(string[] fields, string[] keys) invoked with {0}:{1}",
285// string.Join(",", fields), string.Join(",", keys));
286
281 if (fields.Length != keys.Length) 287 if (fields.Length != keys.Length)
282 return false; 288 return false;
283 289
diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs
index 0614879..a2d4ae4 100644
--- a/OpenSim/Data/MySQL/MySQLRegionData.cs
+++ b/OpenSim/Data/MySQL/MySQLRegionData.cs
@@ -30,11 +30,11 @@ using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Data; 31using System.Data;
32using System.Reflection; 32using System.Reflection;
33 33using MySql.Data.MySqlClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Data; 36using OpenSim.Data;
37using MySql.Data.MySqlClient; 37using RegionFlags = OpenSim.Framework.RegionFlags;
38 38
39namespace OpenSim.Data.MySQL 39namespace OpenSim.Data.MySQL
40{ 40{
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index 4d7c0c9..12c979a 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -747,95 +747,99 @@ namespace OpenSim.Data.MySQL
747 RegionLightShareData nWP = new RegionLightShareData(); 747 RegionLightShareData nWP = new RegionLightShareData();
748 nWP.OnSave += StoreRegionWindlightSettings; 748 nWP.OnSave += StoreRegionWindlightSettings;
749 749
750 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 750 lock (m_dbLock)
751 { 751 {
752 dbcon.Open(); 752 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
753
754 string command = "select * from `regionwindlight` where region_id = ?regionID";
755
756 using (MySqlCommand cmd = new MySqlCommand(command))
757 { 753 {
758 cmd.Connection = dbcon; 754 dbcon.Open();
759 755
760 cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString()); 756 string command = "select * from `regionwindlight` where region_id = ?regionID";
761 757
762 IDataReader result = ExecuteReader(cmd); 758 using (MySqlCommand cmd = new MySqlCommand(command))
763 if (!result.Read())
764 {
765 //No result, so store our default windlight profile and return it
766 nWP.regionID = regionUUID;
767 // StoreRegionWindlightSettings(nWP);
768 return nWP;
769 }
770 else
771 { 759 {
772 nWP.regionID = DBGuid.FromDB(result["region_id"]); 760 cmd.Connection = dbcon;
773 nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); 761
774 nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); 762 cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString());
775 nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); 763
776 nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); 764 IDataReader result = ExecuteReader(cmd);
777 nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); 765 if (!result.Read())
778 nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); 766 {
779 nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); 767 //No result, so store our default windlight profile and return it
780 nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); 768 nWP.regionID = regionUUID;
781 nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); 769// StoreRegionWindlightSettings(nWP);
782 nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); 770 return nWP;
783 nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); 771 }
784 nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); 772 else
785 nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); 773 {
786 nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); 774 nWP.regionID = DBGuid.FromDB(result["region_id"]);
787 nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); 775 nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]);
788 nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); 776 nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]);
789 nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); 777 nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]);
790 UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); 778 nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]);
791 nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); 779 nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]);
792 nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); 780 nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]);
793 nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); 781 nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]);
794 nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); 782 nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]);
795 nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); 783 nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]);
796 nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); 784 nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]);
797 nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); 785 nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]);
798 nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); 786 nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]);
799 nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); 787 nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]);
800 nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); 788 nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]);
801 nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); 789 nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]);
802 nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); 790 nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]);
803 nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); 791 nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]);
804 nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); 792 UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture);
805 nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); 793 nWP.horizon.X = Convert.ToSingle(result["horizon_r"]);
806 nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); 794 nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]);
807 nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); 795 nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]);
808 nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); 796 nWP.horizon.W = Convert.ToSingle(result["horizon_i"]);
809 nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); 797 nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]);
810 nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); 798 nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]);
811 nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); 799 nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]);
812 nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); 800 nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]);
813 nWP.eastAngle = Convert.ToSingle(result["east_angle"]); 801 nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]);
814 nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); 802 nWP.hazeDensity = Convert.ToSingle(result["haze_density"]);
815 nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); 803 nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]);
816 nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); 804 nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]);
817 nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); 805 nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]);
818 nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); 806 nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]);
819 nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); 807 nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]);
820 nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); 808 nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]);
821 nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); 809 nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]);
822 nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); 810 nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]);
823 nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); 811 nWP.ambient.X = Convert.ToSingle(result["ambient_r"]);
824 nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); 812 nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]);
825 nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); 813 nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]);
826 nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); 814 nWP.ambient.W = Convert.ToSingle(result["ambient_i"]);
827 nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); 815 nWP.eastAngle = Convert.ToSingle(result["east_angle"]);
828 nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); 816 nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]);
829 nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]); 817 nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]);
830 nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]); 818 nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]);
831 nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]); 819 nWP.starBrightness = Convert.ToSingle(result["star_brightness"]);
832 nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]); 820 nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]);
833 nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]); 821 nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]);
834 nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]); 822 nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]);
835 nWP.valid = true; 823 nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]);
824 nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]);
825 nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]);
826 nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]);
827 nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]);
828 nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]);
829 nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]);
830 nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]);
831 nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]);
832 nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]);
833 nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]);
834 nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]);
835 nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]);
836 nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]);
837 nWP.valid = true;
838 }
836 } 839 }
837 } 840 }
838 } 841 }
842
839 return nWP; 843 return nWP;
840 } 844 }
841 845
@@ -881,118 +885,124 @@ namespace OpenSim.Data.MySQL
881 885
882 public virtual void StoreRegionWindlightSettings(RegionLightShareData wl) 886 public virtual void StoreRegionWindlightSettings(RegionLightShareData wl)
883 { 887 {
884 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 888 lock (m_dbLock)
885 { 889 {
886 dbcon.Open(); 890 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
887
888 using (MySqlCommand cmd = dbcon.CreateCommand())
889 { 891 {
890 cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, "; 892 dbcon.Open();
891 cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, "; 893
892 cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, "; 894 using (MySqlCommand cmd = dbcon.CreateCommand())
893 cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, "; 895 {
894 cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, "; 896 cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, ";
895 cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, "; 897 cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, ";
896 cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, "; 898 cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, ";
897 cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, "; 899 cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, ";
898 cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, "; 900 cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, ";
899 cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, "; 901 cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, ";
900 cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, "; 902 cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, ";
901 cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, "; 903 cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, ";
902 cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, "; 904 cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, ";
903 cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, "; 905 cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, ";
904 cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, "; 906 cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, ";
905 cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, "; 907 cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, ";
906 cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, "; 908 cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, ";
907 cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, "; 909 cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, ";
908 cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, "; 910 cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, ";
909 cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, "; 911 cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, ";
910 cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, "; 912 cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, ";
911 cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, "; 913 cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, ";
912 cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, "; 914 cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, ";
913 cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, "; 915 cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, ";
914 cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)"; 916 cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, ";
915 917 cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, ";
916 cmd.Parameters.AddWithValue("region_id", wl.regionID); 918 cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, ";
917 cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X); 919 cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, ";
918 cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y); 920 cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)";
919 cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z); 921
920 cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent); 922 cmd.Parameters.AddWithValue("region_id", wl.regionID);
921 cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier); 923 cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X);
922 cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X); 924 cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y);
923 cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y); 925 cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z);
924 cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z); 926 cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent);
925 cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale); 927 cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier);
926 cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset); 928 cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X);
927 cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove); 929 cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y);
928 cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow); 930 cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z);
929 cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier); 931 cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale);
930 cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X); 932 cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset);
931 cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y); 933 cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove);
932 cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X); 934 cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow);
933 cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y); 935 cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier);
934 cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture); 936 cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X);
935 cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X); 937 cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y);
936 cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y); 938 cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X);
937 cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z); 939 cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y);
938 cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W); 940 cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture);
939 cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon); 941 cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X);
940 cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X); 942 cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y);
941 cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y); 943 cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z);
942 cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z); 944 cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W);
943 cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W); 945 cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon);
944 cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity); 946 cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X);
945 cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier); 947 cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y);
946 cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier); 948 cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z);
947 cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude); 949 cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W);
948 cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X); 950 cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity);
949 cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y); 951 cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier);
950 cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z); 952 cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier);
951 cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W); 953 cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude);
952 cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition); 954 cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X);
953 cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X); 955 cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y);
954 cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y); 956 cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z);
955 cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z); 957 cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W);
956 cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W); 958 cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition);
957 cmd.Parameters.AddWithValue("east_angle", wl.eastAngle); 959 cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X);
958 cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus); 960 cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y);
959 cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize); 961 cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z);
960 cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma); 962 cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W);
961 cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness); 963 cmd.Parameters.AddWithValue("east_angle", wl.eastAngle);
962 cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X); 964 cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus);
963 cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y); 965 cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize);
964 cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z); 966 cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma);
965 cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W); 967 cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness);
966 cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X); 968 cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X);
967 cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y); 969 cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y);
968 cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z); 970 cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z);
969 cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage); 971 cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W);
970 cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale); 972 cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X);
971 cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X); 973 cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y);
972 cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y); 974 cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z);
973 cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z); 975 cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage);
974 cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX); 976 cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale);
975 cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock); 977 cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X);
976 cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY); 978 cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y);
977 cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock); 979 cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z);
978 cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds); 980 cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX);
979 981 cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock);
980 ExecuteNonQuery(cmd); 982 cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY);
983 cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock);
984 cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds);
985
986 ExecuteNonQuery(cmd);
987 }
981 } 988 }
982 } 989 }
983 } 990 }
984 991
985 public virtual void RemoveRegionWindlightSettings(UUID regionID) 992 public virtual void RemoveRegionWindlightSettings(UUID regionID)
986 { 993 {
987 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 994 lock (m_dbLock)
988 { 995 {
989 dbcon.Open(); 996 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
990
991 using (MySqlCommand cmd = dbcon.CreateCommand())
992 { 997 {
993 cmd.CommandText = "delete from `regionwindlight` where `region_id`=?regionID"; 998 dbcon.Open();
994 cmd.Parameters.AddWithValue("?regionID", regionID.ToString()); 999
995 ExecuteNonQuery(cmd); 1000 using (MySqlCommand cmd = dbcon.CreateCommand())
1001 {
1002 cmd.CommandText = "delete from `regionwindlight` where `region_id`=?regionID";
1003 cmd.Parameters.AddWithValue("?regionID", regionID.ToString());
1004 ExecuteNonQuery(cmd);
1005 }
996 } 1006 }
997 } 1007 }
998 } 1008 }
@@ -1000,26 +1010,29 @@ namespace OpenSim.Data.MySQL
1000 #region RegionEnvironmentSettings 1010 #region RegionEnvironmentSettings
1001 public string LoadRegionEnvironmentSettings(UUID regionUUID) 1011 public string LoadRegionEnvironmentSettings(UUID regionUUID)
1002 { 1012 {
1003 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1013 lock (m_dbLock)
1004 { 1014 {
1005 dbcon.Open(); 1015 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
1006
1007 string command = "select * from `regionenvironment` where region_id = ?region_id";
1008
1009 using (MySqlCommand cmd = new MySqlCommand(command))
1010 { 1016 {
1011 cmd.Connection = dbcon; 1017 dbcon.Open();
1012 1018
1013 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString()); 1019 string command = "select * from `regionenvironment` where region_id = ?region_id";
1014 1020
1015 IDataReader result = ExecuteReader(cmd); 1021 using (MySqlCommand cmd = new MySqlCommand(command))
1016 if (!result.Read())
1017 {
1018 return String.Empty;
1019 }
1020 else
1021 { 1022 {
1022 return Convert.ToString(result["llsd_settings"]); 1023 cmd.Connection = dbcon;
1024
1025 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
1026
1027 IDataReader result = ExecuteReader(cmd);
1028 if (!result.Read())
1029 {
1030 return String.Empty;
1031 }
1032 else
1033 {
1034 return Convert.ToString(result["llsd_settings"]);
1035 }
1023 } 1036 }
1024 } 1037 }
1025 } 1038 }
@@ -1027,33 +1040,39 @@ namespace OpenSim.Data.MySQL
1027 1040
1028 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings) 1041 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
1029 { 1042 {
1030 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1043 lock (m_dbLock)
1031 { 1044 {
1032 dbcon.Open(); 1045 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
1033
1034 using (MySqlCommand cmd = dbcon.CreateCommand())
1035 { 1046 {
1036 cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)"; 1047 dbcon.Open();
1037 1048
1038 cmd.Parameters.AddWithValue("region_id", regionUUID); 1049 using (MySqlCommand cmd = dbcon.CreateCommand())
1039 cmd.Parameters.AddWithValue("llsd_settings", settings); 1050 {
1040 1051 cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)";
1041 ExecuteNonQuery(cmd); 1052
1053 cmd.Parameters.AddWithValue("region_id", regionUUID);
1054 cmd.Parameters.AddWithValue("llsd_settings", settings);
1055
1056 ExecuteNonQuery(cmd);
1057 }
1042 } 1058 }
1043 } 1059 }
1044 } 1060 }
1045 1061
1046 public void RemoveRegionEnvironmentSettings(UUID regionUUID) 1062 public void RemoveRegionEnvironmentSettings(UUID regionUUID)
1047 { 1063 {
1048 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1064 lock (m_dbLock)
1049 { 1065 {
1050 dbcon.Open(); 1066 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
1051
1052 using (MySqlCommand cmd = dbcon.CreateCommand())
1053 { 1067 {
1054 cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id"; 1068 dbcon.Open();
1055 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString()); 1069
1056 ExecuteNonQuery(cmd); 1070 using (MySqlCommand cmd = dbcon.CreateCommand())
1071 {
1072 cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id";
1073 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
1074 ExecuteNonQuery(cmd);
1075 }
1057 } 1076 }
1058 } 1077 }
1059 } 1078 }
diff --git a/OpenSim/Data/MySQL/MySQLXInventoryData.cs b/OpenSim/Data/MySQL/MySQLXInventoryData.cs
index caf18a4..c74033e 100644
--- a/OpenSim/Data/MySQL/MySQLXInventoryData.cs
+++ b/OpenSim/Data/MySQL/MySQLXInventoryData.cs
@@ -26,9 +26,10 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using System.Data; 30using System.Data;
31using System.Linq;
30using System.Reflection; 32using System.Reflection;
31using System.Collections.Generic;
32using log4net; 33using log4net;
33using MySql.Data.MySqlClient; 34using MySql.Data.MySqlClient;
34using OpenMetaverse; 35using OpenMetaverse;
@@ -41,12 +42,12 @@ namespace OpenSim.Data.MySQL
41 /// </summary> 42 /// </summary>
42 public class MySQLXInventoryData : IXInventoryData 43 public class MySQLXInventoryData : IXInventoryData
43 { 44 {
44 private MySQLGenericTableHandler<XInventoryFolder> m_Folders; 45 private MySqlFolderHandler m_Folders;
45 private MySqlItemHandler m_Items; 46 private MySqlItemHandler m_Items;
46 47
47 public MySQLXInventoryData(string conn, string realm) 48 public MySQLXInventoryData(string conn, string realm)
48 { 49 {
49 m_Folders = new MySQLGenericTableHandler<XInventoryFolder>( 50 m_Folders = new MySqlFolderHandler(
50 conn, "inventoryfolders", "InventoryStore"); 51 conn, "inventoryfolders", "InventoryStore");
51 m_Items = new MySqlItemHandler( 52 m_Items = new MySqlItemHandler(
52 conn, "inventoryitems", String.Empty); 53 conn, "inventoryitems", String.Empty);
@@ -105,6 +106,11 @@ namespace OpenSim.Data.MySQL
105 return m_Items.MoveItem(id, newParent); 106 return m_Items.MoveItem(id, newParent);
106 } 107 }
107 108
109 public bool MoveFolder(string id, string newParent)
110 {
111 return m_Folders.MoveFolder(id, newParent);
112 }
113
108 public XInventoryItem[] GetActiveGestures(UUID principalID) 114 public XInventoryItem[] GetActiveGestures(UUID principalID)
109 { 115 {
110 return m_Items.GetActiveGestures(principalID); 116 return m_Items.GetActiveGestures(principalID);
@@ -116,24 +122,71 @@ namespace OpenSim.Data.MySQL
116 } 122 }
117 } 123 }
118 124
119 public class MySqlItemHandler : MySQLGenericTableHandler<XInventoryItem> 125 public class MySqlItemHandler : MySqlInventoryHandler<XInventoryItem>
120 { 126 {
127// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
128
121 public MySqlItemHandler(string c, string t, string m) : 129 public MySqlItemHandler(string c, string t, string m) :
122 base(c, t, m) 130 base(c, t, m)
123 { 131 {
124 } 132 }
125 133
134 public override bool Delete(string field, string val)
135 {
136 XInventoryItem[] retrievedItems = Get(new string[] { field }, new string[] { val });
137 if (retrievedItems.Length == 0)
138 return false;
139
140 if (!base.Delete(field, val))
141 return false;
142
143 // Don't increment folder version here since Delete(string, string) calls Delete(string[], string[])
144// IncrementFolderVersion(retrievedItems[0].parentFolderID);
145
146 return true;
147 }
148
149 public override bool Delete(string[] fields, string[] vals)
150 {
151 XInventoryItem[] retrievedItems = Get(fields, vals);
152 if (retrievedItems.Length == 0)
153 return false;
154
155 if (!base.Delete(fields, vals))
156 return false;
157
158 HashSet<UUID> deletedItemFolderUUIDs = new HashSet<UUID>();
159
160 Array.ForEach<XInventoryItem>(retrievedItems, i => deletedItemFolderUUIDs.Add(i.parentFolderID));
161
162 foreach (UUID deletedItemFolderUUID in deletedItemFolderUUIDs)
163 IncrementFolderVersion(deletedItemFolderUUID);
164
165 return true;
166 }
167
126 public bool MoveItem(string id, string newParent) 168 public bool MoveItem(string id, string newParent)
127 { 169 {
170 XInventoryItem[] retrievedItems = Get(new string[] { "inventoryID" }, new string[] { id });
171 if (retrievedItems.Length == 0)
172 return false;
173
174 UUID oldParent = retrievedItems[0].parentFolderID;
175
128 using (MySqlCommand cmd = new MySqlCommand()) 176 using (MySqlCommand cmd = new MySqlCommand())
129 { 177 {
130
131 cmd.CommandText = String.Format("update {0} set parentFolderID = ?ParentFolderID where inventoryID = ?InventoryID", m_Realm); 178 cmd.CommandText = String.Format("update {0} set parentFolderID = ?ParentFolderID where inventoryID = ?InventoryID", m_Realm);
132 cmd.Parameters.AddWithValue("?ParentFolderID", newParent); 179 cmd.Parameters.AddWithValue("?ParentFolderID", newParent);
133 cmd.Parameters.AddWithValue("?InventoryID", id); 180 cmd.Parameters.AddWithValue("?InventoryID", id);
134 181
135 return ExecuteNonQuery(cmd) == 0 ? false : true; 182 if (ExecuteNonQuery(cmd) == 0)
183 return false;
136 } 184 }
185
186 IncrementFolderVersion(oldParent);
187 IncrementFolderVersion(newParent);
188
189 return true;
137 } 190 }
138 191
139 public XInventoryItem[] GetActiveGestures(UUID principalID) 192 public XInventoryItem[] GetActiveGestures(UUID principalID)
@@ -184,6 +237,73 @@ namespace OpenSim.Data.MySQL
184 if (!base.Store(item)) 237 if (!base.Store(item))
185 return false; 238 return false;
186 239
240 IncrementFolderVersion(item.parentFolderID);
241
242 return true;
243 }
244 }
245
246 public class MySqlFolderHandler : MySqlInventoryHandler<XInventoryFolder>
247 {
248// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
249
250 public MySqlFolderHandler(string c, string t, string m) :
251 base(c, t, m)
252 {
253 }
254
255 public bool MoveFolder(string id, string newParentFolderID)
256 {
257 XInventoryFolder[] folders = Get(new string[] { "folderID" }, new string[] { id });
258
259 if (folders.Length == 0)
260 return false;
261
262 UUID oldParentFolderUUID = folders[0].parentFolderID;
263
264 using (MySqlCommand cmd = new MySqlCommand())
265 {
266 cmd.CommandText
267 = String.Format(
268 "update {0} set parentFolderID = ?ParentFolderID where folderID = ?folderID", m_Realm);
269 cmd.Parameters.AddWithValue("?ParentFolderID", newParentFolderID);
270 cmd.Parameters.AddWithValue("?folderID", id);
271
272 if (ExecuteNonQuery(cmd) == 0)
273 return false;
274 }
275
276 IncrementFolderVersion(oldParentFolderUUID);
277 IncrementFolderVersion(newParentFolderID);
278
279 return true;
280 }
281
282 public override bool Store(XInventoryFolder folder)
283 {
284 if (!base.Store(folder))
285 return false;
286
287 IncrementFolderVersion(folder.parentFolderID);
288
289 return true;
290 }
291 }
292
293 public class MySqlInventoryHandler<T> : MySQLGenericTableHandler<T> where T: class, new()
294 {
295 public MySqlInventoryHandler(string c, string t, string m) : base(c, t, m) {}
296
297 protected bool IncrementFolderVersion(UUID folderID)
298 {
299 return IncrementFolderVersion(folderID.ToString());
300 }
301
302 protected bool IncrementFolderVersion(string folderID)
303 {
304// m_log.DebugFormat("[MYSQL FOLDER HANDLER]: Incrementing version on folder {0}", folderID);
305// Util.PrintCallStack();
306
187 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 307 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
188 { 308 {
189 dbcon.Open(); 309 dbcon.Open();
@@ -193,7 +313,7 @@ namespace OpenSim.Data.MySQL
193 cmd.Connection = dbcon; 313 cmd.Connection = dbcon;
194 314
195 cmd.CommandText = String.Format("update inventoryfolders set version=version+1 where folderID = ?folderID"); 315 cmd.CommandText = String.Format("update inventoryfolders set version=version+1 where folderID = ?folderID");
196 cmd.Parameters.AddWithValue("?folderID", item.parentFolderID.ToString()); 316 cmd.Parameters.AddWithValue("?folderID", folderID);
197 317
198 try 318 try
199 { 319 {
@@ -205,9 +325,11 @@ namespace OpenSim.Data.MySQL
205 } 325 }
206 cmd.Dispose(); 326 cmd.Dispose();
207 } 327 }
328
208 dbcon.Close(); 329 dbcon.Close();
209 } 330 }
331
210 return true; 332 return true;
211 } 333 }
212 } 334 }
213} 335} \ No newline at end of file
diff --git a/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs b/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
index c28829c..ab3fe36 100644
--- a/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.6.5.*")] 64[assembly : AssemblyVersion("0.7.5.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65[assembly : AssemblyFileVersion("0.6.5.0")]
diff --git a/OpenSim/Data/MySQL/Resources/GridUserStore.migrations b/OpenSim/Data/MySQL/Resources/GridUserStore.migrations
index 32b85ee..d08e096 100644
--- a/OpenSim/Data/MySQL/Resources/GridUserStore.migrations
+++ b/OpenSim/Data/MySQL/Resources/GridUserStore.migrations
@@ -17,3 +17,8 @@ CREATE TABLE `GridUser` (
17) ENGINE=InnoDB; 17) ENGINE=InnoDB;
18 18
19COMMIT; 19COMMIT;
20
21:VERSION 2 # --------------------------
22BEGIN;
23
24COMMIT;
diff --git a/OpenSim/Data/Null/NullRegionData.cs b/OpenSim/Data/Null/NullRegionData.cs
index deb50cb..b4d701a 100644
--- a/OpenSim/Data/Null/NullRegionData.cs
+++ b/OpenSim/Data/Null/NullRegionData.cs
@@ -33,6 +33,7 @@ using OpenSim.Framework;
33using OpenSim.Data; 33using OpenSim.Data;
34using System.Reflection; 34using System.Reflection;
35using log4net; 35using log4net;
36using RegionFlags = OpenSim.Framework.RegionFlags;
36 37
37namespace OpenSim.Data.Null 38namespace OpenSim.Data.Null
38{ 39{
diff --git a/OpenSim/Data/Null/Properties/AssemblyInfo.cs b/OpenSim/Data/Null/Properties/AssemblyInfo.cs
index 4b64436..43b0bb3 100644
--- a/OpenSim/Data/Null/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/Null/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.6.5.*")] 64[assembly : AssemblyVersion("0.7.5.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65[assembly : AssemblyFileVersion("0.6.5.0")]
diff --git a/OpenSim/Data/Properties/AssemblyInfo.cs b/OpenSim/Data/Properties/AssemblyInfo.cs
index 6940d25..0da1a6b 100644
--- a/OpenSim/Data/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.6.5.*")] 64[assembly : AssemblyVersion("0.7.5.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65[assembly : AssemblyFileVersion("0.6.5.0")]
diff --git a/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs b/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
index d45ab50..c9a8553 100644
--- a/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.6.5.*")] 64[assembly : AssemblyVersion("0.7.5.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65[assembly : AssemblyFileVersion("0.6.5.0")]
diff --git a/OpenSim/Data/SQLite/SQLiteAssetData.cs b/OpenSim/Data/SQLite/SQLiteAssetData.cs
index 7f7059b..b94a58c 100644
--- a/OpenSim/Data/SQLite/SQLiteAssetData.cs
+++ b/OpenSim/Data/SQLite/SQLiteAssetData.cs
@@ -204,7 +204,8 @@ namespace OpenSim.Data.SQLite
204 /// <returns>True if exist, or false.</returns> 204 /// <returns>True if exist, or false.</returns>
205 override public bool ExistsAsset(UUID uuid) 205 override public bool ExistsAsset(UUID uuid)
206 { 206 {
207 lock (this) { 207 lock (this)
208 {
208 using (SqliteCommand cmd = new SqliteCommand(SelectAssetSQL, m_conn)) 209 using (SqliteCommand cmd = new SqliteCommand(SelectAssetSQL, m_conn))
209 { 210 {
210 cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString())); 211 cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString()));
@@ -355,12 +356,13 @@ namespace OpenSim.Data.SQLite
355 { 356 {
356 lock (this) 357 lock (this)
357 { 358 {
358 using (SqliteCommand cmd = new SqliteCommand(DeleteAssetSQL, m_conn)) 359 using (SqliteCommand cmd = new SqliteCommand(DeleteAssetSQL, m_conn))
359 { 360 {
360 cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString())); 361 cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString()));
361 cmd.ExecuteNonQuery(); 362 cmd.ExecuteNonQuery();
362 } 363 }
363 } 364 }
365
364 return true; 366 return true;
365 } 367 }
366 368
diff --git a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs
index 5120453..0428c11 100644
--- a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs
@@ -82,11 +82,14 @@ namespace OpenSim.Data.SQLite
82 { 82 {
83 AuthenticationData ret = new AuthenticationData(); 83 AuthenticationData ret = new AuthenticationData();
84 ret.Data = new Dictionary<string, object>(); 84 ret.Data = new Dictionary<string, object>();
85 IDataReader result;
85 86
86 SqliteCommand cmd = new SqliteCommand("select * from `" + m_Realm + "` where UUID = :PrincipalID"); 87 using (SqliteCommand cmd = new SqliteCommand("select * from `" + m_Realm + "` where UUID = :PrincipalID"))
87 cmd.Parameters.Add(new SqliteParameter(":PrincipalID", principalID.ToString())); 88 {
89 cmd.Parameters.Add(new SqliteParameter(":PrincipalID", principalID.ToString()));
88 90
89 IDataReader result = ExecuteReader(cmd, m_Connection); 91 result = ExecuteReader(cmd, m_Connection);
92 }
90 93
91 try 94 try
92 { 95 {
@@ -121,10 +124,6 @@ namespace OpenSim.Data.SQLite
121 catch 124 catch
122 { 125 {
123 } 126 }
124 finally
125 {
126 //CloseCommand(cmd);
127 }
128 127
129 return null; 128 return null;
130 } 129 }
@@ -140,84 +139,81 @@ namespace OpenSim.Data.SQLite
140 foreach (object o in data.Data.Values) 139 foreach (object o in data.Data.Values)
141 values[i++] = o.ToString(); 140 values[i++] = o.ToString();
142 141
143 SqliteCommand cmd = new SqliteCommand(); 142 using (SqliteCommand cmd = new SqliteCommand())
144
145 if (Get(data.PrincipalID) != null)
146 { 143 {
144 if (Get(data.PrincipalID) != null)
145 {
147 146
148 147
149 string update = "update `" + m_Realm + "` set "; 148 string update = "update `" + m_Realm + "` set ";
150 bool first = true; 149 bool first = true;
151 foreach (string field in fields) 150 foreach (string field in fields)
152 { 151 {
153 if (!first) 152 if (!first)
154 update += ", "; 153 update += ", ";
155 update += "`" + field + "` = :" + field; 154 update += "`" + field + "` = :" + field;
156 cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field])); 155 cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field]));
157 156
158 first = false; 157 first = false;
159 } 158 }
160 159
161 update += " where UUID = :UUID"; 160 update += " where UUID = :UUID";
162 cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString())); 161 cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString()));
163 162
164 cmd.CommandText = update; 163 cmd.CommandText = update;
165 try 164 try
166 { 165 {
167 if (ExecuteNonQuery(cmd, m_Connection) < 1) 166 if (ExecuteNonQuery(cmd, m_Connection) < 1)
167 {
168 //CloseCommand(cmd);
169 return false;
170 }
171 }
172 catch (Exception e)
168 { 173 {
174 m_log.Error("[SQLITE]: Exception storing authentication data", e);
169 //CloseCommand(cmd); 175 //CloseCommand(cmd);
170 return false; 176 return false;
171 } 177 }
172 } 178 }
173 catch (Exception e) 179 else
174 { 180 {
175 m_log.Error("[SQLITE]: Exception storing authentication data", e); 181 string insert = "insert into `" + m_Realm + "` (`UUID`, `" +
176 //CloseCommand(cmd); 182 String.Join("`, `", fields) +
177 return false; 183 "`) values (:UUID, :" + String.Join(", :", fields) + ")";
178 }
179 }
180 184
181 else 185 cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString()));
182 { 186 foreach (string field in fields)
183 string insert = "insert into `" + m_Realm + "` (`UUID`, `" + 187 cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field]));
184 String.Join("`, `", fields) +
185 "`) values (:UUID, :" + String.Join(", :", fields) + ")";
186
187 cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString()));
188 foreach (string field in fields)
189 cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field]));
190 188
191 cmd.CommandText = insert; 189 cmd.CommandText = insert;
192 190
193 try 191 try
194 {
195 if (ExecuteNonQuery(cmd, m_Connection) < 1)
196 { 192 {
197 //CloseCommand(cmd); 193 if (ExecuteNonQuery(cmd, m_Connection) < 1)
194 {
195 return false;
196 }
197 }
198 catch (Exception e)
199 {
200 Console.WriteLine(e.ToString());
198 return false; 201 return false;
199 } 202 }
200 } 203 }
201 catch (Exception e)
202 {
203 Console.WriteLine(e.ToString());
204 //CloseCommand(cmd);
205 return false;
206 }
207 } 204 }
208 205
209 //CloseCommand(cmd);
210
211 return true; 206 return true;
212 } 207 }
213 208
214 public bool SetDataItem(UUID principalID, string item, string value) 209 public bool SetDataItem(UUID principalID, string item, string value)
215 { 210 {
216 SqliteCommand cmd = new SqliteCommand("update `" + m_Realm + 211 using (SqliteCommand cmd = new SqliteCommand("update `" + m_Realm +
217 "` set `" + item + "` = " + value + " where UUID = '" + principalID.ToString() + "'"); 212 "` set `" + item + "` = " + value + " where UUID = '" + principalID.ToString() + "'"))
218 213 {
219 if (ExecuteNonQuery(cmd, m_Connection) > 0) 214 if (ExecuteNonQuery(cmd, m_Connection) > 0)
220 return true; 215 return true;
216 }
221 217
222 return false; 218 return false;
223 } 219 }
@@ -227,16 +223,13 @@ namespace OpenSim.Data.SQLite
227 if (System.Environment.TickCount - m_LastExpire > 30000) 223 if (System.Environment.TickCount - m_LastExpire > 30000)
228 DoExpire(); 224 DoExpire();
229 225
230 SqliteCommand cmd = new SqliteCommand("insert into tokens (UUID, token, validity) values ('" + principalID.ToString() + 226 using (SqliteCommand cmd = new SqliteCommand("insert into tokens (UUID, token, validity) values ('" + principalID.ToString() +
231 "', '" + token + "', datetime('now', 'localtime', '+" + lifetime.ToString() + " minutes'))"); 227 "', '" + token + "', datetime('now', 'localtime', '+" + lifetime.ToString() + " minutes'))"))
232
233 if (ExecuteNonQuery(cmd, m_Connection) > 0)
234 { 228 {
235 cmd.Dispose(); 229 if (ExecuteNonQuery(cmd, m_Connection) > 0)
236 return true; 230 return true;
237 } 231 }
238 232
239 cmd.Dispose();
240 return false; 233 return false;
241 } 234 }
242 235
@@ -245,28 +238,22 @@ namespace OpenSim.Data.SQLite
245 if (System.Environment.TickCount - m_LastExpire > 30000) 238 if (System.Environment.TickCount - m_LastExpire > 30000)
246 DoExpire(); 239 DoExpire();
247 240
248 SqliteCommand cmd = new SqliteCommand("update tokens set validity = datetime('now', 'localtime', '+" + lifetime.ToString() + 241 using (SqliteCommand cmd = new SqliteCommand("update tokens set validity = datetime('now', 'localtime', '+" + lifetime.ToString() +
249 " minutes') where UUID = '" + principalID.ToString() + "' and token = '" + token + "' and validity > datetime('now', 'localtime')"); 242 " minutes') where UUID = '" + principalID.ToString() + "' and token = '" + token + "' and validity > datetime('now', 'localtime')"))
250
251 if (ExecuteNonQuery(cmd, m_Connection) > 0)
252 { 243 {
253 cmd.Dispose(); 244 if (ExecuteNonQuery(cmd, m_Connection) > 0)
254 return true; 245 return true;
255 } 246 }
256 247
257 cmd.Dispose();
258
259 return false; 248 return false;
260 } 249 }
261 250
262 private void DoExpire() 251 private void DoExpire()
263 { 252 {
264 SqliteCommand cmd = new SqliteCommand("delete from tokens where validity < datetime('now', 'localtime')"); 253 using (SqliteCommand cmd = new SqliteCommand("delete from tokens where validity < datetime('now', 'localtime')"))
265 ExecuteNonQuery(cmd, m_Connection); 254 ExecuteNonQuery(cmd, m_Connection);
266
267 cmd.Dispose();
268 255
269 m_LastExpire = System.Environment.TickCount; 256 m_LastExpire = System.Environment.TickCount;
270 } 257 }
271 } 258 }
272} 259} \ No newline at end of file
diff --git a/OpenSim/Data/SQLite/SQLiteAvatarData.cs b/OpenSim/Data/SQLite/SQLiteAvatarData.cs
index faf34da..c6d615b 100644
--- a/OpenSim/Data/SQLite/SQLiteAvatarData.cs
+++ b/OpenSim/Data/SQLite/SQLiteAvatarData.cs
@@ -56,23 +56,17 @@ namespace OpenSim.Data.SQLite
56 56
57 public bool Delete(UUID principalID, string name) 57 public bool Delete(UUID principalID, string name)
58 { 58 {
59 SqliteCommand cmd = new SqliteCommand(); 59 using (SqliteCommand cmd = new SqliteCommand())
60
61 cmd.CommandText = String.Format("delete from {0} where `PrincipalID` = :PrincipalID and `Name` = :Name", m_Realm);
62 cmd.Parameters.AddWithValue(":PrincipalID", principalID.ToString());
63 cmd.Parameters.AddWithValue(":Name", name);
64
65 try
66 { 60 {
61 cmd.CommandText = String.Format("delete from {0} where `PrincipalID` = :PrincipalID and `Name` = :Name", m_Realm);
62 cmd.Parameters.AddWithValue(":PrincipalID", principalID.ToString());
63 cmd.Parameters.AddWithValue(":Name", name);
64
67 if (ExecuteNonQuery(cmd, m_Connection) > 0) 65 if (ExecuteNonQuery(cmd, m_Connection) > 0)
68 return true; 66 return true;
69
70 return false;
71 }
72 finally
73 {
74 //CloseCommand(cmd);
75 } 67 }
68
69 return false;
76 } 70 }
77 } 71 }
78} 72} \ No newline at end of file
diff --git a/OpenSim/Data/SQLite/SQLiteEstateData.cs b/OpenSim/Data/SQLite/SQLiteEstateData.cs
index c042ba2..d51f2d4 100644
--- a/OpenSim/Data/SQLite/SQLiteEstateData.cs
+++ b/OpenSim/Data/SQLite/SQLiteEstateData.cs
@@ -104,12 +104,13 @@ namespace OpenSim.Data.SQLite
104 { 104 {
105 string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = :RegionID"; 105 string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = :RegionID";
106 106
107 SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); 107 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
108 108 {
109 cmd.CommandText = sql; 109 cmd.CommandText = sql;
110 cmd.Parameters.AddWithValue(":RegionID", regionID.ToString()); 110 cmd.Parameters.AddWithValue(":RegionID", regionID.ToString());
111 111
112 return DoLoad(cmd, regionID, create); 112 return DoLoad(cmd, regionID, create);
113 }
113 } 114 }
114 115
115 private EstateSettings DoLoad(SqliteCommand cmd, UUID regionID, bool create) 116 private EstateSettings DoLoad(SqliteCommand cmd, UUID regionID, bool create)
@@ -186,37 +187,39 @@ namespace OpenSim.Data.SQLite
186 { 187 {
187 List<string> names = new List<string>(FieldList); 188 List<string> names = new List<string>(FieldList);
188 189
189 SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand();
190 IDataReader r = null; 190 IDataReader r = null;
191 191
192 names.Remove("EstateID"); 192 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
193 {
194 names.Remove("EstateID");
193 195
194 string sql = "insert into estate_settings ("+String.Join(",", names.ToArray())+") values ( :"+String.Join(", :", names.ToArray())+")"; 196 string sql = "insert into estate_settings ("+String.Join(",", names.ToArray())+") values ( :"+String.Join(", :", names.ToArray())+")";
195 197
196 cmd.CommandText = sql; 198 cmd.CommandText = sql;
197 cmd.Parameters.Clear(); 199 cmd.Parameters.Clear();
198 200
199 foreach (string name in FieldList) 201 foreach (string name in FieldList)
200 {
201 if (m_FieldMap[name].GetValue(es) is bool)
202 { 202 {
203 if ((bool)m_FieldMap[name].GetValue(es)) 203 if (m_FieldMap[name].GetValue(es) is bool)
204 cmd.Parameters.AddWithValue(":"+name, "1"); 204 {
205 if ((bool)m_FieldMap[name].GetValue(es))
206 cmd.Parameters.AddWithValue(":"+name, "1");
207 else
208 cmd.Parameters.AddWithValue(":"+name, "0");
209 }
205 else 210 else
206 cmd.Parameters.AddWithValue(":"+name, "0"); 211 {
207 } 212 cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString());
208 else 213 }
209 {
210 cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString());
211 } 214 }
212 }
213 215
214 cmd.ExecuteNonQuery(); 216 cmd.ExecuteNonQuery();
215 217
216 cmd.CommandText = "select LAST_INSERT_ROWID() as id"; 218 cmd.CommandText = "select LAST_INSERT_ROWID() as id";
217 cmd.Parameters.Clear(); 219 cmd.Parameters.Clear();
218 220
219 r = cmd.ExecuteReader(); 221 r = cmd.ExecuteReader();
222 }
220 223
221 r.Read(); 224 r.Read();
222 225
@@ -239,26 +242,27 @@ namespace OpenSim.Data.SQLite
239 242
240 string sql = "update estate_settings set "+String.Join(", ", terms.ToArray())+" where EstateID = :EstateID"; 243 string sql = "update estate_settings set "+String.Join(", ", terms.ToArray())+" where EstateID = :EstateID";
241 244
242 SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); 245 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
243
244 cmd.CommandText = sql;
245
246 foreach (string name in FieldList)
247 { 246 {
248 if (m_FieldMap[name].GetValue(es) is bool) 247 cmd.CommandText = sql;
248
249 foreach (string name in FieldList)
249 { 250 {
250 if ((bool)m_FieldMap[name].GetValue(es)) 251 if (m_FieldMap[name].GetValue(es) is bool)
251 cmd.Parameters.AddWithValue(":"+name, "1"); 252 {
253 if ((bool)m_FieldMap[name].GetValue(es))
254 cmd.Parameters.AddWithValue(":"+name, "1");
255 else
256 cmd.Parameters.AddWithValue(":"+name, "0");
257 }
252 else 258 else
253 cmd.Parameters.AddWithValue(":"+name, "0"); 259 {
254 } 260 cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString());
255 else 261 }
256 {
257 cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString());
258 } 262 }
259 }
260 263
261 cmd.ExecuteNonQuery(); 264 cmd.ExecuteNonQuery();
265 }
262 266
263 SaveBanList(es); 267 SaveBanList(es);
264 SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers); 268 SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers);
@@ -270,12 +274,15 @@ namespace OpenSim.Data.SQLite
270 { 274 {
271 es.ClearBans(); 275 es.ClearBans();
272 276
273 SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); 277 IDataReader r;
274 278
275 cmd.CommandText = "select bannedUUID from estateban where EstateID = :EstateID"; 279 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
276 cmd.Parameters.AddWithValue(":EstateID", es.EstateID); 280 {
281 cmd.CommandText = "select bannedUUID from estateban where EstateID = :EstateID";
282 cmd.Parameters.AddWithValue(":EstateID", es.EstateID);
277 283
278 IDataReader r = cmd.ExecuteReader(); 284 r = cmd.ExecuteReader();
285 }
279 286
280 while (r.Read()) 287 while (r.Read())
281 { 288 {
@@ -294,60 +301,64 @@ namespace OpenSim.Data.SQLite
294 301
295 private void SaveBanList(EstateSettings es) 302 private void SaveBanList(EstateSettings es)
296 { 303 {
297 SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); 304 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
298
299 cmd.CommandText = "delete from estateban where EstateID = :EstateID";
300 cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString());
301
302 cmd.ExecuteNonQuery();
303
304 cmd.Parameters.Clear();
305
306 cmd.CommandText = "insert into estateban (EstateID, bannedUUID, bannedIp, bannedIpHostMask, bannedNameMask) values ( :EstateID, :bannedUUID, '', '', '' )";
307
308 foreach (EstateBan b in es.EstateBans)
309 { 305 {
306 cmd.CommandText = "delete from estateban where EstateID = :EstateID";
310 cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString()); 307 cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString());
311 cmd.Parameters.AddWithValue(":bannedUUID", b.BannedUserID.ToString());
312 308
313 cmd.ExecuteNonQuery(); 309 cmd.ExecuteNonQuery();
310
314 cmd.Parameters.Clear(); 311 cmd.Parameters.Clear();
312
313 cmd.CommandText = "insert into estateban (EstateID, bannedUUID, bannedIp, bannedIpHostMask, bannedNameMask) values ( :EstateID, :bannedUUID, '', '', '' )";
314
315 foreach (EstateBan b in es.EstateBans)
316 {
317 cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString());
318 cmd.Parameters.AddWithValue(":bannedUUID", b.BannedUserID.ToString());
319
320 cmd.ExecuteNonQuery();
321 cmd.Parameters.Clear();
322 }
315 } 323 }
316 } 324 }
317 325
318 void SaveUUIDList(uint EstateID, string table, UUID[] data) 326 void SaveUUIDList(uint EstateID, string table, UUID[] data)
319 { 327 {
320 SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); 328 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
321
322 cmd.CommandText = "delete from "+table+" where EstateID = :EstateID";
323 cmd.Parameters.AddWithValue(":EstateID", EstateID.ToString());
324
325 cmd.ExecuteNonQuery();
326
327 cmd.Parameters.Clear();
328
329 cmd.CommandText = "insert into "+table+" (EstateID, uuid) values ( :EstateID, :uuid )";
330
331 foreach (UUID uuid in data)
332 { 329 {
330 cmd.CommandText = "delete from "+table+" where EstateID = :EstateID";
333 cmd.Parameters.AddWithValue(":EstateID", EstateID.ToString()); 331 cmd.Parameters.AddWithValue(":EstateID", EstateID.ToString());
334 cmd.Parameters.AddWithValue(":uuid", uuid.ToString());
335 332
336 cmd.ExecuteNonQuery(); 333 cmd.ExecuteNonQuery();
334
337 cmd.Parameters.Clear(); 335 cmd.Parameters.Clear();
336
337 cmd.CommandText = "insert into "+table+" (EstateID, uuid) values ( :EstateID, :uuid )";
338
339 foreach (UUID uuid in data)
340 {
341 cmd.Parameters.AddWithValue(":EstateID", EstateID.ToString());
342 cmd.Parameters.AddWithValue(":uuid", uuid.ToString());
343
344 cmd.ExecuteNonQuery();
345 cmd.Parameters.Clear();
346 }
338 } 347 }
339 } 348 }
340 349
341 UUID[] LoadUUIDList(uint EstateID, string table) 350 UUID[] LoadUUIDList(uint EstateID, string table)
342 { 351 {
343 List<UUID> uuids = new List<UUID>(); 352 List<UUID> uuids = new List<UUID>();
353 IDataReader r;
344 354
345 SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); 355 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
346 356 {
347 cmd.CommandText = "select uuid from "+table+" where EstateID = :EstateID"; 357 cmd.CommandText = "select uuid from "+table+" where EstateID = :EstateID";
348 cmd.Parameters.AddWithValue(":EstateID", EstateID); 358 cmd.Parameters.AddWithValue(":EstateID", EstateID);
349 359
350 IDataReader r = cmd.ExecuteReader(); 360 r = cmd.ExecuteReader();
361 }
351 362
352 while (r.Read()) 363 while (r.Read())
353 { 364 {
@@ -367,12 +378,13 @@ namespace OpenSim.Data.SQLite
367 { 378 {
368 string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_settings where estate_settings.EstateID = :EstateID"; 379 string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_settings where estate_settings.EstateID = :EstateID";
369 380
370 SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); 381 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
371 382 {
372 cmd.CommandText = sql; 383 cmd.CommandText = sql;
373 cmd.Parameters.AddWithValue(":EstateID", estateID.ToString()); 384 cmd.Parameters.AddWithValue(":EstateID", estateID.ToString());
374 385
375 return DoLoad(cmd, UUID.Zero, false); 386 return DoLoad(cmd, UUID.Zero, false);
387 }
376 } 388 }
377 389
378 public List<EstateSettings> LoadEstateSettingsAll() 390 public List<EstateSettings> LoadEstateSettingsAll()
@@ -391,13 +403,15 @@ namespace OpenSim.Data.SQLite
391 List<int> result = new List<int>(); 403 List<int> result = new List<int>();
392 404
393 string sql = "select EstateID from estate_settings where estate_settings.EstateName = :EstateName"; 405 string sql = "select EstateID from estate_settings where estate_settings.EstateName = :EstateName";
406 IDataReader r;
394 407
395 SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); 408 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
396 409 {
397 cmd.CommandText = sql; 410 cmd.CommandText = sql;
398 cmd.Parameters.AddWithValue(":EstateName", search); 411 cmd.Parameters.AddWithValue(":EstateName", search);
399 412
400 IDataReader r = cmd.ExecuteReader(); 413 r = cmd.ExecuteReader();
414 }
401 415
402 while (r.Read()) 416 while (r.Read())
403 { 417 {
@@ -413,12 +427,14 @@ namespace OpenSim.Data.SQLite
413 List<int> result = new List<int>(); 427 List<int> result = new List<int>();
414 428
415 string sql = "select EstateID from estate_settings"; 429 string sql = "select EstateID from estate_settings";
430 IDataReader r;
416 431
417 SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); 432 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
418 433 {
419 cmd.CommandText = sql; 434 cmd.CommandText = sql;
420 435
421 IDataReader r = cmd.ExecuteReader(); 436 r = cmd.ExecuteReader();
437 }
422 438
423 while (r.Read()) 439 while (r.Read())
424 { 440 {
@@ -434,13 +450,15 @@ namespace OpenSim.Data.SQLite
434 List<int> result = new List<int>(); 450 List<int> result = new List<int>();
435 451
436 string sql = "select EstateID from estate_settings where estate_settings.EstateOwner = :EstateOwner"; 452 string sql = "select EstateID from estate_settings where estate_settings.EstateOwner = :EstateOwner";
453 IDataReader r;
437 454
438 SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); 455 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
439 456 {
440 cmd.CommandText = sql; 457 cmd.CommandText = sql;
441 cmd.Parameters.AddWithValue(":EstateOwner", ownerID); 458 cmd.Parameters.AddWithValue(":EstateOwner", ownerID);
442 459
443 IDataReader r = cmd.ExecuteReader(); 460 r = cmd.ExecuteReader();
461 }
444 462
445 while (r.Read()) 463 while (r.Read())
446 { 464 {
diff --git a/OpenSim/Data/SQLite/SQLiteFramework.cs b/OpenSim/Data/SQLite/SQLiteFramework.cs
index 1594717..35b9a2f 100644
--- a/OpenSim/Data/SQLite/SQLiteFramework.cs
+++ b/OpenSim/Data/SQLite/SQLiteFramework.cs
@@ -90,12 +90,5 @@ namespace OpenSim.Data.SQLite
90 return cmd.ExecuteReader(); 90 return cmd.ExecuteReader();
91 } 91 }
92 } 92 }
93
94 protected void CloseCommand(SqliteCommand cmd)
95 {
96 cmd.Connection.Close();
97 cmd.Connection.Dispose();
98 cmd.Dispose();
99 }
100 } 93 }
101} 94} \ No newline at end of file
diff --git a/OpenSim/Data/SQLite/SQLiteFriendsData.cs b/OpenSim/Data/SQLite/SQLiteFriendsData.cs
index 5f68977..cab85eb 100644
--- a/OpenSim/Data/SQLite/SQLiteFriendsData.cs
+++ b/OpenSim/Data/SQLite/SQLiteFriendsData.cs
@@ -53,13 +53,13 @@ namespace OpenSim.Data.SQLite
53 53
54 public FriendsData[] GetFriends(string userID) 54 public FriendsData[] GetFriends(string userID)
55 { 55 {
56 SqliteCommand cmd = new SqliteCommand(); 56 using (SqliteCommand cmd = new SqliteCommand())
57 57 {
58 cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID = :PrincipalID", m_Realm); 58 cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID = :PrincipalID", m_Realm);
59 cmd.Parameters.AddWithValue(":PrincipalID", userID.ToString()); 59 cmd.Parameters.AddWithValue(":PrincipalID", userID.ToString());
60
61 return DoQuery(cmd);
62 60
61 return DoQuery(cmd);
62 }
63 } 63 }
64 64
65 public bool Delete(UUID principalID, string friend) 65 public bool Delete(UUID principalID, string friend)
@@ -69,13 +69,14 @@ namespace OpenSim.Data.SQLite
69 69
70 public bool Delete(string principalID, string friend) 70 public bool Delete(string principalID, string friend)
71 { 71 {
72 SqliteCommand cmd = new SqliteCommand(); 72 using (SqliteCommand cmd = new SqliteCommand())
73 73 {
74 cmd.CommandText = String.Format("delete from {0} where PrincipalID = :PrincipalID and Friend = :Friend", m_Realm); 74 cmd.CommandText = String.Format("delete from {0} where PrincipalID = :PrincipalID and Friend = :Friend", m_Realm);
75 cmd.Parameters.AddWithValue(":PrincipalID", principalID.ToString()); 75 cmd.Parameters.AddWithValue(":PrincipalID", principalID.ToString());
76 cmd.Parameters.AddWithValue(":Friend", friend); 76 cmd.Parameters.AddWithValue(":Friend", friend);
77 77
78 ExecuteNonQuery(cmd, m_Connection); 78 ExecuteNonQuery(cmd, m_Connection);
79 }
79 80
80 return true; 81 return true;
81 } 82 }
diff --git a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs
index 4f977a8..9fbeb10 100644
--- a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs
+++ b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs
@@ -120,34 +120,35 @@ namespace OpenSim.Data.SQLite
120 } 120 }
121 } 121 }
122 122
123 public T[] Get(string field, string key) 123 public virtual T[] Get(string field, string key)
124 { 124 {
125 return Get(new string[] { field }, new string[] { key }); 125 return Get(new string[] { field }, new string[] { key });
126 } 126 }
127 127
128 public T[] Get(string[] fields, string[] keys) 128 public virtual T[] Get(string[] fields, string[] keys)
129 { 129 {
130 if (fields.Length != keys.Length) 130 if (fields.Length != keys.Length)
131 return new T[0]; 131 return new T[0];
132 132
133 List<string> terms = new List<string>(); 133 List<string> terms = new List<string>();
134 134
135 SqliteCommand cmd = new SqliteCommand(); 135 using (SqliteCommand cmd = new SqliteCommand())
136
137 for (int i = 0 ; i < fields.Length ; i++)
138 { 136 {
139 cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i])); 137 for (int i = 0 ; i < fields.Length ; i++)
140 terms.Add("`" + fields[i] + "` = :" + fields[i]); 138 {
141 } 139 cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i]));
140 terms.Add("`" + fields[i] + "` = :" + fields[i]);
141 }
142 142
143 string where = String.Join(" and ", terms.ToArray()); 143 string where = String.Join(" and ", terms.ToArray());
144 144
145 string query = String.Format("select * from {0} where {1}", 145 string query = String.Format("select * from {0} where {1}",
146 m_Realm, where); 146 m_Realm, where);
147 147
148 cmd.CommandText = query; 148 cmd.CommandText = query;
149 149
150 return DoQuery(cmd); 150 return DoQuery(cmd);
151 }
151 } 152 }
152 153
153 protected T[] DoQuery(SqliteCommand cmd) 154 protected T[] DoQuery(SqliteCommand cmd)
@@ -212,52 +213,54 @@ namespace OpenSim.Data.SQLite
212 return result.ToArray(); 213 return result.ToArray();
213 } 214 }
214 215
215 public T[] Get(string where) 216 public virtual T[] Get(string where)
216 { 217 {
217 SqliteCommand cmd = new SqliteCommand(); 218 using (SqliteCommand cmd = new SqliteCommand())
218 219 {
219 string query = String.Format("select * from {0} where {1}", 220 string query = String.Format("select * from {0} where {1}",
220 m_Realm, where); 221 m_Realm, where);
221 222
222 cmd.CommandText = query; 223 cmd.CommandText = query;
223 224
224 return DoQuery(cmd); 225 return DoQuery(cmd);
226 }
225 } 227 }
226 228
227 public bool Store(T row) 229 public virtual bool Store(T row)
228 { 230 {
229 SqliteCommand cmd = new SqliteCommand(); 231 using (SqliteCommand cmd = new SqliteCommand())
230
231 string query = "";
232 List<String> names = new List<String>();
233 List<String> values = new List<String>();
234
235 foreach (FieldInfo fi in m_Fields.Values)
236 { 232 {
237 names.Add(fi.Name); 233 string query = "";
238 values.Add(":" + fi.Name); 234 List<String> names = new List<String>();
239 cmd.Parameters.Add(new SqliteParameter(":" + fi.Name, fi.GetValue(row).ToString())); 235 List<String> values = new List<String>();
240 }
241 236
242 if (m_DataField != null) 237 foreach (FieldInfo fi in m_Fields.Values)
243 { 238 {
244 Dictionary<string, string> data = 239 names.Add(fi.Name);
245 (Dictionary<string, string>)m_DataField.GetValue(row); 240 values.Add(":" + fi.Name);
241 cmd.Parameters.Add(new SqliteParameter(":" + fi.Name, fi.GetValue(row).ToString()));
242 }
246 243
247 foreach (KeyValuePair<string, string> kvp in data) 244 if (m_DataField != null)
248 { 245 {
249 names.Add(kvp.Key); 246 Dictionary<string, string> data =
250 values.Add(":" + kvp.Key); 247 (Dictionary<string, string>)m_DataField.GetValue(row);
251 cmd.Parameters.Add(new SqliteParameter(":" + kvp.Key, kvp.Value)); 248
249 foreach (KeyValuePair<string, string> kvp in data)
250 {
251 names.Add(kvp.Key);
252 values.Add(":" + kvp.Key);
253 cmd.Parameters.Add(new SqliteParameter(":" + kvp.Key, kvp.Value));
254 }
252 } 255 }
253 }
254 256
255 query = String.Format("replace into {0} (`", m_Realm) + String.Join("`,`", names.ToArray()) + "`) values (" + String.Join(",", values.ToArray()) + ")"; 257 query = String.Format("replace into {0} (`", m_Realm) + String.Join("`,`", names.ToArray()) + "`) values (" + String.Join(",", values.ToArray()) + ")";
256 258
257 cmd.CommandText = query; 259 cmd.CommandText = query;
258 260
259 if (ExecuteNonQuery(cmd, m_Connection) > 0) 261 if (ExecuteNonQuery(cmd, m_Connection) > 0)
260 return true; 262 return true;
263 }
261 264
262 return false; 265 return false;
263 } 266 }
@@ -267,28 +270,29 @@ namespace OpenSim.Data.SQLite
267 return Delete(new string[] { field }, new string[] { key }); 270 return Delete(new string[] { field }, new string[] { key });
268 } 271 }
269 272
270 public bool Delete(string[] fields, string[] keys) 273 public virtual bool Delete(string[] fields, string[] keys)
271 { 274 {
272 if (fields.Length != keys.Length) 275 if (fields.Length != keys.Length)
273 return false; 276 return false;
274 277
275 List<string> terms = new List<string>(); 278 List<string> terms = new List<string>();
276 279
277 SqliteCommand cmd = new SqliteCommand(); 280 using (SqliteCommand cmd = new SqliteCommand())
278
279 for (int i = 0 ; i < fields.Length ; i++)
280 { 281 {
281 cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i])); 282 for (int i = 0 ; i < fields.Length ; i++)
282 terms.Add("`" + fields[i] + "` = :" + fields[i]); 283 {
283 } 284 cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i]));
285 terms.Add("`" + fields[i] + "` = :" + fields[i]);
286 }
284 287
285 string where = String.Join(" and ", terms.ToArray()); 288 string where = String.Join(" and ", terms.ToArray());
286 289
287 string query = String.Format("delete from {0} where {1}", m_Realm, where); 290 string query = String.Format("delete from {0} where {1}", m_Realm, where);
288 291
289 cmd.CommandText = query; 292 cmd.CommandText = query;
290 293
291 return ExecuteNonQuery(cmd, m_Connection) > 0; 294 return ExecuteNonQuery(cmd, m_Connection) > 0;
295 }
292 } 296 }
293 } 297 }
294} 298}
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index 431709f..42cd59d 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -1366,6 +1366,13 @@ namespace OpenSim.Data.SQLite
1366 createCol(land, "UserLookAtZ", typeof(Double)); 1366 createCol(land, "UserLookAtZ", typeof(Double));
1367 createCol(land, "AuthbuyerID", typeof(String)); 1367 createCol(land, "AuthbuyerID", typeof(String));
1368 createCol(land, "OtherCleanTime", typeof(Int32)); 1368 createCol(land, "OtherCleanTime", typeof(Int32));
1369 createCol(land, "Dwell", typeof(Int32));
1370 createCol(land, "MediaType", typeof(String));
1371 createCol(land, "MediaDescription", typeof(String));
1372 createCol(land, "MediaSize", typeof(String));
1373 createCol(land, "MediaLoop", typeof(Boolean));
1374 createCol(land, "ObscureMedia", typeof(Boolean));
1375 createCol(land, "ObscureMusic", typeof(Boolean));
1369 1376
1370 land.PrimaryKey = new DataColumn[] { land.Columns["UUID"] }; 1377 land.PrimaryKey = new DataColumn[] { land.Columns["UUID"] };
1371 1378
@@ -1781,9 +1788,16 @@ namespace OpenSim.Data.SQLite
1781 newData.PassHours = Convert.ToSingle(row["PassHours"]); 1788 newData.PassHours = Convert.ToSingle(row["PassHours"]);
1782 newData.PassPrice = Convert.ToInt32(row["PassPrice"]); 1789 newData.PassPrice = Convert.ToInt32(row["PassPrice"]);
1783 newData.SnapshotID = (UUID)(String)row["SnapshotUUID"]; 1790 newData.SnapshotID = (UUID)(String)row["SnapshotUUID"];
1791 newData.Dwell = Convert.ToInt32(row["Dwell"]);
1792 newData.MediaType = (String)row["MediaType"];
1793 newData.MediaDescription = (String)row["MediaDescription"];
1794 newData.MediaWidth = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[0]);
1795 newData.MediaHeight = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[1]);
1796 newData.MediaLoop = Convert.ToBoolean(row["MediaLoop"]);
1797 newData.ObscureMedia = Convert.ToBoolean(row["ObscureMedia"]);
1798 newData.ObscureMusic = Convert.ToBoolean(row["ObscureMusic"]);
1784 try 1799 try
1785 { 1800 {
1786
1787 newData.UserLocation = 1801 newData.UserLocation =
1788 new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), 1802 new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]),
1789 Convert.ToSingle(row["UserLocationZ"])); 1803 Convert.ToSingle(row["UserLocationZ"]));
@@ -2195,12 +2209,13 @@ namespace OpenSim.Data.SQLite
2195 row["UserLookAtZ"] = land.UserLookAt.Z; 2209 row["UserLookAtZ"] = land.UserLookAt.Z;
2196 row["AuthbuyerID"] = land.AuthBuyerID.ToString(); 2210 row["AuthbuyerID"] = land.AuthBuyerID.ToString();
2197 row["OtherCleanTime"] = land.OtherCleanTime; 2211 row["OtherCleanTime"] = land.OtherCleanTime;
2212 row["Dwell"] = land.Dwell;
2198 row["MediaType"] = land.MediaType; 2213 row["MediaType"] = land.MediaType;
2199 row["MediaDescription"] = land.MediaDescription; 2214 row["MediaDescription"] = land.MediaDescription;
2200 row["MediaSize"] = land.MediaWidth.ToString() + "," + land.MediaHeight.ToString(); 2215 row["MediaSize"] = String.Format("{0},{1}", land.MediaWidth, land.MediaHeight);
2201 row["MediaLoop"] = land.MediaLoop.ToString(); 2216 row["MediaLoop"] = land.MediaLoop;
2202 row["ObscureMusic"] = land.ObscureMusic.ToString(); 2217 row["ObscureMusic"] = land.ObscureMusic;
2203 row["ObscureMedia"] = land.ObscureMedia.ToString(); 2218 row["ObscureMedia"] = land.ObscureMedia;
2204 } 2219 }
2205 2220
2206 /// <summary> 2221 /// <summary>
diff --git a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs
index 4d580c0..91d62ce 100644
--- a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs
+++ b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs
@@ -66,20 +66,21 @@ namespace OpenSim.Data.SQLite
66 if (words.Length > 2) 66 if (words.Length > 2)
67 return new UserAccountData[0]; 67 return new UserAccountData[0];
68 68
69 SqliteCommand cmd = new SqliteCommand(); 69 using (SqliteCommand cmd = new SqliteCommand())
70
71 if (words.Length == 1)
72 {
73 cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')",
74 m_Realm, scopeID.ToString(), words[0]);
75 }
76 else
77 { 70 {
78 cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{3}%')", 71 if (words.Length == 1)
79 m_Realm, scopeID.ToString(), words[0], words[1]); 72 {
80 } 73 cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')",
74 m_Realm, scopeID.ToString(), words[0]);
75 }
76 else
77 {
78 cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{3}%')",
79 m_Realm, scopeID.ToString(), words[0], words[1]);
80 }
81 81
82 return DoQuery(cmd); 82 return DoQuery(cmd);
83 }
83 } 84 }
84 85
85 public UserAccountData[] GetUsersWhere(UUID scopeID, string where) 86 public UserAccountData[] GetUsersWhere(UUID scopeID, string where)
diff --git a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs
index 1f36986..2a0a8f6 100644
--- a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs
+++ b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Data.SQLite
47 { 47 {
48// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 private SQLiteGenericTableHandler<XInventoryFolder> m_Folders; 50 private SqliteFolderHandler m_Folders;
51 private SqliteItemHandler m_Items; 51 private SqliteItemHandler m_Items;
52 52
53 public SQLiteXInventoryData(string conn, string realm) 53 public SQLiteXInventoryData(string conn, string realm)
@@ -55,7 +55,7 @@ namespace OpenSim.Data.SQLite
55 if (Util.IsWindows()) 55 if (Util.IsWindows())
56 Util.LoadArchSpecificWindowsDll("sqlite3.dll"); 56 Util.LoadArchSpecificWindowsDll("sqlite3.dll");
57 57
58 m_Folders = new SQLiteGenericTableHandler<XInventoryFolder>( 58 m_Folders = new SqliteFolderHandler(
59 conn, "inventoryfolders", "XInventoryStore"); 59 conn, "inventoryfolders", "XInventoryStore");
60 m_Items = new SqliteItemHandler( 60 m_Items = new SqliteItemHandler(
61 conn, "inventoryitems", String.Empty); 61 conn, "inventoryitems", String.Empty);
@@ -114,6 +114,11 @@ namespace OpenSim.Data.SQLite
114 return m_Items.MoveItem(id, newParent); 114 return m_Items.MoveItem(id, newParent);
115 } 115 }
116 116
117 public bool MoveFolder(string id, string newParent)
118 {
119 return m_Folders.MoveFolder(id, newParent);
120 }
121
117 public XInventoryItem[] GetActiveGestures(UUID principalID) 122 public XInventoryItem[] GetActiveGestures(UUID principalID)
118 { 123 {
119 return m_Items.GetActiveGestures(principalID); 124 return m_Items.GetActiveGestures(principalID);
@@ -125,44 +130,106 @@ namespace OpenSim.Data.SQLite
125 } 130 }
126 } 131 }
127 132
128 public class SqliteItemHandler : SQLiteGenericTableHandler<XInventoryItem> 133 public class SqliteItemHandler : SqliteInventoryHandler<XInventoryItem>
129 { 134 {
130 public SqliteItemHandler(string c, string t, string m) : 135 public SqliteItemHandler(string c, string t, string m) :
131 base(c, t, m) 136 base(c, t, m)
132 { 137 {
133 } 138 }
134 139
140 public override bool Store(XInventoryItem item)
141 {
142 if (!base.Store(item))
143 return false;
144
145 IncrementFolderVersion(item.parentFolderID);
146
147 return true;
148 }
149
150 public override bool Delete(string field, string val)
151 {
152 XInventoryItem[] retrievedItems = Get(new string[] { field }, new string[] { val });
153 if (retrievedItems.Length == 0)
154 return false;
155
156 if (!base.Delete(field, val))
157 return false;
158
159 // Don't increment folder version here since Delete(string, string) calls Delete(string[], string[])
160// IncrementFolderVersion(retrievedItems[0].parentFolderID);
161
162 return true;
163 }
164
165 public override bool Delete(string[] fields, string[] vals)
166 {
167 XInventoryItem[] retrievedItems = Get(fields, vals);
168 if (retrievedItems.Length == 0)
169 return false;
170
171 if (!base.Delete(fields, vals))
172 return false;
173
174 HashSet<UUID> deletedItemFolderUUIDs = new HashSet<UUID>();
175
176 Array.ForEach<XInventoryItem>(retrievedItems, i => deletedItemFolderUUIDs.Add(i.parentFolderID));
177
178 foreach (UUID deletedItemFolderUUID in deletedItemFolderUUIDs)
179 IncrementFolderVersion(deletedItemFolderUUID);
180
181 return true;
182 }
183
135 public bool MoveItem(string id, string newParent) 184 public bool MoveItem(string id, string newParent)
136 { 185 {
137 SqliteCommand cmd = new SqliteCommand(); 186 XInventoryItem[] retrievedItems = Get(new string[] { "inventoryID" }, new string[] { id });
187 if (retrievedItems.Length == 0)
188 return false;
189
190 UUID oldParent = retrievedItems[0].parentFolderID;
191
192 using (SqliteCommand cmd = new SqliteCommand())
193 {
194 cmd.CommandText = String.Format("update {0} set parentFolderID = :ParentFolderID where inventoryID = :InventoryID", m_Realm);
195 cmd.Parameters.Add(new SqliteParameter(":ParentFolderID", newParent));
196 cmd.Parameters.Add(new SqliteParameter(":InventoryID", id));
138 197
139 cmd.CommandText = String.Format("update {0} set parentFolderID = :ParentFolderID where inventoryID = :InventoryID", m_Realm); 198 if (ExecuteNonQuery(cmd, m_Connection) == 0)
140 cmd.Parameters.Add(new SqliteParameter(":ParentFolderID", newParent)); 199 return false;
141 cmd.Parameters.Add(new SqliteParameter(":InventoryID", id)); 200 }
201
202 IncrementFolderVersion(oldParent);
203 IncrementFolderVersion(newParent);
142 204
143 return ExecuteNonQuery(cmd, m_Connection) == 0 ? false : true; 205 return true;
144 } 206 }
145 207
146 public XInventoryItem[] GetActiveGestures(UUID principalID) 208 public XInventoryItem[] GetActiveGestures(UUID principalID)
147 { 209 {
148 SqliteCommand cmd = new SqliteCommand(); 210 using (SqliteCommand cmd = new SqliteCommand())
149 cmd.CommandText = String.Format("select * from inventoryitems where avatarId = :uuid and assetType = :type and flags = 1", m_Realm); 211 {
212 cmd.CommandText = String.Format("select * from inventoryitems where avatarId = :uuid and assetType = :type and flags = 1", m_Realm);
150 213
151 cmd.Parameters.Add(new SqliteParameter(":uuid", principalID.ToString())); 214 cmd.Parameters.Add(new SqliteParameter(":uuid", principalID.ToString()));
152 cmd.Parameters.Add(new SqliteParameter(":type", (int)AssetType.Gesture)); 215 cmd.Parameters.Add(new SqliteParameter(":type", (int)AssetType.Gesture));
153 216
154 return DoQuery(cmd); 217 return DoQuery(cmd);
218 }
155 } 219 }
156 220
157 public int GetAssetPermissions(UUID principalID, UUID assetID) 221 public int GetAssetPermissions(UUID principalID, UUID assetID)
158 { 222 {
159 SqliteCommand cmd = new SqliteCommand(); 223 IDataReader reader;
160 224
161 cmd.CommandText = String.Format("select inventoryCurrentPermissions from inventoryitems where avatarID = :PrincipalID and assetID = :AssetID", m_Realm); 225 using (SqliteCommand cmd = new SqliteCommand())
162 cmd.Parameters.Add(new SqliteParameter(":PrincipalID", principalID.ToString())); 226 {
163 cmd.Parameters.Add(new SqliteParameter(":AssetID", assetID.ToString())); 227 cmd.CommandText = String.Format("select inventoryCurrentPermissions from inventoryitems where avatarID = :PrincipalID and assetID = :AssetID", m_Realm);
228 cmd.Parameters.Add(new SqliteParameter(":PrincipalID", principalID.ToString()));
229 cmd.Parameters.Add(new SqliteParameter(":AssetID", assetID.ToString()));
164 230
165 IDataReader reader = ExecuteReader(cmd, m_Connection); 231 reader = ExecuteReader(cmd, m_Connection);
232 }
166 233
167 int perms = 0; 234 int perms = 0;
168 235
@@ -177,4 +244,81 @@ namespace OpenSim.Data.SQLite
177 return perms; 244 return perms;
178 } 245 }
179 } 246 }
180} 247
248 public class SqliteFolderHandler : SqliteInventoryHandler<XInventoryFolder>
249 {
250 public SqliteFolderHandler(string c, string t, string m) :
251 base(c, t, m)
252 {
253 }
254
255 public override bool Store(XInventoryFolder folder)
256 {
257 if (!base.Store(folder))
258 return false;
259
260 IncrementFolderVersion(folder.parentFolderID);
261
262 return true;
263 }
264
265 public bool MoveFolder(string id, string newParentFolderID)
266 {
267 XInventoryFolder[] folders = Get(new string[] { "folderID" }, new string[] { id });
268
269 if (folders.Length == 0)
270 return false;
271
272 UUID oldParentFolderUUID = folders[0].parentFolderID;
273
274 using (SqliteCommand cmd = new SqliteCommand())
275 {
276 cmd.CommandText = String.Format("update {0} set parentFolderID = :ParentFolderID where folderID = :FolderID", m_Realm);
277 cmd.Parameters.Add(new SqliteParameter(":ParentFolderID", newParentFolderID));
278 cmd.Parameters.Add(new SqliteParameter(":FolderID", id));
279
280 if (ExecuteNonQuery(cmd, m_Connection) == 0)
281 return false;
282 }
283
284 IncrementFolderVersion(oldParentFolderUUID);
285 IncrementFolderVersion(newParentFolderID);
286
287 return true;
288 }
289
290 }
291
292 public class SqliteInventoryHandler<T> : SQLiteGenericTableHandler<T> where T: class, new()
293 {
294 public SqliteInventoryHandler(string c, string t, string m) : base(c, t, m) {}
295
296 protected bool IncrementFolderVersion(UUID folderID)
297 {
298 return IncrementFolderVersion(folderID.ToString());
299 }
300
301 protected bool IncrementFolderVersion(string folderID)
302 {
303// m_log.DebugFormat("[MYSQL ITEM HANDLER]: Incrementing version on folder {0}", folderID);
304// Util.PrintCallStack();
305
306 using (SqliteCommand cmd = new SqliteCommand())
307 {
308 cmd.CommandText = "update inventoryfolders set version=version+1 where folderID = ?folderID";
309 cmd.Parameters.Add(new SqliteParameter(":folderID", folderID));
310
311 try
312 {
313 cmd.ExecuteNonQuery();
314 }
315 catch (Exception)
316 {
317 return false;
318 }
319 }
320
321 return true;
322 }
323 }
324} \ No newline at end of file
diff --git a/OpenSim/Framework/AssemblyInfo.cs b/OpenSim/Framework/AssemblyInfo.cs
index adeaeb2..02986d5 100644
--- a/OpenSim/Framework/AssemblyInfo.cs
+++ b/OpenSim/Framework/AssemblyInfo.cs
@@ -59,5 +59,5 @@ using System.Runtime.InteropServices;
59// Revision 59// Revision
60// 60//
61 61
62[assembly : AssemblyVersion("0.6.5.*")] 62[assembly : AssemblyVersion("0.7.5.*")]
63[assembly : AssemblyFileVersion("0.6.5.0")] \ No newline at end of file 63[assembly : AssemblyFileVersion("0.6.5.0")] \ No newline at end of file
diff --git a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..0498ed4
--- /dev/null
+++ b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Framework.AssetLoader.Filesystem")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("8cb9cf69-4771-4d3a-a2ba-bac7230de326")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/AssetPermissions.cs b/OpenSim/Framework/AssetPermissions.cs
new file mode 100644
index 0000000..4a905c2
--- /dev/null
+++ b/OpenSim/Framework/AssetPermissions.cs
@@ -0,0 +1,84 @@
1using System;
2using System.Collections.Generic;
3using System.Reflection;
4
5using Nini.Config;
6using log4net;
7
8using OpenMetaverse;
9
10namespace OpenSim.Framework
11{
12 public class AssetPermissions
13 {
14 private static readonly ILog m_log =
15 LogManager.GetLogger(
16 MethodBase.GetCurrentMethod().DeclaringType);
17
18 private bool[] m_DisallowExport, m_DisallowImport;
19 private string[] m_AssetTypeNames;
20
21 public AssetPermissions(IConfig config)
22 {
23 Type enumType = typeof(AssetType);
24 m_AssetTypeNames = Enum.GetNames(enumType);
25 for (int i = 0; i < m_AssetTypeNames.Length; i++)
26 m_AssetTypeNames[i] = m_AssetTypeNames[i].ToLower();
27 int n = Enum.GetValues(enumType).Length;
28 m_DisallowExport = new bool[n];
29 m_DisallowImport = new bool[n];
30
31 LoadPermsFromConfig(config, "DisallowExport", m_DisallowExport);
32 LoadPermsFromConfig(config, "DisallowImport", m_DisallowImport);
33
34 }
35
36 private void LoadPermsFromConfig(IConfig assetConfig, string variable, bool[] bitArray)
37 {
38 if (assetConfig == null)
39 return;
40
41 string perms = assetConfig.GetString(variable, String.Empty);
42 string[] parts = perms.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
43 foreach (string s in parts)
44 {
45 int index = Array.IndexOf(m_AssetTypeNames, s.Trim().ToLower());
46 if (index >= 0)
47 bitArray[index] = true;
48 else
49 m_log.WarnFormat("[Asset Permissions]: Invalid AssetType {0}", s);
50 }
51
52 }
53
54 public bool AllowedExport(sbyte type)
55 {
56 string assetTypeName = ((AssetType)type).ToString();
57
58 int index = Array.IndexOf(m_AssetTypeNames, assetTypeName.ToLower());
59 if (index >= 0 && m_DisallowExport[index])
60 {
61 m_log.DebugFormat("[Asset Permissions]: Export denied: configuration does not allow export of AssetType {0}", assetTypeName);
62 return false;
63 }
64
65 return true;
66 }
67
68 public bool AllowedImport(sbyte type)
69 {
70 string assetTypeName = ((AssetType)type).ToString();
71
72 int index = Array.IndexOf(m_AssetTypeNames, assetTypeName.ToLower());
73 if (index >= 0 && m_DisallowImport[index])
74 {
75 m_log.DebugFormat("[Asset Permissions]: Import denied: configuration does not allow import of AssetType {0}", assetTypeName);
76 return false;
77 }
78
79 return true;
80 }
81
82
83 }
84}
diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs
index c5d9641..1638541 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -358,6 +358,9 @@ namespace OpenSim.Framework
358 SetVisualParams(visualParams); 358 SetVisualParams(visualParams);
359 } 359 }
360 360
361 /// <summary>
362 /// Set avatar height by a calculation based on their visual parameters.
363 /// </summary>
361 public virtual void SetHeight() 364 public virtual void SetHeight()
362 { 365 {
363 // Start with shortest possible female avatar height 366 // Start with shortest possible female avatar height
diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs
index 79e20fc..31cab4a 100644
--- a/OpenSim/Framework/Cache.cs
+++ b/OpenSim/Framework/Cache.cs
@@ -199,7 +199,14 @@ namespace OpenSim.Framework
199 // 199 //
200 public class Cache 200 public class Cache
201 { 201 {
202 /// <summary>
203 /// Must only be accessed under lock.
204 /// </summary>
202 private List<CacheItemBase> m_Index = new List<CacheItemBase>(); 205 private List<CacheItemBase> m_Index = new List<CacheItemBase>();
206
207 /// <summary>
208 /// Must only be accessed under m_Index lock.
209 /// </summary>
203 private Dictionary<string, CacheItemBase> m_Lookup = 210 private Dictionary<string, CacheItemBase> m_Lookup =
204 new Dictionary<string, CacheItemBase>(); 211 new Dictionary<string, CacheItemBase>();
205 212
@@ -320,19 +327,19 @@ namespace OpenSim.Framework
320 { 327 {
321 if (m_Lookup.ContainsKey(index)) 328 if (m_Lookup.ContainsKey(index))
322 item = m_Lookup[index]; 329 item = m_Lookup[index];
323 }
324 330
325 if (item == null) 331 if (item == null)
326 { 332 {
333 Expire(true);
334 return null;
335 }
336
337 item.hits++;
338 item.lastUsed = DateTime.Now;
339
327 Expire(true); 340 Expire(true);
328 return null;
329 } 341 }
330 342
331 item.hits++;
332 item.lastUsed = DateTime.Now;
333
334 Expire(true);
335
336 return item; 343 return item;
337 } 344 }
338 345
@@ -385,7 +392,10 @@ namespace OpenSim.Framework
385 // 392 //
386 public Object Find(Predicate<CacheItemBase> d) 393 public Object Find(Predicate<CacheItemBase> d)
387 { 394 {
388 CacheItemBase item = m_Index.Find(d); 395 CacheItemBase item;
396
397 lock (m_Index)
398 item = m_Index.Find(d);
389 399
390 if (item == null) 400 if (item == null)
391 return null; 401 return null;
@@ -419,12 +429,12 @@ namespace OpenSim.Framework
419 public virtual void Store(string index, Object data, Type container, 429 public virtual void Store(string index, Object data, Type container,
420 Object[] parameters) 430 Object[] parameters)
421 { 431 {
422 Expire(false);
423
424 CacheItemBase item; 432 CacheItemBase item;
425 433
426 lock (m_Index) 434 lock (m_Index)
427 { 435 {
436 Expire(false);
437
428 if (m_Index.Contains(new CacheItemBase(index))) 438 if (m_Index.Contains(new CacheItemBase(index)))
429 { 439 {
430 if ((m_Flags & CacheFlags.AllowUpdate) != 0) 440 if ((m_Flags & CacheFlags.AllowUpdate) != 0)
@@ -450,9 +460,17 @@ namespace OpenSim.Framework
450 m_Index.Add(item); 460 m_Index.Add(item);
451 m_Lookup[index] = item; 461 m_Lookup[index] = item;
452 } 462 }
463
453 item.Store(data); 464 item.Store(data);
454 } 465 }
455 466
467 /// <summary>
468 /// Expire items as appropriate.
469 /// </summary>
470 /// <remarks>
471 /// Callers must lock m_Index.
472 /// </remarks>
473 /// <param name='getting'></param>
456 protected virtual void Expire(bool getting) 474 protected virtual void Expire(bool getting)
457 { 475 {
458 if (getting && (m_Strategy == CacheStrategy.Aggressive)) 476 if (getting && (m_Strategy == CacheStrategy.Aggressive))
@@ -475,12 +493,10 @@ namespace OpenSim.Framework
475 493
476 switch (m_Strategy) 494 switch (m_Strategy)
477 { 495 {
478 case CacheStrategy.Aggressive: 496 case CacheStrategy.Aggressive:
479 if (Count < Size) 497 if (Count < Size)
480 return; 498 return;
481 499
482 lock (m_Index)
483 {
484 m_Index.Sort(new SortLRU()); 500 m_Index.Sort(new SortLRU());
485 m_Index.Reverse(); 501 m_Index.Reverse();
486 502
@@ -490,7 +506,7 @@ namespace OpenSim.Framework
490 506
491 ExpireDelegate doExpire = OnExpire; 507 ExpireDelegate doExpire = OnExpire;
492 508
493 if (doExpire != null) 509 if (doExpire != null)
494 { 510 {
495 List<CacheItemBase> candidates = 511 List<CacheItemBase> candidates =
496 m_Index.GetRange(target, Count - target); 512 m_Index.GetRange(target, Count - target);
@@ -513,27 +529,34 @@ namespace OpenSim.Framework
513 foreach (CacheItemBase item in m_Index) 529 foreach (CacheItemBase item in m_Index)
514 m_Lookup[item.uuid] = item; 530 m_Lookup[item.uuid] = item;
515 } 531 }
516 } 532
517 break; 533 break;
518 default: 534
519 break; 535 default:
536 break;
520 } 537 }
521 } 538 }
522 539
523 public void Invalidate(string uuid) 540 public void Invalidate(string uuid)
524 { 541 {
525 if (!m_Lookup.ContainsKey(uuid)) 542 lock (m_Index)
526 return; 543 {
544 if (!m_Lookup.ContainsKey(uuid))
545 return;
527 546
528 CacheItemBase item = m_Lookup[uuid]; 547 CacheItemBase item = m_Lookup[uuid];
529 m_Lookup.Remove(uuid); 548 m_Lookup.Remove(uuid);
530 m_Index.Remove(item); 549 m_Index.Remove(item);
550 }
531 } 551 }
532 552
533 public void Clear() 553 public void Clear()
534 { 554 {
535 m_Index.Clear(); 555 lock (m_Index)
536 m_Lookup.Clear(); 556 {
557 m_Index.Clear();
558 m_Lookup.Clear();
559 }
537 } 560 }
538 } 561 }
539} 562} \ No newline at end of file
diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs
index e718aa6..8c32734 100644
--- a/OpenSim/Framework/ChildAgentDataUpdate.cs
+++ b/OpenSim/Framework/ChildAgentDataUpdate.cs
@@ -312,6 +312,7 @@ namespace OpenSim.Framework
312 public AgentGroupData[] Groups; 312 public AgentGroupData[] Groups;
313 public Animation[] Anims; 313 public Animation[] Anims;
314 public Animation DefaultAnim = null; 314 public Animation DefaultAnim = null;
315 public Animation AnimState = null;
315 316
316 public UUID GranterID; 317 public UUID GranterID;
317 public UUID ParentPart; 318 public UUID ParentPart;
@@ -403,6 +404,11 @@ namespace OpenSim.Framework
403 args["default_animation"] = DefaultAnim.PackUpdateMessage(); 404 args["default_animation"] = DefaultAnim.PackUpdateMessage();
404 } 405 }
405 406
407 if (AnimState != null)
408 {
409 args["animation_state"] = AnimState.PackUpdateMessage();
410 }
411
406 if (Appearance != null) 412 if (Appearance != null)
407 args["packed_appearance"] = Appearance.Pack(); 413 args["packed_appearance"] = Appearance.Pack();
408 414
@@ -612,6 +618,18 @@ namespace OpenSim.Framework
612 } 618 }
613 } 619 }
614 620
621 if (args["animation_state"] != null)
622 {
623 try
624 {
625 AnimState = new Animation((OSDMap)args["animation_state"]);
626 }
627 catch
628 {
629 AnimState = null;
630 }
631 }
632
615 //if ((args["agent_textures"] != null) && (args["agent_textures"]).Type == OSDType.Array) 633 //if ((args["agent_textures"] != null) && (args["agent_textures"]).Type == OSDType.Array)
616 //{ 634 //{
617 // OSDArray textures = (OSDArray)(args["agent_textures"]); 635 // OSDArray textures = (OSDArray)(args["agent_textures"]);
diff --git a/OpenSim/Framework/Client/IClientChat.cs b/OpenSim/Framework/Client/IClientChat.cs
index 078ea9b..86b1faa 100644
--- a/OpenSim/Framework/Client/IClientChat.cs
+++ b/OpenSim/Framework/Client/IClientChat.cs
@@ -33,7 +33,8 @@ namespace OpenSim.Framework.Client
33 { 33 {
34 event ChatMessage OnChatFromClient; 34 event ChatMessage OnChatFromClient;
35 35
36 void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, 36 void SendChatMessage(
37 byte audible); 37 string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source,
38 byte audible);
38 } 39 }
39} 40} \ No newline at end of file
diff --git a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
index 2df6ace..6d1c03a 100644
--- a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
@@ -32,12 +32,12 @@ using System.Runtime.InteropServices;
32// set of attributes. Change these attribute values to modify the information 32// set of attributes. Change these attribute values to modify the information
33// associated with an assembly. 33// associated with an assembly.
34 34
35[assembly : AssemblyTitle("OpenGrid.Framework.Communications")] 35[assembly : AssemblyTitle("OpenSim.Framework.Communications")]
36[assembly : AssemblyDescription("")] 36[assembly : AssemblyDescription("")]
37[assembly : AssemblyConfiguration("")] 37[assembly : AssemblyConfiguration("")]
38[assembly : AssemblyCompany("http://opensimulator.org")] 38[assembly : AssemblyCompany("http://opensimulator.org")]
39[assembly : AssemblyProduct("OpenGrid.Framework.Communications")] 39[assembly : AssemblyProduct("OpenSim")]
40[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")] 40[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")]
41[assembly : AssemblyTrademark("")] 41[assembly : AssemblyTrademark("")]
42[assembly : AssemblyCulture("")] 42[assembly : AssemblyCulture("")]
43 43
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.6.5.*")] 64[assembly : AssemblyVersion("0.7.5.*")]
65[assembly : AssemblyFileVersion("0.6.5.0")] 65[assembly : AssemblyFileVersion("0.6.5.0")]
diff --git a/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs b/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..0674656
--- /dev/null
+++ b/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Framework.Configuration.HTTP")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator develoeprs")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("cb78b672-d000-4f93-88f9-dae151cc0061")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs b/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1095b23
--- /dev/null
+++ b/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Framework.Configuration.XML")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("eeb880df-0112-4c3d-87ed-b2108d614c55")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Console/AssemblyInfo.cs b/OpenSim/Framework/Console/AssemblyInfo.cs
index 75e35bf..37c7304 100644
--- a/OpenSim/Framework/Console/AssemblyInfo.cs
+++ b/OpenSim/Framework/Console/AssemblyInfo.cs
@@ -39,7 +39,7 @@ using System.Runtime.InteropServices;
39[assembly: AssemblyConfiguration("")] 39[assembly: AssemblyConfiguration("")]
40[assembly: AssemblyCompany("http://opensimulator.org")] 40[assembly: AssemblyCompany("http://opensimulator.org")]
41[assembly : AssemblyProduct("ServerConsole")] 41[assembly : AssemblyProduct("ServerConsole")]
42[assembly: AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")] 42[assembly: AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")]
43[assembly: AssemblyTrademark("")] 43[assembly: AssemblyTrademark("")]
44[assembly: AssemblyCulture("")] 44[assembly: AssemblyCulture("")]
45 45
@@ -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.6.5.*")] 58[assembly : AssemblyVersion("0.7.5.*")]
diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs
index bd23d1c..d703d78 100644
--- a/OpenSim/Framework/Console/CommandConsole.cs
+++ b/OpenSim/Framework/Console/CommandConsole.cs
@@ -83,7 +83,8 @@ namespace OpenSim.Framework.Console
83 = "To enter an argument that contains spaces, surround the argument with double quotes.\nFor example, show object name \"My long object name\"\n"; 83 = "To enter an argument that contains spaces, surround the argument with double quotes.\nFor example, show object name \"My long object name\"\n";
84 84
85 public const string ItemHelpText 85 public const string ItemHelpText
86 = "For more information, type 'help <item>' where <item> is one of the following:"; 86= @"For more information, type 'help' to get a list of all commands,
87 or type help <item>' where <item> is one of the following:";
87 88
88 /// <value> 89 /// <value>
89 /// Commands organized by keyword in a tree 90 /// Commands organized by keyword in a tree
@@ -114,6 +115,12 @@ namespace OpenSim.Framework.Console
114 { 115 {
115 help.Add(""); // Will become a newline. 116 help.Add(""); // Will become a newline.
116 help.Add(GeneralHelpText); 117 help.Add(GeneralHelpText);
118 help.AddRange(CollectAllCommandsHelp());
119 }
120 else if (helpParts.Count == 1 && helpParts[0] == "categories")
121 {
122 help.Add(""); // Will become a newline.
123 help.Add(GeneralHelpText);
117 help.Add(ItemHelpText); 124 help.Add(ItemHelpText);
118 help.AddRange(CollectModulesHelp(tree)); 125 help.AddRange(CollectModulesHelp(tree));
119 } 126 }
@@ -124,6 +131,31 @@ namespace OpenSim.Framework.Console
124 131
125 return help; 132 return help;
126 } 133 }
134
135 /// <summary>
136 /// Collects the help from all commands and return in alphabetical order.
137 /// </summary>
138 /// <returns></returns>
139 private List<string> CollectAllCommandsHelp()
140 {
141 List<string> help = new List<string>();
142
143 lock (m_modulesCommands)
144 {
145 foreach (List<CommandInfo> commands in m_modulesCommands.Values)
146 {
147 foreach (CommandInfo c in commands)
148 {
149 if (c.long_help != String.Empty)
150 help.Add(string.Format("{0} - {1}", c.help_text, c.long_help));
151 }
152 }
153 }
154
155 help.Sort();
156
157 return help;
158 }
127 159
128 /// <summary> 160 /// <summary>
129 /// See if we can find the requested command in order to display longer help 161 /// See if we can find the requested command in order to display longer help
@@ -711,7 +743,7 @@ namespace OpenSim.Framework.Console
711 /// </summary> 743 /// </summary>
712 public void Prompt() 744 public void Prompt()
713 { 745 {
714 string line = ReadLine(m_defaultPrompt + "# ", true, true); 746 string line = ReadLine(DefaultPrompt + "# ", true, true);
715 747
716 if (line != String.Empty) 748 if (line != String.Empty)
717 Output("Invalid command"); 749 Output("Invalid command");
diff --git a/OpenSim/Framework/Console/ConsoleBase.cs b/OpenSim/Framework/Console/ConsoleBase.cs
index 4b375d9..2d8e723 100755
--- a/OpenSim/Framework/Console/ConsoleBase.cs
+++ b/OpenSim/Framework/Console/ConsoleBase.cs
@@ -43,15 +43,7 @@ namespace OpenSim.Framework.Console
43 43
44 public object ConsoleScene { get; set; } 44 public object ConsoleScene { get; set; }
45 45
46 /// <summary> 46 public string DefaultPrompt { get; set; }
47 /// The default prompt text.
48 /// </summary>
49 public string DefaultPrompt
50 {
51 set { m_defaultPrompt = value; }
52 get { return m_defaultPrompt; }
53 }
54 protected string m_defaultPrompt;
55 47
56 public ConsoleBase(string defaultPrompt) 48 public ConsoleBase(string defaultPrompt)
57 { 49 {
diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs
new file mode 100644
index 0000000..16a63e0
--- /dev/null
+++ b/OpenSim/Framework/Console/ConsoleUtil.cs
@@ -0,0 +1,228 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Linq;
32using System.Reflection;
33using log4net;
34using OpenMetaverse;
35
36namespace OpenSim.Framework.Console
37{
38 public class ConsoleUtil
39 {
40 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
42 public const int LocalIdNotFound = 0;
43
44 /// <summary>
45 /// Used by modules to display stock co-ordinate help, though possibly this should be under some general section
46 /// rather than in each help summary.
47 /// </summary>
48 public const string CoordHelp
49 = @"Each component of the coord is comma separated. There must be no spaces between the commas.
50 If you don't care about the z component you can simply omit it.
51 If you don't care about the x or y components then you can leave them blank (though a comma is still required)
52 If you want to specify the maxmimum value of a component then you can use ~ instead of a number
53 If you want to specify the minimum value of a component then you can use -~ instead of a number
54 e.g.
55 delete object pos 20,20,20 to 40,40,40
56 delete object pos 20,20 to 40,40
57 delete object pos ,20,20 to ,40,40
58 delete object pos ,,30 to ,,~
59 delete object pos ,,-~ to ,,30";
60
61 public const string MinRawConsoleVectorValue = "-~";
62 public const string MaxRawConsoleVectorValue = "~";
63
64 public const string VectorSeparator = ",";
65 public static char[] VectorSeparatorChars = VectorSeparator.ToCharArray();
66
67 /// <summary>
68 /// Check if the given file path exists.
69 /// </summary>
70 /// <remarks>If not, warning is printed to the given console.</remarks>
71 /// <returns>true if the file does not exist, false otherwise.</returns>
72 /// <param name='console'></param>
73 /// <param name='path'></param>
74 public static bool CheckFileDoesNotExist(ICommandConsole console, string path)
75 {
76 if (File.Exists(path))
77 {
78 console.OutputFormat("File {0} already exists. Please move or remove it.", path);
79 return false;
80 }
81
82 return true;
83 }
84
85 /// <summary>
86 /// Try to parse a console UUID from the console.
87 /// </summary>
88 /// <remarks>
89 /// Will complain to the console if parsing fails.
90 /// </remarks>
91 /// <returns></returns>
92 /// <param name='console'>If null then no complaint is printed.</param>
93 /// <param name='rawUuid'></param>
94 /// <param name='uuid'></param>
95 public static bool TryParseConsoleUuid(ICommandConsole console, string rawUuid, out UUID uuid)
96 {
97 if (!UUID.TryParse(rawUuid, out uuid))
98 {
99 if (console != null)
100 console.OutputFormat("{0} is not a valid uuid", rawUuid);
101
102 return false;
103 }
104
105 return true;
106 }
107
108 public static bool TryParseConsoleLocalId(ICommandConsole console, string rawLocalId, out uint localId)
109 {
110 if (!uint.TryParse(rawLocalId, out localId))
111 {
112 if (console != null)
113 console.OutputFormat("{0} is not a valid local id", localId);
114
115 return false;
116 }
117
118 if (localId == 0)
119 {
120 if (console != null)
121 console.OutputFormat("{0} is not a valid local id - it must be greater than 0", localId);
122
123 return false;
124 }
125
126 return true;
127 }
128
129 /// <summary>
130 /// Tries to parse the input as either a UUID or a local ID.
131 /// </summary>
132 /// <returns>true if parsing succeeded, false otherwise.</returns>
133 /// <param name='console'></param>
134 /// <param name='rawId'></param>
135 /// <param name='uuid'></param>
136 /// <param name='localId'>
137 /// Will be set to ConsoleUtil.LocalIdNotFound if parsing result was a UUID or no parse succeeded.
138 /// </param>
139 public static bool TryParseConsoleId(ICommandConsole console, string rawId, out UUID uuid, out uint localId)
140 {
141 if (TryParseConsoleUuid(null, rawId, out uuid))
142 {
143 localId = LocalIdNotFound;
144 return true;
145 }
146
147 if (TryParseConsoleLocalId(null, rawId, out localId))
148 {
149 return true;
150 }
151
152 if (console != null)
153 console.OutputFormat("{0} is not a valid UUID or local id", rawId);
154
155 return false;
156 }
157
158 /// <summary>
159 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
160 /// </summary>
161 /// <param name='rawConsoleVector'>/param>
162 /// <param name='vector'></param>
163 /// <returns></returns>
164 public static bool TryParseConsoleMinVector(string rawConsoleVector, out Vector3 vector)
165 {
166 return TryParseConsoleVector(rawConsoleVector, c => float.MinValue.ToString(), out vector);
167 }
168
169 /// <summary>
170 /// Convert a maximum vector input from the console to an OpenMetaverse.Vector3
171 /// </summary>
172 /// <param name='rawConsoleVector'>/param>
173 /// <param name='vector'></param>
174 /// <returns></returns>
175 public static bool TryParseConsoleMaxVector(string rawConsoleVector, out Vector3 vector)
176 {
177 return TryParseConsoleVector(rawConsoleVector, c => float.MaxValue.ToString(), out vector);
178 }
179
180 /// <summary>
181 /// Convert a vector input from the console to an OpenMetaverse.Vector3
182 /// </summary>
183 /// <param name='rawConsoleVector'>
184 /// A string in the form <x>,<y>,<z> where there is no space between values.
185 /// Any component can be missing (e.g. ,,40). blankComponentFunc is invoked to replace the blank with a suitable value
186 /// Also, if the blank component is at the end, then the comma can be missed off entirely (e.g. 40,30 or 40)
187 /// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue
188 /// Other than that, component values must be numeric.
189 /// </param>
190 /// <param name='blankComponentFunc'></param>
191 /// <param name='vector'></param>
192 /// <returns></returns>
193 public static bool TryParseConsoleVector(
194 string rawConsoleVector, Func<string, string> blankComponentFunc, out Vector3 vector)
195 {
196 List<string> components = rawConsoleVector.Split(VectorSeparatorChars).ToList();
197
198 if (components.Count < 1 || components.Count > 3)
199 {
200 vector = Vector3.Zero;
201 return false;
202 }
203
204 for (int i = components.Count; i < 3; i++)
205 components.Add("");
206
207 List<string> semiDigestedComponents
208 = components.ConvertAll<string>(
209 c =>
210 {
211 if (c == "")
212 return blankComponentFunc.Invoke(c);
213 else if (c == MaxRawConsoleVectorValue)
214 return float.MaxValue.ToString();
215 else if (c == MinRawConsoleVectorValue)
216 return float.MinValue.ToString();
217 else
218 return c;
219 });
220
221 string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray());
222
223 // m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector);
224
225 return Vector3.TryParse(semiDigestedConsoleVector, out vector);
226 }
227 }
228} \ No newline at end of file
diff --git a/OpenSim/Framework/Console/MockConsole.cs b/OpenSim/Framework/Console/MockConsole.cs
index b489f93..8ba58e4 100644
--- a/OpenSim/Framework/Console/MockConsole.cs
+++ b/OpenSim/Framework/Console/MockConsole.cs
@@ -46,13 +46,18 @@ namespace OpenSim.Framework.Console
46 46
47 public ICommands Commands { get { return m_commands; } } 47 public ICommands Commands { get { return m_commands; } }
48 48
49 public string DefaultPrompt { get; set; }
50
49 public void Prompt() {} 51 public void Prompt() {}
50 52
51 public void RunCommand(string cmd) {} 53 public void RunCommand(string cmd) {}
52 54
53 public string ReadLine(string p, bool isCommand, bool e) { return ""; } 55 public string ReadLine(string p, bool isCommand, bool e) { return ""; }
54 56
55 public object ConsoleScene { get { return null; } } 57 public object ConsoleScene {
58 get { return null; }
59 set {}
60 }
56 61
57 public void Output(string text, string level) {} 62 public void Output(string text, string level) {}
58 public void Output(string text) {} 63 public void Output(string text) {}
diff --git a/OpenSim/Framework/Constants.cs b/OpenSim/Framework/Constants.cs
index 1b1aaf2..a2eb5ee 100644
--- a/OpenSim/Framework/Constants.cs
+++ b/OpenSim/Framework/Constants.cs
@@ -31,6 +31,7 @@ namespace OpenSim.Framework
31 public class Constants 31 public class Constants
32 { 32 {
33 public const uint RegionSize = 256; 33 public const uint RegionSize = 256;
34 public const uint RegionHeight = 4096;
34 public const byte TerrainPatchSize = 16; 35 public const byte TerrainPatchSize = 16;
35 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f"; 36 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f";
36 37
diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs
index 9020761..e03750b 100644
--- a/OpenSim/Framework/EstateSettings.cs
+++ b/OpenSim/Framework/EstateSettings.cs
@@ -419,11 +419,11 @@ namespace OpenSim.Framework
419 419
420 public void SetFromFlags(ulong regionFlags) 420 public void SetFromFlags(ulong regionFlags)
421 { 421 {
422 ResetHomeOnTeleport = ((regionFlags & (ulong)RegionFlags.ResetHomeOnTeleport) == (ulong)RegionFlags.ResetHomeOnTeleport); 422 ResetHomeOnTeleport = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.ResetHomeOnTeleport) == (ulong)OpenMetaverse.RegionFlags.ResetHomeOnTeleport);
423 BlockDwell = ((regionFlags & (ulong)RegionFlags.BlockDwell) == (ulong)RegionFlags.BlockDwell); 423 BlockDwell = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.BlockDwell) == (ulong)OpenMetaverse.RegionFlags.BlockDwell);
424 AllowLandmark = ((regionFlags & (ulong)RegionFlags.AllowLandmark) == (ulong)RegionFlags.AllowLandmark); 424 AllowLandmark = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowLandmark) == (ulong)OpenMetaverse.RegionFlags.AllowLandmark);
425 AllowParcelChanges = ((regionFlags & (ulong)RegionFlags.AllowParcelChanges) == (ulong)RegionFlags.AllowParcelChanges); 425 AllowParcelChanges = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowParcelChanges) == (ulong)OpenMetaverse.RegionFlags.AllowParcelChanges);
426 AllowSetHome = ((regionFlags & (ulong)RegionFlags.AllowSetHome) == (ulong)RegionFlags.AllowSetHome); 426 AllowSetHome = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowSetHome) == (ulong)OpenMetaverse.RegionFlags.AllowSetHome);
427 } 427 }
428 428
429 public bool GroupAccess(UUID groupID) 429 public bool GroupAccess(UUID groupID)
diff --git a/OpenSim/Framework/GridInstantMessage.cs b/OpenSim/Framework/GridInstantMessage.cs
index a6bf6e3..6ae0488 100644
--- a/OpenSim/Framework/GridInstantMessage.cs
+++ b/OpenSim/Framework/GridInstantMessage.cs
@@ -44,7 +44,6 @@ namespace OpenSim.Framework
44 public Vector3 Position; 44 public Vector3 Position;
45 public byte[] binaryBucket; 45 public byte[] binaryBucket;
46 46
47
48 public uint ParentEstateID; 47 public uint ParentEstateID;
49 public Guid RegionID; 48 public Guid RegionID;
50 public uint timestamp; 49 public uint timestamp;
@@ -58,7 +57,7 @@ namespace OpenSim.Framework
58 string _fromAgentName, UUID _toAgentID, 57 string _fromAgentName, UUID _toAgentID,
59 byte _dialog, bool _fromGroup, string _message, 58 byte _dialog, bool _fromGroup, string _message,
60 UUID _imSessionID, bool _offline, Vector3 _position, 59 UUID _imSessionID, bool _offline, Vector3 _position,
61 byte[] _binaryBucket) 60 byte[] _binaryBucket, bool addTimestamp)
62 { 61 {
63 fromAgentID = _fromAgentID.Guid; 62 fromAgentID = _fromAgentID.Guid;
64 fromAgentName = _fromAgentName; 63 fromAgentName = _fromAgentName;
@@ -79,7 +78,9 @@ namespace OpenSim.Framework
79 ParentEstateID = scene.RegionInfo.EstateSettings.ParentEstateID; 78 ParentEstateID = scene.RegionInfo.EstateSettings.ParentEstateID;
80 RegionID = scene.RegionInfo.RegionSettings.RegionUUID.Guid; 79 RegionID = scene.RegionInfo.RegionSettings.RegionUUID.Guid;
81 } 80 }
82 timestamp = (uint)Util.UnixTimeSinceEpoch(); 81
82 if (addTimestamp)
83 timestamp = (uint)Util.UnixTimeSinceEpoch();
83 } 84 }
84 85
85 public GridInstantMessage(IScene scene, UUID _fromAgentID, 86 public GridInstantMessage(IScene scene, UUID _fromAgentID,
@@ -87,7 +88,7 @@ namespace OpenSim.Framework
87 string _message, bool _offline, 88 string _message, bool _offline,
88 Vector3 _position) : this(scene, _fromAgentID, _fromAgentName, 89 Vector3 _position) : this(scene, _fromAgentID, _fromAgentName,
89 _toAgentID, _dialog, false, _message, 90 _toAgentID, _dialog, false, _message,
90 _fromAgentID ^ _toAgentID, _offline, _position, new byte[0]) 91 _fromAgentID ^ _toAgentID, _offline, _position, new byte[0], true)
91 { 92 {
92 } 93 }
93 } 94 }
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 5909ce1..f686c60 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -815,8 +815,23 @@ namespace OpenSim.Framework
815 event Action<IClientAPI> OnRegionHandShakeReply; 815 event Action<IClientAPI> OnRegionHandShakeReply;
816 event GenericCall1 OnRequestWearables; 816 event GenericCall1 OnRequestWearables;
817 event Action<IClientAPI, bool> OnCompleteMovementToRegion; 817 event Action<IClientAPI, bool> OnCompleteMovementToRegion;
818
819 /// <summary>
820 /// Called when an AgentUpdate message is received and before OnAgentUpdate.
821 /// </summary>
822 /// <remarks>
823 /// Listeners must not retain a reference to AgentUpdateArgs since this object may be reused for subsequent AgentUpdates.
824 /// </remarks>
818 event UpdateAgent OnPreAgentUpdate; 825 event UpdateAgent OnPreAgentUpdate;
826
827 /// <summary>
828 /// Called when an AgentUpdate message is received and after OnPreAgentUpdate.
829 /// </summary>
830 /// <remarks>
831 /// Listeners must not retain a reference to AgentUpdateArgs since this object may be reused for subsequent AgentUpdates.
832 /// </remarks>
819 event UpdateAgent OnAgentUpdate; 833 event UpdateAgent OnAgentUpdate;
834
820 event AgentRequestSit OnAgentRequestSit; 835 event AgentRequestSit OnAgentRequestSit;
821 event AgentSit OnAgentSit; 836 event AgentSit OnAgentSit;
822 event AvatarPickerRequest OnAvatarPickerRequest; 837 event AvatarPickerRequest OnAvatarPickerRequest;
@@ -1038,7 +1053,7 @@ namespace OpenSim.Framework
1038 event MuteListEntryRemove OnRemoveMuteListEntry; 1053 event MuteListEntryRemove OnRemoveMuteListEntry;
1039 event GodlikeMessage onGodlikeMessage; 1054 event GodlikeMessage onGodlikeMessage;
1040 event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 1055 event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
1041 1056 event GenericCall2 OnUpdateThrottles;
1042 /// <summary> 1057 /// <summary>
1043 /// Set the debug level at which packet output should be printed to console. 1058 /// Set the debug level at which packet output should be printed to console.
1044 /// </summary> 1059 /// </summary>
@@ -1046,8 +1061,21 @@ namespace OpenSim.Framework
1046 1061
1047 void InPacket(object NewPack); 1062 void InPacket(object NewPack);
1048 void ProcessInPacket(Packet NewPack); 1063 void ProcessInPacket(Packet NewPack);
1064
1065 /// <summary>
1066 /// Close this client
1067 /// </summary>
1049 void Close(); 1068 void Close();
1050 void Close(bool sendStop); 1069
1070 /// <summary>
1071 /// Close this client
1072 /// </summary>
1073 /// <param name='force'>
1074 /// If true, attempts the close without checking active status. You do not want to try this except as a last
1075 /// ditch attempt where Active == false but the ScenePresence still exists.
1076 /// </param>
1077 void Close(bool sendStop, bool force);
1078
1051 void Kick(string message); 1079 void Kick(string message);
1052 1080
1053 /// <summary> 1081 /// <summary>
@@ -1084,8 +1112,20 @@ namespace OpenSim.Framework
1084 void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); 1112 void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs);
1085 void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); 1113 void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args);
1086 1114
1087 void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, 1115 /// <summary>
1088 byte audible); 1116 /// Send chat to the viewer.
1117 /// </summary>
1118 /// <param name='message'></param>
1119 /// <param name='type'></param>
1120 /// <param name='fromPos'></param>
1121 /// <param name='fromName'></param>
1122 /// <param name='fromAgentID'></param>
1123 /// <param name='ownerID'></param>
1124 /// <param name='source'></param>
1125 /// <param name='audible'></param>
1126 void SendChatMessage(
1127 string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source,
1128 byte audible);
1089 1129
1090 void SendInstantMessage(GridInstantMessage im); 1130 void SendInstantMessage(GridInstantMessage im);
1091 1131
@@ -1135,6 +1175,8 @@ namespace OpenSim.Framework
1135 1175
1136 void SetChildAgentThrottle(byte[] throttle); 1176 void SetChildAgentThrottle(byte[] throttle);
1137 1177
1178 void SetAgentThrottleSilent(int throttle, int setting);
1179
1138 void SendAvatarDataImmediate(ISceneEntity avatar); 1180 void SendAvatarDataImmediate(ISceneEntity avatar);
1139 1181
1140 /// <summary> 1182 /// <summary>
diff --git a/OpenSim/Framework/ICommandConsole.cs b/OpenSim/Framework/ICommandConsole.cs
index 8cd20da..a6573f8 100644
--- a/OpenSim/Framework/ICommandConsole.cs
+++ b/OpenSim/Framework/ICommandConsole.cs
@@ -83,6 +83,11 @@ namespace OpenSim.Framework
83 ICommands Commands { get; } 83 ICommands Commands { get; }
84 84
85 /// <summary> 85 /// <summary>
86 /// The default prompt text.
87 /// </summary>
88 string DefaultPrompt { get; set; }
89
90 /// <summary>
86 /// Display a command prompt on the console and wait for user input 91 /// Display a command prompt on the console and wait for user input
87 /// </summary> 92 /// </summary>
88 void Prompt(); 93 void Prompt();
diff --git a/OpenSim/Framework/IConsole.cs b/OpenSim/Framework/IConsole.cs
index 33024b2..79560d8 100644
--- a/OpenSim/Framework/IConsole.cs
+++ b/OpenSim/Framework/IConsole.cs
@@ -32,7 +32,7 @@ namespace OpenSim.Framework
32{ 32{
33 public interface IConsole 33 public interface IConsole
34 { 34 {
35 object ConsoleScene { get; } 35 object ConsoleScene { get; set; }
36 36
37 void Output(string text, string level); 37 void Output(string text, string level);
38 void Output(string text); 38 void Output(string text);
diff --git a/OpenSim/Framework/IMoneyModule.cs b/OpenSim/Framework/IMoneyModule.cs
index 71de93a..7378d2e 100644
--- a/OpenSim/Framework/IMoneyModule.cs
+++ b/OpenSim/Framework/IMoneyModule.cs
@@ -33,7 +33,7 @@ namespace OpenSim.Framework
33 public interface IMoneyModule 33 public interface IMoneyModule
34 { 34 {
35 bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, 35 bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID,
36 int amount); 36 int amount, UUID txn);
37 37
38 int GetBalance(UUID agentID); 38 int GetBalance(UUID agentID);
39 bool UploadCovered(UUID agentID, int amount); 39 bool UploadCovered(UUID agentID, int amount);
diff --git a/OpenSim/Framework/InventoryFolderBase.cs b/OpenSim/Framework/InventoryFolderBase.cs
index a12183c..b3457a6 100644
--- a/OpenSim/Framework/InventoryFolderBase.cs
+++ b/OpenSim/Framework/InventoryFolderBase.cs
@@ -73,33 +73,27 @@ namespace OpenSim.Framework
73 { 73 {
74 } 74 }
75 75
76 public InventoryFolderBase(UUID id) 76 public InventoryFolderBase(UUID id) : this()
77 { 77 {
78 ID = id; 78 ID = id;
79 } 79 }
80 80
81 public InventoryFolderBase(UUID id, UUID owner) 81 public InventoryFolderBase(UUID id, UUID owner) : this(id)
82 { 82 {
83 ID = id;
84 Owner = owner; 83 Owner = owner;
85 } 84 }
86 85
87 public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) 86 public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) : this(id, owner)
88 { 87 {
89 ID = id;
90 Name = name; 88 Name = name;
91 Owner = owner;
92 ParentID = parent; 89 ParentID = parent;
93 } 90 }
94 91
95 public InventoryFolderBase(UUID id, string name, UUID owner, short type, UUID parent, ushort version) 92 public InventoryFolderBase(
93 UUID id, string name, UUID owner, short type, UUID parent, ushort version) : this(id, name, owner, parent)
96 { 94 {
97 ID = id;
98 Name = name;
99 Owner = owner;
100 Type = type; 95 Type = type;
101 ParentID = parent;
102 Version = version; 96 Version = version;
103 } 97 }
104 } 98 }
105} 99} \ No newline at end of file
diff --git a/OpenSim/Framework/InventoryItemBase.cs b/OpenSim/Framework/InventoryItemBase.cs
index a663680..3d45e76 100644
--- a/OpenSim/Framework/InventoryItemBase.cs
+++ b/OpenSim/Framework/InventoryItemBase.cs
@@ -87,16 +87,7 @@ namespace OpenSim.Framework
87 protected string m_creatorId; 87 protected string m_creatorId;
88 88
89 /// <value> 89 /// <value>
90 /// The UUID for the creator. This may be different from the canonical CreatorId. This property is used 90 /// The CreatorId expressed as a UUID.tely
91 /// for communication with the client over the Second Life protocol, since that protocol can only understand
92 /// UUIDs. As this is a basic framework class, this means that both the string creator id and the uuid
93 /// reference have to be settable separately
94 ///
95 /// Database plugins don't need to set this, it will be set by
96 /// upstream code (or set by the get accessor if left unset).
97 ///
98 /// XXX: An alternative to having a separate uuid property would be to hash the CreatorId appropriately
99 /// every time there was communication with a UUID-only client. This may be much more expensive.
100 /// </value> 91 /// </value>
101 public UUID CreatorIdAsUuid 92 public UUID CreatorIdAsUuid
102 { 93 {
@@ -109,20 +100,18 @@ namespace OpenSim.Framework
109 100
110 return m_creatorIdAsUuid; 101 return m_creatorIdAsUuid;
111 } 102 }
112
113 set
114 {
115 m_creatorIdAsUuid = value;
116 }
117 } 103 }
118 protected UUID m_creatorIdAsUuid = UUID.Zero; 104 protected UUID m_creatorIdAsUuid = UUID.Zero;
119 105
120 protected string m_creatorData = string.Empty; 106 /// <summary>
107 /// Extended creator information of the form <profile url>;<name>
108 /// </summary>
121 public string CreatorData // = <profile url>;<name> 109 public string CreatorData // = <profile url>;<name>
122 { 110 {
123 get { return m_creatorData; } 111 get { return m_creatorData; }
124 set { m_creatorData = value; } 112 set { m_creatorData = value; }
125 } 113 }
114 protected string m_creatorData = string.Empty;
126 115
127 /// <summary> 116 /// <summary>
128 /// Used by the DB layer to retrieve / store the entire user identification. 117 /// Used by the DB layer to retrieve / store the entire user identification.
@@ -162,7 +151,6 @@ namespace OpenSim.Framework
162 name = parts[2]; 151 name = parts[2];
163 152
164 m_creatorData += ';' + name; 153 m_creatorData += ';' + name;
165
166 } 154 }
167 } 155 }
168 } 156 }
diff --git a/OpenSim/Framework/LandData.cs b/OpenSim/Framework/LandData.cs
index dcaa46d..4dffd3f 100644
--- a/OpenSim/Framework/LandData.cs
+++ b/OpenSim/Framework/LandData.cs
@@ -49,8 +49,8 @@ namespace OpenSim.Framework
49 // use only one serializer to give the runtime a chance to 49 // use only one serializer to give the runtime a chance to
50 // optimize it (it won't do that if you use a new instance 50 // optimize it (it won't do that if you use a new instance
51 // every time) 51 // every time)
52 private static XmlSerializer serializer = new XmlSerializer(typeof (LandData)); 52 private static XmlSerializer serializer = new XmlSerializer(typeof(LandData));
53 53
54 private Vector3 _AABBMax = new Vector3(); 54 private Vector3 _AABBMax = new Vector3();
55 private Vector3 _AABBMin = new Vector3(); 55 private Vector3 _AABBMin = new Vector3();
56 private int _area = 0; 56 private int _area = 0;
@@ -65,11 +65,11 @@ namespace OpenSim.Framework
65 private byte[] _bitmap = new byte[512]; 65 private byte[] _bitmap = new byte[512];
66 private string _description = String.Empty; 66 private string _description = String.Empty;
67 67
68 private uint _flags = (uint) ParcelFlags.AllowFly | (uint) ParcelFlags.AllowLandmark | 68 private uint _flags = (uint)ParcelFlags.AllowFly | (uint)ParcelFlags.AllowLandmark |
69 (uint) ParcelFlags.AllowAPrimitiveEntry | 69 (uint)ParcelFlags.AllowAPrimitiveEntry |
70 (uint) ParcelFlags.AllowDeedToGroup | 70 (uint)ParcelFlags.AllowDeedToGroup |
71 (uint) ParcelFlags.CreateObjects | (uint) ParcelFlags.AllowOtherScripts | 71 (uint)ParcelFlags.CreateObjects | (uint)ParcelFlags.AllowOtherScripts |
72 (uint) ParcelFlags.SoundLocal | (uint) ParcelFlags.AllowVoiceChat; 72 (uint)ParcelFlags.AllowVoiceChat;
73 73
74 private byte _landingType = 0; 74 private byte _landingType = 0;
75 private string _name = "Your Parcel"; 75 private string _name = "Your Parcel";
@@ -97,16 +97,36 @@ namespace OpenSim.Framework
97 private bool _mediaLoop = false; 97 private bool _mediaLoop = false;
98 private bool _obscureMusic = false; 98 private bool _obscureMusic = false;
99 private bool _obscureMedia = false; 99 private bool _obscureMedia = false;
100 private float _dwell = 0;
101
102 /// <summary>
103 /// Traffic count of parcel
104 /// </summary>
105 [XmlIgnore]
106 public float Dwell
107 {
108 get
109 {
110 return _dwell;
111 }
112 set
113 {
114 _dwell = value;
115 }
116 }
100 117
101 /// <summary> 118 /// <summary>
102 /// Whether to obscure parcel media URL 119 /// Whether to obscure parcel media URL
103 /// </summary> 120 /// </summary>
104 [XmlIgnore] 121 [XmlIgnore]
105 public bool ObscureMedia { 122 public bool ObscureMedia
106 get { 123 {
124 get
125 {
107 return _obscureMedia; 126 return _obscureMedia;
108 } 127 }
109 set { 128 set
129 {
110 _obscureMedia = value; 130 _obscureMedia = value;
111 } 131 }
112 } 132 }
@@ -115,11 +135,14 @@ namespace OpenSim.Framework
115 /// Whether to obscure parcel music URL 135 /// Whether to obscure parcel music URL
116 /// </summary> 136 /// </summary>
117 [XmlIgnore] 137 [XmlIgnore]
118 public bool ObscureMusic { 138 public bool ObscureMusic
119 get { 139 {
140 get
141 {
120 return _obscureMusic; 142 return _obscureMusic;
121 } 143 }
122 set { 144 set
145 {
123 _obscureMusic = value; 146 _obscureMusic = value;
124 } 147 }
125 } 148 }
@@ -128,11 +151,14 @@ namespace OpenSim.Framework
128 /// Whether to loop parcel media 151 /// Whether to loop parcel media
129 /// </summary> 152 /// </summary>
130 [XmlIgnore] 153 [XmlIgnore]
131 public bool MediaLoop { 154 public bool MediaLoop
132 get { 155 {
156 get
157 {
133 return _mediaLoop; 158 return _mediaLoop;
134 } 159 }
135 set { 160 set
161 {
136 _mediaLoop = value; 162 _mediaLoop = value;
137 } 163 }
138 } 164 }
@@ -141,11 +167,14 @@ namespace OpenSim.Framework
141 /// Height of parcel media render 167 /// Height of parcel media render
142 /// </summary> 168 /// </summary>
143 [XmlIgnore] 169 [XmlIgnore]
144 public int MediaHeight { 170 public int MediaHeight
145 get { 171 {
172 get
173 {
146 return _mediaHeight; 174 return _mediaHeight;
147 } 175 }
148 set { 176 set
177 {
149 _mediaHeight = value; 178 _mediaHeight = value;
150 } 179 }
151 } 180 }
@@ -154,11 +183,14 @@ namespace OpenSim.Framework
154 /// Width of parcel media render 183 /// Width of parcel media render
155 /// </summary> 184 /// </summary>
156 [XmlIgnore] 185 [XmlIgnore]
157 public int MediaWidth { 186 public int MediaWidth
158 get { 187 {
188 get
189 {
159 return _mediaWidth; 190 return _mediaWidth;
160 } 191 }
161 set { 192 set
193 {
162 _mediaWidth = value; 194 _mediaWidth = value;
163 } 195 }
164 } 196 }
@@ -167,11 +199,14 @@ namespace OpenSim.Framework
167 /// Upper corner of the AABB for the parcel 199 /// Upper corner of the AABB for the parcel
168 /// </summary> 200 /// </summary>
169 [XmlIgnore] 201 [XmlIgnore]
170 public Vector3 AABBMax { 202 public Vector3 AABBMax
171 get { 203 {
204 get
205 {
172 return _AABBMax; 206 return _AABBMax;
173 } 207 }
174 set { 208 set
209 {
175 _AABBMax = value; 210 _AABBMax = value;
176 } 211 }
177 } 212 }
@@ -179,11 +214,14 @@ namespace OpenSim.Framework
179 /// Lower corner of the AABB for the parcel 214 /// Lower corner of the AABB for the parcel
180 /// </summary> 215 /// </summary>
181 [XmlIgnore] 216 [XmlIgnore]
182 public Vector3 AABBMin { 217 public Vector3 AABBMin
183 get { 218 {
219 get
220 {
184 return _AABBMin; 221 return _AABBMin;
185 } 222 }
186 set { 223 set
224 {
187 _AABBMin = value; 225 _AABBMin = value;
188 } 226 }
189 } 227 }
@@ -191,11 +229,14 @@ namespace OpenSim.Framework
191 /// <summary> 229 /// <summary>
192 /// Area in meters^2 the parcel contains 230 /// Area in meters^2 the parcel contains
193 /// </summary> 231 /// </summary>
194 public int Area { 232 public int Area
195 get { 233 {
234 get
235 {
196 return _area; 236 return _area;
197 } 237 }
198 set { 238 set
239 {
199 _area = value; 240 _area = value;
200 } 241 }
201 } 242 }
@@ -203,11 +244,14 @@ namespace OpenSim.Framework
203 /// <summary> 244 /// <summary>
204 /// ID of auction (3rd Party Integration) when parcel is being auctioned 245 /// ID of auction (3rd Party Integration) when parcel is being auctioned
205 /// </summary> 246 /// </summary>
206 public uint AuctionID { 247 public uint AuctionID
207 get { 248 {
249 get
250 {
208 return _auctionID; 251 return _auctionID;
209 } 252 }
210 set { 253 set
254 {
211 _auctionID = value; 255 _auctionID = value;
212 } 256 }
213 } 257 }
@@ -215,11 +259,14 @@ namespace OpenSim.Framework
215 /// <summary> 259 /// <summary>
216 /// UUID of authorized buyer of parcel. This is UUID.Zero if anyone can buy it. 260 /// UUID of authorized buyer of parcel. This is UUID.Zero if anyone can buy it.
217 /// </summary> 261 /// </summary>
218 public UUID AuthBuyerID { 262 public UUID AuthBuyerID
219 get { 263 {
264 get
265 {
220 return _authBuyerID; 266 return _authBuyerID;
221 } 267 }
222 set { 268 set
269 {
223 _authBuyerID = value; 270 _authBuyerID = value;
224 } 271 }
225 } 272 }
@@ -227,11 +274,14 @@ namespace OpenSim.Framework
227 /// <summary> 274 /// <summary>
228 /// Category of parcel. Used for classifying the parcel in classified listings 275 /// Category of parcel. Used for classifying the parcel in classified listings
229 /// </summary> 276 /// </summary>
230 public ParcelCategory Category { 277 public ParcelCategory Category
231 get { 278 {
279 get
280 {
232 return _category; 281 return _category;
233 } 282 }
234 set { 283 set
284 {
235 _category = value; 285 _category = value;
236 } 286 }
237 } 287 }
@@ -239,11 +289,14 @@ namespace OpenSim.Framework
239 /// <summary> 289 /// <summary>
240 /// Date that the current owner purchased or claimed the parcel 290 /// Date that the current owner purchased or claimed the parcel
241 /// </summary> 291 /// </summary>
242 public int ClaimDate { 292 public int ClaimDate
243 get { 293 {
294 get
295 {
244 return _claimDate; 296 return _claimDate;
245 } 297 }
246 set { 298 set
299 {
247 _claimDate = value; 300 _claimDate = value;
248 } 301 }
249 } 302 }
@@ -251,11 +304,14 @@ namespace OpenSim.Framework
251 /// <summary> 304 /// <summary>
252 /// The last price that the parcel was sold at 305 /// The last price that the parcel was sold at
253 /// </summary> 306 /// </summary>
254 public int ClaimPrice { 307 public int ClaimPrice
255 get { 308 {
309 get
310 {
256 return _claimPrice; 311 return _claimPrice;
257 } 312 }
258 set { 313 set
314 {
259 _claimPrice = value; 315 _claimPrice = value;
260 } 316 }
261 } 317 }
@@ -263,11 +319,14 @@ namespace OpenSim.Framework
263 /// <summary> 319 /// <summary>
264 /// Global ID for the parcel. (3rd Party Integration) 320 /// Global ID for the parcel. (3rd Party Integration)
265 /// </summary> 321 /// </summary>
266 public UUID GlobalID { 322 public UUID GlobalID
267 get { 323 {
324 get
325 {
268 return _globalID; 326 return _globalID;
269 } 327 }
270 set { 328 set
329 {
271 _globalID = value; 330 _globalID = value;
272 } 331 }
273 } 332 }
@@ -275,11 +334,14 @@ namespace OpenSim.Framework
275 /// <summary> 334 /// <summary>
276 /// Unique ID of the Group that owns 335 /// Unique ID of the Group that owns
277 /// </summary> 336 /// </summary>
278 public UUID GroupID { 337 public UUID GroupID
279 get { 338 {
339 get
340 {
280 return _groupID; 341 return _groupID;
281 } 342 }
282 set { 343 set
344 {
283 _groupID = value; 345 _groupID = value;
284 } 346 }
285 } 347 }
@@ -287,11 +349,14 @@ namespace OpenSim.Framework
287 /// <summary> 349 /// <summary>
288 /// Returns true if the Land Parcel is owned by a group 350 /// Returns true if the Land Parcel is owned by a group
289 /// </summary> 351 /// </summary>
290 public bool IsGroupOwned { 352 public bool IsGroupOwned
291 get { 353 {
354 get
355 {
292 return _isGroupOwned; 356 return _isGroupOwned;
293 } 357 }
294 set { 358 set
359 {
295 _isGroupOwned = value; 360 _isGroupOwned = value;
296 } 361 }
297 } 362 }
@@ -299,11 +364,14 @@ namespace OpenSim.Framework
299 /// <summary> 364 /// <summary>
300 /// jp2 data for the image representative of the parcel in the parcel dialog 365 /// jp2 data for the image representative of the parcel in the parcel dialog
301 /// </summary> 366 /// </summary>
302 public byte[] Bitmap { 367 public byte[] Bitmap
303 get { 368 {
369 get
370 {
304 return _bitmap; 371 return _bitmap;
305 } 372 }
306 set { 373 set
374 {
307 _bitmap = value; 375 _bitmap = value;
308 } 376 }
309 } 377 }
@@ -311,11 +379,14 @@ namespace OpenSim.Framework
311 /// <summary> 379 /// <summary>
312 /// Parcel Description 380 /// Parcel Description
313 /// </summary> 381 /// </summary>
314 public string Description { 382 public string Description
315 get { 383 {
384 get
385 {
316 return _description; 386 return _description;
317 } 387 }
318 set { 388 set
389 {
319 _description = value; 390 _description = value;
320 } 391 }
321 } 392 }
@@ -323,11 +394,14 @@ namespace OpenSim.Framework
323 /// <summary> 394 /// <summary>
324 /// Parcel settings. Access flags, Fly, NoPush, Voice, Scripts allowed, etc. ParcelFlags 395 /// Parcel settings. Access flags, Fly, NoPush, Voice, Scripts allowed, etc. ParcelFlags
325 /// </summary> 396 /// </summary>
326 public uint Flags { 397 public uint Flags
327 get { 398 {
399 get
400 {
328 return _flags; 401 return _flags;
329 } 402 }
330 set { 403 set
404 {
331 _flags = value; 405 _flags = value;
332 } 406 }
333 } 407 }
@@ -336,11 +410,14 @@ namespace OpenSim.Framework
336 /// Determines if people are able to teleport where they please on the parcel or if they 410 /// Determines if people are able to teleport where they please on the parcel or if they
337 /// get constrainted to a specific point on teleport within the parcel 411 /// get constrainted to a specific point on teleport within the parcel
338 /// </summary> 412 /// </summary>
339 public byte LandingType { 413 public byte LandingType
340 get { 414 {
415 get
416 {
341 return _landingType; 417 return _landingType;
342 } 418 }
343 set { 419 set
420 {
344 _landingType = value; 421 _landingType = value;
345 } 422 }
346 } 423 }
@@ -348,11 +425,14 @@ namespace OpenSim.Framework
348 /// <summary> 425 /// <summary>
349 /// Parcel Name 426 /// Parcel Name
350 /// </summary> 427 /// </summary>
351 public string Name { 428 public string Name
352 get { 429 {
430 get
431 {
353 return _name; 432 return _name;
354 } 433 }
355 set { 434 set
435 {
356 _name = value; 436 _name = value;
357 } 437 }
358 } 438 }
@@ -360,11 +440,14 @@ namespace OpenSim.Framework
360 /// <summary> 440 /// <summary>
361 /// Status of Parcel, Leased, Abandoned, For Sale 441 /// Status of Parcel, Leased, Abandoned, For Sale
362 /// </summary> 442 /// </summary>
363 public ParcelStatus Status { 443 public ParcelStatus Status
364 get { 444 {
445 get
446 {
365 return _status; 447 return _status;
366 } 448 }
367 set { 449 set
450 {
368 _status = value; 451 _status = value;
369 } 452 }
370 } 453 }
@@ -372,11 +455,14 @@ namespace OpenSim.Framework
372 /// <summary> 455 /// <summary>
373 /// Internal ID of the parcel. Sometimes the client will try to use this value 456 /// Internal ID of the parcel. Sometimes the client will try to use this value
374 /// </summary> 457 /// </summary>
375 public int LocalID { 458 public int LocalID
376 get { 459 {
460 get
461 {
377 return _localID; 462 return _localID;
378 } 463 }
379 set { 464 set
465 {
380 _localID = value; 466 _localID = value;
381 } 467 }
382 } 468 }
@@ -384,11 +470,14 @@ namespace OpenSim.Framework
384 /// <summary> 470 /// <summary>
385 /// Determines if we scale the media based on the surface it's on 471 /// Determines if we scale the media based on the surface it's on
386 /// </summary> 472 /// </summary>
387 public byte MediaAutoScale { 473 public byte MediaAutoScale
388 get { 474 {
475 get
476 {
389 return _mediaAutoScale; 477 return _mediaAutoScale;
390 } 478 }
391 set { 479 set
480 {
392 _mediaAutoScale = value; 481 _mediaAutoScale = value;
393 } 482 }
394 } 483 }
@@ -396,11 +485,14 @@ namespace OpenSim.Framework
396 /// <summary> 485 /// <summary>
397 /// Texture Guid to replace with the output of the media stream 486 /// Texture Guid to replace with the output of the media stream
398 /// </summary> 487 /// </summary>
399 public UUID MediaID { 488 public UUID MediaID
400 get { 489 {
490 get
491 {
401 return _mediaID; 492 return _mediaID;
402 } 493 }
403 set { 494 set
495 {
404 _mediaID = value; 496 _mediaID = value;
405 } 497 }
406 } 498 }
@@ -408,11 +500,14 @@ namespace OpenSim.Framework
408 /// <summary> 500 /// <summary>
409 /// URL to the media file to display 501 /// URL to the media file to display
410 /// </summary> 502 /// </summary>
411 public string MediaURL { 503 public string MediaURL
412 get { 504 {
505 get
506 {
413 return _mediaURL; 507 return _mediaURL;
414 } 508 }
415 set { 509 set
510 {
416 _mediaURL = value; 511 _mediaURL = value;
417 } 512 }
418 } 513 }
@@ -432,11 +527,14 @@ namespace OpenSim.Framework
432 /// <summary> 527 /// <summary>
433 /// URL to the shoutcast music stream to play on the parcel 528 /// URL to the shoutcast music stream to play on the parcel
434 /// </summary> 529 /// </summary>
435 public string MusicURL { 530 public string MusicURL
436 get { 531 {
532 get
533 {
437 return _musicURL; 534 return _musicURL;
438 } 535 }
439 set { 536 set
537 {
440 _musicURL = value; 538 _musicURL = value;
441 } 539 }
442 } 540 }
@@ -445,11 +543,14 @@ namespace OpenSim.Framework
445 /// Owner Avatar or Group of the parcel. Naturally, all land masses must be 543 /// Owner Avatar or Group of the parcel. Naturally, all land masses must be
446 /// owned by someone 544 /// owned by someone
447 /// </summary> 545 /// </summary>
448 public UUID OwnerID { 546 public UUID OwnerID
449 get { 547 {
548 get
549 {
450 return _ownerID; 550 return _ownerID;
451 } 551 }
452 set { 552 set
553 {
453 _ownerID = value; 554 _ownerID = value;
454 } 555 }
455 } 556 }
@@ -457,11 +558,14 @@ namespace OpenSim.Framework
457 /// <summary> 558 /// <summary>
458 /// List of access data for the parcel. User data, some bitflags, and a time 559 /// List of access data for the parcel. User data, some bitflags, and a time
459 /// </summary> 560 /// </summary>
460 public List<LandAccessEntry> ParcelAccessList { 561 public List<LandAccessEntry> ParcelAccessList
461 get { 562 {
563 get
564 {
462 return _parcelAccessList; 565 return _parcelAccessList;
463 } 566 }
464 set { 567 set
568 {
465 _parcelAccessList = value; 569 _parcelAccessList = value;
466 } 570 }
467 } 571 }
@@ -469,11 +573,14 @@ namespace OpenSim.Framework
469 /// <summary> 573 /// <summary>
470 /// How long in hours a Pass to the parcel is given 574 /// How long in hours a Pass to the parcel is given
471 /// </summary> 575 /// </summary>
472 public float PassHours { 576 public float PassHours
473 get { 577 {
578 get
579 {
474 return _passHours; 580 return _passHours;
475 } 581 }
476 set { 582 set
583 {
477 _passHours = value; 584 _passHours = value;
478 } 585 }
479 } 586 }
@@ -481,11 +588,14 @@ namespace OpenSim.Framework
481 /// <summary> 588 /// <summary>
482 /// Price to purchase a Pass to a restricted parcel 589 /// Price to purchase a Pass to a restricted parcel
483 /// </summary> 590 /// </summary>
484 public int PassPrice { 591 public int PassPrice
485 get { 592 {
593 get
594 {
486 return _passPrice; 595 return _passPrice;
487 } 596 }
488 set { 597 set
598 {
489 _passPrice = value; 599 _passPrice = value;
490 } 600 }
491 } 601 }
@@ -493,11 +603,14 @@ namespace OpenSim.Framework
493 /// <summary> 603 /// <summary>
494 /// When the parcel is being sold, this is the price to purchase the parcel 604 /// When the parcel is being sold, this is the price to purchase the parcel
495 /// </summary> 605 /// </summary>
496 public int SalePrice { 606 public int SalePrice
497 get { 607 {
608 get
609 {
498 return _salePrice; 610 return _salePrice;
499 } 611 }
500 set { 612 set
613 {
501 _salePrice = value; 614 _salePrice = value;
502 } 615 }
503 } 616 }
@@ -506,11 +619,14 @@ namespace OpenSim.Framework
506 /// Number of meters^2 in the Simulator 619 /// Number of meters^2 in the Simulator
507 /// </summary> 620 /// </summary>
508 [XmlIgnore] 621 [XmlIgnore]
509 public int SimwideArea { 622 public int SimwideArea
510 get { 623 {
624 get
625 {
511 return _simwideArea; 626 return _simwideArea;
512 } 627 }
513 set { 628 set
629 {
514 _simwideArea = value; 630 _simwideArea = value;
515 } 631 }
516 } 632 }
@@ -519,11 +635,14 @@ namespace OpenSim.Framework
519 /// Number of SceneObjectPart in the Simulator 635 /// Number of SceneObjectPart in the Simulator
520 /// </summary> 636 /// </summary>
521 [XmlIgnore] 637 [XmlIgnore]
522 public int SimwidePrims { 638 public int SimwidePrims
523 get { 639 {
640 get
641 {
524 return _simwidePrims; 642 return _simwidePrims;
525 } 643 }
526 set { 644 set
645 {
527 _simwidePrims = value; 646 _simwidePrims = value;
528 } 647 }
529 } 648 }
@@ -531,11 +650,14 @@ namespace OpenSim.Framework
531 /// <summary> 650 /// <summary>
532 /// ID of the snapshot used in the client parcel dialog of the parcel 651 /// ID of the snapshot used in the client parcel dialog of the parcel
533 /// </summary> 652 /// </summary>
534 public UUID SnapshotID { 653 public UUID SnapshotID
535 get { 654 {
655 get
656 {
536 return _snapshotID; 657 return _snapshotID;
537 } 658 }
538 set { 659 set
660 {
539 _snapshotID = value; 661 _snapshotID = value;
540 } 662 }
541 } 663 }
@@ -544,11 +666,14 @@ namespace OpenSim.Framework
544 /// When teleporting is restricted to a certain point, this is the location 666 /// When teleporting is restricted to a certain point, this is the location
545 /// that the user will be redirected to 667 /// that the user will be redirected to
546 /// </summary> 668 /// </summary>
547 public Vector3 UserLocation { 669 public Vector3 UserLocation
548 get { 670 {
671 get
672 {
549 return _userLocation; 673 return _userLocation;
550 } 674 }
551 set { 675 set
676 {
552 _userLocation = value; 677 _userLocation = value;
553 } 678 }
554 } 679 }
@@ -557,11 +682,14 @@ namespace OpenSim.Framework
557 /// When teleporting is restricted to a certain point, this is the rotation 682 /// When teleporting is restricted to a certain point, this is the rotation
558 /// that the user will be positioned 683 /// that the user will be positioned
559 /// </summary> 684 /// </summary>
560 public Vector3 UserLookAt { 685 public Vector3 UserLookAt
561 get { 686 {
687 get
688 {
562 return _userLookAt; 689 return _userLookAt;
563 } 690 }
564 set { 691 set
692 {
565 _userLookAt = value; 693 _userLookAt = value;
566 } 694 }
567 } 695 }
@@ -570,11 +698,14 @@ namespace OpenSim.Framework
570 /// Autoreturn number of minutes to return SceneObjectGroup that are owned by someone who doesn't own 698 /// Autoreturn number of minutes to return SceneObjectGroup that are owned by someone who doesn't own
571 /// the parcel and isn't set to the same 'group' as the parcel. 699 /// the parcel and isn't set to the same 'group' as the parcel.
572 /// </summary> 700 /// </summary>
573 public int OtherCleanTime { 701 public int OtherCleanTime
574 get { 702 {
703 get
704 {
575 return _otherCleanTime; 705 return _otherCleanTime;
576 } 706 }
577 set { 707 set
708 {
578 _otherCleanTime = value; 709 _otherCleanTime = value;
579 } 710 }
580 } 711 }
@@ -582,11 +713,14 @@ namespace OpenSim.Framework
582 /// <summary> 713 /// <summary>
583 /// parcel media description 714 /// parcel media description
584 /// </summary> 715 /// </summary>
585 public string MediaDescription { 716 public string MediaDescription
586 get { 717 {
718 get
719 {
587 return _mediaDescription; 720 return _mediaDescription;
588 } 721 }
589 set { 722 set
723 {
590 _mediaDescription = value; 724 _mediaDescription = value;
591 } 725 }
592 } 726 }
@@ -622,7 +756,7 @@ namespace OpenSim.Framework
622 landData._mediaURL = _mediaURL; 756 landData._mediaURL = _mediaURL;
623 landData._musicURL = _musicURL; 757 landData._musicURL = _musicURL;
624 landData._ownerID = _ownerID; 758 landData._ownerID = _ownerID;
625 landData._bitmap = (byte[]) _bitmap.Clone(); 759 landData._bitmap = (byte[])_bitmap.Clone();
626 landData._description = _description; 760 landData._description = _description;
627 landData._flags = _flags; 761 landData._flags = _flags;
628 landData._name = _name; 762 landData._name = _name;
@@ -643,6 +777,7 @@ namespace OpenSim.Framework
643 landData._obscureMedia = _obscureMedia; 777 landData._obscureMedia = _obscureMedia;
644 landData._simwideArea = _simwideArea; 778 landData._simwideArea = _simwideArea;
645 landData._simwidePrims = _simwidePrims; 779 landData._simwidePrims = _simwidePrims;
780 landData._dwell = _dwell;
646 781
647 landData._parcelAccessList.Clear(); 782 landData._parcelAccessList.Clear();
648 foreach (LandAccessEntry entry in _parcelAccessList) 783 foreach (LandAccessEntry entry in _parcelAccessList)
diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
index 9ee0876..446e3c0 100644
--- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
@@ -43,27 +43,32 @@ namespace OpenSim.Framework.Monitoring
43 StringBuilder sb = new StringBuilder(Environment.NewLine); 43 StringBuilder sb = new StringBuilder(Environment.NewLine);
44 sb.Append("MEMORY STATISTICS"); 44 sb.Append("MEMORY STATISTICS");
45 sb.Append(Environment.NewLine); 45 sb.Append(Environment.NewLine);
46 sb.Append( 46 sb.AppendFormat(
47 string.Format(
48 "Allocated to OpenSim objects: {0} MB\n", 47 "Allocated to OpenSim objects: {0} MB\n",
49 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0))); 48 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
49
50 sb.AppendFormat(
51 "OpenSim last object memory churn : {0} MB/s\n",
52 Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3));
53
54 sb.AppendFormat(
55 "OpenSim average object memory churn : {0} MB/s\n",
56 Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3));
50 57
51 Process myprocess = Process.GetCurrentProcess(); 58 Process myprocess = Process.GetCurrentProcess();
52 if (!myprocess.HasExited) 59 if (!myprocess.HasExited)
53 { 60 {
54 myprocess.Refresh(); 61 myprocess.Refresh();
55 sb.Append( 62 sb.AppendFormat(
56 string.Format(
57 "Process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n", 63 "Process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n",
58 Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0), 64 Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0),
59 Math.Round(Process.GetCurrentProcess().PagedMemorySize64 / 1024.0 / 1024.0), 65 Math.Round(Process.GetCurrentProcess().PagedMemorySize64 / 1024.0 / 1024.0),
60 Math.Round(Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0 / 1024.0))); 66 Math.Round(Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0 / 1024.0));
61 sb.Append( 67 sb.AppendFormat(
62 string.Format(
63 "Peak process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n", 68 "Peak process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n",
64 Math.Round(Process.GetCurrentProcess().PeakWorkingSet64 / 1024.0 / 1024.0), 69 Math.Round(Process.GetCurrentProcess().PeakWorkingSet64 / 1024.0 / 1024.0),
65 Math.Round(Process.GetCurrentProcess().PeakPagedMemorySize64 / 1024.0 / 1024.0), 70 Math.Round(Process.GetCurrentProcess().PeakPagedMemorySize64 / 1024.0 / 1024.0),
66 Math.Round(Process.GetCurrentProcess().PeakVirtualMemorySize64 / 1024.0 / 1024.0))); 71 Math.Round(Process.GetCurrentProcess().PeakVirtualMemorySize64 / 1024.0 / 1024.0));
67 } 72 }
68 else 73 else
69 sb.Append("Process reported as Exited \n"); 74 sb.Append("Process reported as Exited \n");
diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
index a23cf1f..c6010cd 100644
--- a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
+++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
@@ -60,7 +60,7 @@ namespace OpenSim.Framework.Monitoring
60 private static bool m_enabled; 60 private static bool m_enabled;
61 61
62 /// <summary> 62 /// <summary>
63 /// Average memory churn in bytes per millisecond. 63 /// Last memory churn in bytes per millisecond.
64 /// </summary> 64 /// </summary>
65 public static double AverageMemoryChurn 65 public static double AverageMemoryChurn
66 { 66 {
@@ -68,6 +68,14 @@ namespace OpenSim.Framework.Monitoring
68 } 68 }
69 69
70 /// <summary> 70 /// <summary>
71 /// Average memory churn in bytes per millisecond.
72 /// </summary>
73 public static double LastMemoryChurn
74 {
75 get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; }
76 }
77
78 /// <summary>
71 /// Maximum number of statistical samples. 79 /// Maximum number of statistical samples.
72 /// </summary> 80 /// </summary>
73 /// <remarks> 81 /// <remarks>
diff --git a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1f2bb40
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Framework.Monitoring")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("74506fe3-2f9d-44c1-94c9-a30f79d9e0cb")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
index cdd7cc7..aa86202 100644
--- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
@@ -355,10 +355,25 @@ Asset service request failures: {3}" + Environment.NewLine,
355 sb.Append(Environment.NewLine); 355 sb.Append(Environment.NewLine);
356 sb.Append( 356 sb.Append(
357 string.Format( 357 string.Format(
358 "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}", 358 "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}\n\n",
359 inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, 359 inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime,
360 netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); 360 netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime));
361 sb.Append(Environment.NewLine); 361
362 Dictionary<string, Dictionary<string, Stat>> sceneStats;
363
364 if (StatsManager.TryGetStats("scene", out sceneStats))
365 {
366 foreach (KeyValuePair<string, Dictionary<string, Stat>> kvp in sceneStats)
367 {
368 foreach (Stat stat in kvp.Value.Values)
369 {
370 if (stat.Verbosity == StatVerbosity.Info)
371 {
372 sb.AppendFormat("{0} ({1}): {2}{3}\n", stat.Name, stat.Container, stat.Value, stat.UnitName);
373 }
374 }
375 }
376 }
362 377
363 /* 378 /*
364 sb.Append(Environment.NewLine); 379 sb.Append(Environment.NewLine);
diff --git a/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs b/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs
new file mode 100644
index 0000000..60bed55
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs
@@ -0,0 +1,88 @@
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;
31
32namespace OpenSim.Framework.Monitoring
33{
34 public class PercentageStat : Stat
35 {
36 public long Antecedent { get; set; }
37 public long Consequent { get; set; }
38
39 public override double Value
40 {
41 get
42 {
43 // Asking for an update here means that the updater cannot access this value without infinite recursion.
44 // XXX: A slightly messy but simple solution may be to flick a flag so we can tell if this is being
45 // called by the pull action and just return the value.
46 if (StatType == StatType.Pull)
47 PullAction(this);
48
49 long c = Consequent;
50
51 // Avoid any chance of a multi-threaded divide-by-zero
52 if (c == 0)
53 return 0;
54
55 return (double)Antecedent / c * 100;
56 }
57
58 set
59 {
60 throw new InvalidOperationException("Cannot set value on a PercentageStat");
61 }
62 }
63
64 public PercentageStat(
65 string shortName,
66 string name,
67 string description,
68 string category,
69 string container,
70 StatType type,
71 Action<Stat> pullAction,
72 StatVerbosity verbosity)
73 : base(shortName, name, description, "%", category, container, type, pullAction, verbosity) {}
74
75 public override string ToConsoleString()
76 {
77 StringBuilder sb = new StringBuilder();
78
79 sb.AppendFormat(
80 "{0}.{1}.{2} : {3:0.##}{4} ({5}/{6})",
81 Category, Container, ShortName, Value, UnitName, Antecedent, Consequent);
82
83 AppendMeasuresOfInterest(sb);
84
85 return sb.ToString();
86 }
87 }
88} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs
new file mode 100644
index 0000000..f91251b
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs
@@ -0,0 +1,238 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above 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;
31
32namespace OpenSim.Framework.Monitoring
33{
34 /// <summary>
35 /// Holds individual statistic details
36 /// </summary>
37 public class Stat
38 {
39 /// <summary>
40 /// Category of this stat (e.g. cache, scene, etc).
41 /// </summary>
42 public string Category { get; private set; }
43
44 /// <summary>
45 /// Containing name for this stat.
46 /// FIXME: In the case of a scene, this is currently the scene name (though this leaves
47 /// us with a to-be-resolved problem of non-unique region names).
48 /// </summary>
49 /// <value>
50 /// The container.
51 /// </value>
52 public string Container { get; private set; }
53
54 public StatType StatType { get; private set; }
55
56 public MeasuresOfInterest MeasuresOfInterest { get; private set; }
57
58 /// <summary>
59 /// Action used to update this stat when the value is requested if it's a pull type.
60 /// </summary>
61 public Action<Stat> PullAction { get; private set; }
62
63 public StatVerbosity Verbosity { get; private set; }
64 public string ShortName { get; private set; }
65 public string Name { get; private set; }
66 public string Description { get; private set; }
67 public virtual string UnitName { get; private set; }
68
69 public virtual double Value
70 {
71 get
72 {
73 // Asking for an update here means that the updater cannot access this value without infinite recursion.
74 // XXX: A slightly messy but simple solution may be to flick a flag so we can tell if this is being
75 // called by the pull action and just return the value.
76 if (StatType == StatType.Pull)
77 PullAction(this);
78
79 return m_value;
80 }
81
82 set
83 {
84 m_value = value;
85 }
86 }
87
88 private double m_value;
89
90 /// <summary>
91 /// Historical samples for calculating measures of interest average.
92 /// </summary>
93 /// <remarks>
94 /// Will be null if no measures of interest require samples.
95 /// </remarks>
96 private static Queue<double> m_samples;
97
98 /// <summary>
99 /// Maximum number of statistical samples.
100 /// </summary>
101 /// <remarks>
102 /// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from
103 /// the main Watchdog.
104 /// </remarks>
105 private static int m_maxSamples = 24;
106
107 public Stat(
108 string shortName,
109 string name,
110 string description,
111 string unitName,
112 string category,
113 string container,
114 StatType type,
115 Action<Stat> pullAction,
116 StatVerbosity verbosity)
117 : this(
118 shortName,
119 name,
120 description,
121 unitName,
122 category,
123 container,
124 type,
125 MeasuresOfInterest.None,
126 pullAction,
127 verbosity)
128 {
129 }
130
131 /// <summary>
132 /// Constructor
133 /// </summary>
134 /// <param name='shortName'>Short name for the stat. Must not contain spaces. e.g. "LongFrames"</param>
135 /// <param name='name'>Human readable name for the stat. e.g. "Long frames"</param>
136 /// <param name='description'>Description of stat</param>
137 /// <param name='unitName'>
138 /// Unit name for the stat. Should be preceeded by a space if the unit name isn't normally appeneded immediately to the value.
139 /// e.g. " frames"
140 /// </param>
141 /// <param name='category'>Category under which this stat should appear, e.g. "scene". Do not capitalize.</param>
142 /// <param name='container'>Entity to which this stat relates. e.g. scene name if this is a per scene stat.</param>
143 /// <param name='type'>Push or pull</param>
144 /// <param name='pullAction'>Pull stats need an action to update the stat on request. Push stats should set null here.</param>
145 /// <param name='moi'>Measures of interest</param>
146 /// <param name='verbosity'>Verbosity of stat. Controls whether it will appear in short stat display or only full display.</param>
147 public Stat(
148 string shortName,
149 string name,
150 string description,
151 string unitName,
152 string category,
153 string container,
154 StatType type,
155 MeasuresOfInterest moi,
156 Action<Stat> pullAction,
157 StatVerbosity verbosity)
158 {
159 if (StatsManager.SubCommands.Contains(category))
160 throw new Exception(
161 string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
162
163 ShortName = shortName;
164 Name = name;
165 Description = description;
166 UnitName = unitName;
167 Category = category;
168 Container = container;
169 StatType = type;
170
171 if (StatType == StatType.Push && pullAction != null)
172 throw new Exception("A push stat cannot have a pull action");
173 else
174 PullAction = pullAction;
175
176 MeasuresOfInterest = moi;
177
178 if ((moi & MeasuresOfInterest.AverageChangeOverTime) == MeasuresOfInterest.AverageChangeOverTime)
179 m_samples = new Queue<double>(m_maxSamples);
180
181 Verbosity = verbosity;
182 }
183
184 /// <summary>
185 /// Record a value in the sample set.
186 /// </summary>
187 /// <remarks>
188 /// Do not call this if MeasuresOfInterest.None
189 /// </remarks>
190 public void RecordValue()
191 {
192 double newValue = Value;
193
194 lock (m_samples)
195 {
196 if (m_samples.Count >= m_maxSamples)
197 m_samples.Dequeue();
198
199 m_samples.Enqueue(newValue);
200 }
201 }
202
203 public virtual string ToConsoleString()
204 {
205 StringBuilder sb = new StringBuilder();
206 sb.AppendFormat("{0}.{1}.{2} : {3}{4}", Category, Container, ShortName, Value, UnitName);
207
208 AppendMeasuresOfInterest(sb);
209
210 return sb.ToString();
211 }
212
213 protected void AppendMeasuresOfInterest(StringBuilder sb)
214 {
215 if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime)
216 == MeasuresOfInterest.AverageChangeOverTime)
217 {
218 double totalChange = 0;
219 double? lastSample = null;
220
221 lock (m_samples)
222 {
223 foreach (double s in m_samples)
224 {
225 if (lastSample != null)
226 totalChange += s - (double)lastSample;
227
228 lastSample = s;
229 }
230 }
231
232 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1;
233
234 sb.AppendFormat(", {0:0.##}{1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName);
235 }
236 }
237 }
238} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index d78fa6a..0762b01 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -25,6 +25,10 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Collections.Generic;
30using System.Text;
31
28namespace OpenSim.Framework.Monitoring 32namespace OpenSim.Framework.Monitoring
29{ 33{
30 /// <summary> 34 /// <summary>
@@ -32,6 +36,24 @@ namespace OpenSim.Framework.Monitoring
32 /// </summary> 36 /// </summary>
33 public class StatsManager 37 public class StatsManager
34 { 38 {
39 // Subcommand used to list other stats.
40 public const string AllSubCommand = "all";
41
42 // Subcommand used to list other stats.
43 public const string ListSubCommand = "list";
44
45 // All subcommands
46 public static HashSet<string> SubCommands = new HashSet<string> { AllSubCommand, ListSubCommand };
47
48 /// <summary>
49 /// Registered stats categorized by category/container/shortname
50 /// </summary>
51 /// <remarks>
52 /// Do not add or remove directly from this dictionary.
53 /// </remarks>
54 public static Dictionary<string, Dictionary<string, Dictionary<string, Stat>>> RegisteredStats
55 = new Dictionary<string, Dictionary<string, Dictionary<string, Stat>>>();
56
35 private static AssetStatsCollector assetStats; 57 private static AssetStatsCollector assetStats;
36 private static UserStatsCollector userStats; 58 private static UserStatsCollector userStats;
37 private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); 59 private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
@@ -40,6 +62,75 @@ namespace OpenSim.Framework.Monitoring
40 public static UserStatsCollector UserStats { get { return userStats; } } 62 public static UserStatsCollector UserStats { get { return userStats; } }
41 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } 63 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
42 64
65 public static void RegisterConsoleCommands(ICommandConsole console)
66 {
67 console.Commands.AddCommand(
68 "General",
69 false,
70 "show stats",
71 "show stats [list|all|<category>]",
72 "Show statistical information for this server",
73 "If no final argument is specified then legacy statistics information is currently shown.\n"
74 + "If list is specified then statistic categories are shown.\n"
75 + "If all is specified then all registered statistics are shown.\n"
76 + "If a category name is specified then only statistics from that category are shown.\n"
77 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
78 HandleShowStatsCommand);
79 }
80
81 public static void HandleShowStatsCommand(string module, string[] cmd)
82 {
83 ICommandConsole con = MainConsole.Instance;
84
85 if (cmd.Length > 2)
86 {
87 var categoryName = cmd[2];
88
89 if (categoryName == AllSubCommand)
90 {
91 foreach (var category in RegisteredStats.Values)
92 {
93 OutputCategoryStatsToConsole(con, category);
94 }
95 }
96 else if (categoryName == ListSubCommand)
97 {
98 con.Output("Statistic categories available are:");
99 foreach (string category in RegisteredStats.Keys)
100 con.OutputFormat(" {0}", category);
101 }
102 else
103 {
104 Dictionary<string, Dictionary<string, Stat>> category;
105 if (!RegisteredStats.TryGetValue(categoryName, out category))
106 {
107 con.OutputFormat("No such category as {0}", categoryName);
108 }
109 else
110 {
111 OutputCategoryStatsToConsole(con, category);
112 }
113 }
114 }
115 else
116 {
117 // Legacy
118 con.Output(SimExtraStats.Report());
119 }
120 }
121
122 private static void OutputCategoryStatsToConsole(
123 ICommandConsole con, Dictionary<string, Dictionary<string, Stat>> category)
124 {
125 foreach (var container in category.Values)
126 {
127 foreach (Stat stat in container.Values)
128 {
129 con.Output(stat.ToConsoleString());
130 }
131 }
132 }
133
43 /// <summary> 134 /// <summary>
44 /// Start collecting statistics related to assets. 135 /// Start collecting statistics related to assets.
45 /// Should only be called once. 136 /// Should only be called once.
@@ -61,5 +152,153 @@ namespace OpenSim.Framework.Monitoring
61 152
62 return userStats; 153 return userStats;
63 } 154 }
155
156 /// <summary>
157 /// Registers a statistic.
158 /// </summary>
159 /// <param name='stat'></param>
160 /// <returns></returns>
161 public static bool RegisterStat(Stat stat)
162 {
163 Dictionary<string, Dictionary<string, Stat>> category = null, newCategory;
164 Dictionary<string, Stat> container = null, newContainer;
165
166 lock (RegisteredStats)
167 {
168 // Stat name is not unique across category/container/shortname key.
169 // XXX: For now just return false. This is to avoid problems in regression tests where all tests
170 // in a class are run in the same instance of the VM.
171 if (TryGetStat(stat, out category, out container))
172 return false;
173
174 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
175 // This means that we don't need to lock or copy them on iteration, which will be a much more
176 // common operation after startup.
177 if (container != null)
178 newContainer = new Dictionary<string, Stat>(container);
179 else
180 newContainer = new Dictionary<string, Stat>();
181
182 if (category != null)
183 newCategory = new Dictionary<string, Dictionary<string, Stat>>(category);
184 else
185 newCategory = new Dictionary<string, Dictionary<string, Stat>>();
186
187 newContainer[stat.ShortName] = stat;
188 newCategory[stat.Container] = newContainer;
189 RegisteredStats[stat.Category] = newCategory;
190 }
191
192 return true;
193 }
194
195 /// <summary>
196 /// Deregister a statistic
197 /// </summary>>
198 /// <param name='stat'></param>
199 /// <returns></returns
200 public static bool DeregisterStat(Stat stat)
201 {
202 Dictionary<string, Dictionary<string, Stat>> category = null, newCategory;
203 Dictionary<string, Stat> container = null, newContainer;
204
205 lock (RegisteredStats)
206 {
207 if (!TryGetStat(stat, out category, out container))
208 return false;
209
210 newContainer = new Dictionary<string, Stat>(container);
211 newContainer.Remove(stat.ShortName);
212
213 newCategory = new Dictionary<string, Dictionary<string, Stat>>(category);
214 newCategory.Remove(stat.Container);
215
216 newCategory[stat.Container] = newContainer;
217 RegisteredStats[stat.Category] = newCategory;
218
219 return true;
220 }
221 }
222
223 public static bool TryGetStats(string category, out Dictionary<string, Dictionary<string, Stat>> stats)
224 {
225 return RegisteredStats.TryGetValue(category, out stats);
226 }
227
228 public static bool TryGetStat(
229 Stat stat,
230 out Dictionary<string, Dictionary<string, Stat>> category,
231 out Dictionary<string, Stat> container)
232 {
233 category = null;
234 container = null;
235
236 lock (RegisteredStats)
237 {
238 if (RegisteredStats.TryGetValue(stat.Category, out category))
239 {
240 if (category.TryGetValue(stat.Container, out container))
241 {
242 if (container.ContainsKey(stat.ShortName))
243 return true;
244 }
245 }
246 }
247
248 return false;
249 }
250
251 public static void RecordStats()
252 {
253 lock (RegisteredStats)
254 {
255 foreach (Dictionary<string, Dictionary<string, Stat>> category in RegisteredStats.Values)
256 {
257 foreach (Dictionary<string, Stat> container in category.Values)
258 {
259 foreach (Stat stat in container.Values)
260 {
261 if (stat.MeasuresOfInterest != MeasuresOfInterest.None)
262 stat.RecordValue();
263 }
264 }
265 }
266 }
267 }
268 }
269
270 /// <summary>
271 /// Stat type.
272 /// </summary>
273 /// <remarks>
274 /// A push stat is one which is continually updated and so it's value can simply by read.
275 /// A pull stat is one where reading the value triggers a collection method - the stat is not continually updated.
276 /// </remarks>
277 public enum StatType
278 {
279 Push,
280 Pull
281 }
282
283 /// <summary>
284 /// Measures of interest for this stat.
285 /// </summary>
286 [Flags]
287 public enum MeasuresOfInterest
288 {
289 None,
290 AverageChangeOverTime
291 }
292
293 /// <summary>
294 /// Verbosity of stat.
295 /// </summary>
296 /// <remarks>
297 /// Info will always be displayed.
298 /// </remarks>
299 public enum StatVerbosity
300 {
301 Debug,
302 Info
64 } 303 }
65} \ No newline at end of file 304} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index b709baa..69d2db5 100644
--- a/OpenSim/Framework/Monitoring/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -39,7 +39,7 @@ namespace OpenSim.Framework.Monitoring
39 public static class Watchdog 39 public static class Watchdog
40 { 40 {
41 /// <summary>Timer interval in milliseconds for the watchdog timer</summary> 41 /// <summary>Timer interval in milliseconds for the watchdog timer</summary>
42 const double WATCHDOG_INTERVAL_MS = 2500.0d; 42 public const double WATCHDOG_INTERVAL_MS = 2500.0d;
43 43
44 /// <summary>Default timeout in milliseconds before a thread is considered dead</summary> 44 /// <summary>Default timeout in milliseconds before a thread is considered dead</summary>
45 public const int DEFAULT_WATCHDOG_TIMEOUT_MS = 5000; 45 public const int DEFAULT_WATCHDOG_TIMEOUT_MS = 5000;
@@ -89,6 +89,17 @@ namespace OpenSim.Framework.Monitoring
89 FirstTick = Environment.TickCount & Int32.MaxValue; 89 FirstTick = Environment.TickCount & Int32.MaxValue;
90 LastTick = FirstTick; 90 LastTick = FirstTick;
91 } 91 }
92
93 public ThreadWatchdogInfo(ThreadWatchdogInfo previousTwi)
94 {
95 Thread = previousTwi.Thread;
96 FirstTick = previousTwi.FirstTick;
97 LastTick = previousTwi.LastTick;
98 Timeout = previousTwi.Timeout;
99 IsTimedOut = previousTwi.IsTimedOut;
100 AlarmIfTimeout = previousTwi.AlarmIfTimeout;
101 AlarmMethod = previousTwi.AlarmMethod;
102 }
92 } 103 }
93 104
94 /// <summary> 105 /// <summary>
@@ -220,7 +231,25 @@ namespace OpenSim.Framework.Monitoring
220 private static bool RemoveThread(int threadID) 231 private static bool RemoveThread(int threadID)
221 { 232 {
222 lock (m_threads) 233 lock (m_threads)
223 return m_threads.Remove(threadID); 234 {
235 ThreadWatchdogInfo twi;
236 if (m_threads.TryGetValue(threadID, out twi))
237 {
238 m_log.DebugFormat(
239 "[WATCHDOG]: Removing thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
240
241 m_threads.Remove(threadID);
242
243 return true;
244 }
245 else
246 {
247 m_log.WarnFormat(
248 "[WATCHDOG]: Requested to remove thread with ID {0} but this is not being monitored", threadID);
249
250 return false;
251 }
252 }
224 } 253 }
225 254
226 public static bool AbortThread(int threadID) 255 public static bool AbortThread(int threadID)
@@ -335,7 +364,9 @@ namespace OpenSim.Framework.Monitoring
335 if (callbackInfos == null) 364 if (callbackInfos == null)
336 callbackInfos = new List<ThreadWatchdogInfo>(); 365 callbackInfos = new List<ThreadWatchdogInfo>();
337 366
338 callbackInfos.Add(threadInfo); 367 // Send a copy of the watchdog info to prevent race conditions where the watchdog
368 // thread updates the monitoring info after an alarm has been sent out.
369 callbackInfos.Add(new ThreadWatchdogInfo(threadInfo));
339 } 370 }
340 } 371 }
341 } 372 }
@@ -349,6 +380,8 @@ namespace OpenSim.Framework.Monitoring
349 if (MemoryWatchdog.Enabled) 380 if (MemoryWatchdog.Enabled)
350 MemoryWatchdog.Update(); 381 MemoryWatchdog.Update();
351 382
383 StatsManager.RecordStats();
384
352 m_watchdogTimer.Start(); 385 m_watchdogTimer.Start();
353 } 386 }
354 } 387 }
diff --git a/OpenSim/Services/InventoryService/InventoryServiceBase.cs b/OpenSim/Framework/Pool.cs
index 456e455..5484f5c 100644
--- a/OpenSim/Services/InventoryService/InventoryServiceBase.cs
+++ b/OpenSim/Framework/Pool.cs
@@ -27,56 +27,65 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection;
31using Nini.Config;
32using OpenSim.Framework;
33using OpenSim.Data;
34using OpenSim.Services.Interfaces;
35using OpenSim.Services.Base;
36 30
37namespace OpenSim.Services.InventoryService 31namespace OpenSim.Framework
38{ 32{
39 public class InventoryServiceBase : ServiceBase 33 /// <summary>
34 /// Naive pool implementation.
35 /// </summary>
36 /// <remarks>
37 /// Currently assumes that objects are in a useable state when returned.
38 /// </remarks>
39 public class Pool<T>
40 { 40 {
41 protected IInventoryDataPlugin m_Database = null; 41 /// <summary>
42 42 /// Number of objects in the pool.
43 public InventoryServiceBase(IConfigSource config) : base(config) 43 /// </summary>
44 public int Count
44 { 45 {
45 string dllName = String.Empty; 46 get
46 string connString = String.Empty;
47
48 //
49 // Try reading the [DatabaseService] section first, if it exists
50 //
51 IConfig dbConfig = config.Configs["DatabaseService"];
52 if (dbConfig != null)
53 { 47 {
54 dllName = dbConfig.GetString("StorageProvider", String.Empty); 48 lock (m_pool)
55 connString = dbConfig.GetString("ConnectionString", String.Empty); 49 return m_pool.Count;
56 } 50 }
51 }
57 52
58 // 53 private Stack<T> m_pool;
59 // Try reading the more specific [InventoryService] section, if it exists
60 //
61 IConfig inventoryConfig = config.Configs["InventoryService"];
62 if (inventoryConfig != null)
63 {
64 dllName = inventoryConfig.GetString("StorageProvider", dllName);
65 connString = inventoryConfig.GetString("ConnectionString", connString);
66 }
67 54
68 // 55 /// <summary>
69 // We tried, but this doesn't exist. We can't proceed. 56 /// Maximum pool size. Beyond this, any returned objects are not pooled.
70 // 57 /// </summary>
71 if (dllName.Equals(String.Empty)) 58 private int m_maxPoolSize;
72 throw new Exception("No InventoryService configuration");
73 59
74 m_Database = LoadPlugin<IInventoryDataPlugin>(dllName); 60 private Func<T> m_createFunction;
75 if (m_Database == null)
76 throw new Exception("Could not find a storage interface in the given module");
77 61
78 m_Database.Initialise(connString); 62 public Pool(Func<T> createFunction, int maxSize)
63 {
64 m_maxPoolSize = maxSize;
65 m_createFunction = createFunction;
66 m_pool = new Stack<T>(m_maxPoolSize);
79 } 67 }
80 68
69 public T GetObject()
70 {
71 lock (m_pool)
72 {
73 if (m_pool.Count > 0)
74 return m_pool.Pop();
75 else
76 return m_createFunction();
77 }
78 }
79
80 public void ReturnObject(T obj)
81 {
82 lock (m_pool)
83 {
84 if (m_pool.Count >= m_maxPoolSize)
85 return;
86 else
87 m_pool.Push(obj);
88 }
89 }
81 } 90 }
82} 91} \ No newline at end of file
diff --git a/OpenSim/Framework/RegionFlags.cs b/OpenSim/Framework/RegionFlags.cs
new file mode 100644
index 0000000..a3089b0
--- /dev/null
+++ b/OpenSim/Framework/RegionFlags.cs
@@ -0,0 +1,53 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29
30namespace OpenSim.Framework
31{
32 /// <summary>
33 /// Region flags used internally by OpenSimulator to store installation specific information about regions.
34 /// </summary>
35 /// <remarks>
36 /// Don't confuse with OpenMetaverse.RegionFlags which are client facing flags (i.e. they go over the wire).
37 /// Returned by IGridService.GetRegionFlags()
38 /// </remarks>
39 [Flags]
40 public enum RegionFlags : int
41 {
42 DefaultRegion = 1, // Used for new Rez. Random if multiple defined
43 FallbackRegion = 2, // Regions we redirect to when the destination is down
44 RegionOnline = 4, // Set when a region comes online, unset when it unregisters and DeleteOnUnregister is false
45 NoDirectLogin = 8, // Region unavailable for direct logins (by name)
46 Persistent = 16, // Don't remove on unregister
47 LockedOut = 32, // Don't allow registration
48 NoMove = 64, // Don't allow moving this region
49 Reservation = 128, // This is an inactive reservation
50 Authenticate = 256, // Require authentication
51 Hyperlink = 512 // Record represents a HG link
52 }
53} \ No newline at end of file
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index 4bde7be..e7bed6a 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -122,10 +122,13 @@ namespace OpenSim.Framework
122 public UUID lastMapUUID = UUID.Zero; 122 public UUID lastMapUUID = UUID.Zero;
123 public string lastMapRefresh = "0"; 123 public string lastMapRefresh = "0";
124 124
125 private float m_nonphysPrimMin = 0;
125 private int m_nonphysPrimMax = 0; 126 private int m_nonphysPrimMax = 0;
127 private float m_physPrimMin = 0;
126 private int m_physPrimMax = 0; 128 private int m_physPrimMax = 0;
127 private bool m_clampPrimSize = false; 129 private bool m_clampPrimSize = false;
128 private int m_objectCapacity = 0; 130 private int m_objectCapacity = 0;
131 private int m_linksetCapacity = 0;
129 private int m_agentCapacity = 0; 132 private int m_agentCapacity = 0;
130 private string m_regionType = String.Empty; 133 private string m_regionType = String.Empty;
131 private RegionLightShareData m_windlight = new RegionLightShareData(); 134 private RegionLightShareData m_windlight = new RegionLightShareData();
@@ -287,11 +290,21 @@ namespace OpenSim.Framework
287 set { m_windlight = value; } 290 set { m_windlight = value; }
288 } 291 }
289 292
293 public float NonphysPrimMin
294 {
295 get { return m_nonphysPrimMin; }
296 }
297
290 public int NonphysPrimMax 298 public int NonphysPrimMax
291 { 299 {
292 get { return m_nonphysPrimMax; } 300 get { return m_nonphysPrimMax; }
293 } 301 }
294 302
303 public float PhysPrimMin
304 {
305 get { return m_physPrimMin; }
306 }
307
295 public int PhysPrimMax 308 public int PhysPrimMax
296 { 309 {
297 get { return m_physPrimMax; } 310 get { return m_physPrimMax; }
@@ -307,6 +320,11 @@ namespace OpenSim.Framework
307 get { return m_objectCapacity; } 320 get { return m_objectCapacity; }
308 } 321 }
309 322
323 public int LinksetCapacity
324 {
325 get { return m_linksetCapacity; }
326 }
327
310 public int AgentCapacity 328 public int AgentCapacity
311 { 329 {
312 get { return m_agentCapacity; } 330 get { return m_agentCapacity; }
@@ -625,16 +643,31 @@ namespace OpenSim.Framework
625 m_regionType = config.GetString("RegionType", String.Empty); 643 m_regionType = config.GetString("RegionType", String.Empty);
626 allKeys.Remove("RegionType"); 644 allKeys.Remove("RegionType");
627 645
628 // Prim stuff 646 #region Prim stuff
629 // 647
630 m_nonphysPrimMax = config.GetInt("NonphysicalPrimMax", 0); 648 m_nonphysPrimMin = config.GetFloat("NonPhysicalPrimMin", 0);
631 allKeys.Remove("NonphysicalPrimMax"); 649 allKeys.Remove("NonPhysicalPrimMin");
650
651 m_nonphysPrimMax = config.GetInt("NonPhysicalPrimMax", 0);
652 allKeys.Remove("NonPhysicalPrimMax");
653
654 m_physPrimMin = config.GetFloat("PhysicalPrimMin", 0);
655 allKeys.Remove("PhysicalPrimMin");
656
632 m_physPrimMax = config.GetInt("PhysicalPrimMax", 0); 657 m_physPrimMax = config.GetInt("PhysicalPrimMax", 0);
633 allKeys.Remove("PhysicalPrimMax"); 658 allKeys.Remove("PhysicalPrimMax");
659
634 m_clampPrimSize = config.GetBoolean("ClampPrimSize", false); 660 m_clampPrimSize = config.GetBoolean("ClampPrimSize", false);
635 allKeys.Remove("ClampPrimSize"); 661 allKeys.Remove("ClampPrimSize");
662
636 m_objectCapacity = config.GetInt("MaxPrims", 15000); 663 m_objectCapacity = config.GetInt("MaxPrims", 15000);
637 allKeys.Remove("MaxPrims"); 664 allKeys.Remove("MaxPrims");
665
666 m_linksetCapacity = config.GetInt("LinksetPrims", 0);
667 allKeys.Remove("LinksetPrims");
668
669 #endregion
670
638 m_agentCapacity = config.GetInt("MaxAgents", 100); 671 m_agentCapacity = config.GetInt("MaxAgents", 100);
639 allKeys.Remove("MaxAgents"); 672 allKeys.Remove("MaxAgents");
640 673
@@ -673,16 +706,27 @@ namespace OpenSim.Framework
673 706
674 config.Set("ExternalHostName", m_externalHostName); 707 config.Set("ExternalHostName", m_externalHostName);
675 708
676 if (m_nonphysPrimMax != 0) 709 if (m_nonphysPrimMin > 0)
710 config.Set("NonphysicalPrimMax", m_nonphysPrimMin);
711
712 if (m_nonphysPrimMax > 0)
677 config.Set("NonphysicalPrimMax", m_nonphysPrimMax); 713 config.Set("NonphysicalPrimMax", m_nonphysPrimMax);
678 if (m_physPrimMax != 0) 714
715 if (m_physPrimMin > 0)
716 config.Set("PhysicalPrimMax", m_physPrimMin);
717
718 if (m_physPrimMax > 0)
679 config.Set("PhysicalPrimMax", m_physPrimMax); 719 config.Set("PhysicalPrimMax", m_physPrimMax);
720
680 config.Set("ClampPrimSize", m_clampPrimSize.ToString()); 721 config.Set("ClampPrimSize", m_clampPrimSize.ToString());
681 722
682 if (m_objectCapacity != 0) 723 if (m_objectCapacity > 0)
683 config.Set("MaxPrims", m_objectCapacity); 724 config.Set("MaxPrims", m_objectCapacity);
684 725
685 if (m_agentCapacity != 0) 726 if (m_linksetCapacity > 0)
727 config.Set("LinksetPrims", m_linksetCapacity);
728
729 if (m_agentCapacity > 0)
686 config.Set("MaxAgents", m_agentCapacity); 730 config.Set("MaxAgents", m_agentCapacity);
687 731
688 if (ScopeID != UUID.Zero) 732 if (ScopeID != UUID.Zero)
@@ -759,9 +803,15 @@ namespace OpenSim.Framework
759 configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, 803 configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
760 "Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true); 804 "Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true);
761 805
806 configMember.addConfigurationOption("nonphysical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
807 "Minimum size for nonphysical prims", m_nonphysPrimMin.ToString(), true);
808
762 configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 809 configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
763 "Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true); 810 "Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true);
764 811
812 configMember.addConfigurationOption("physical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
813 "Minimum size for nonphysical prims", m_physPrimMin.ToString(), true);
814
765 configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 815 configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
766 "Maximum size for physical prims", m_physPrimMax.ToString(), true); 816 "Maximum size for physical prims", m_physPrimMax.ToString(), true);
767 817
@@ -771,6 +821,9 @@ namespace OpenSim.Framework
771 configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 821 configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
772 "Max objects this sim will hold", m_objectCapacity.ToString(), true); 822 "Max objects this sim will hold", m_objectCapacity.ToString(), true);
773 823
824 configMember.addConfigurationOption("linkset_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
825 "Max prims an object will hold", m_linksetCapacity.ToString(), true);
826
774 configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 827 configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
775 "Max avatars this sim will hold", m_agentCapacity.ToString(), true); 828 "Max avatars this sim will hold", m_agentCapacity.ToString(), true);
776 829
@@ -892,6 +945,9 @@ namespace OpenSim.Framework
892 case "object_capacity": 945 case "object_capacity":
893 m_objectCapacity = (int)configuration_result; 946 m_objectCapacity = (int)configuration_result;
894 break; 947 break;
948 case "linkset_capacity":
949 m_linksetCapacity = (int)configuration_result;
950 break;
895 case "agent_capacity": 951 case "agent_capacity":
896 m_agentCapacity = (int)configuration_result; 952 m_agentCapacity = (int)configuration_result;
897 break; 953 break;
diff --git a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..d670f2f
--- /dev/null
+++ b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Framework.RegionLoader.Filesystem")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("4ab5c74b-e886-40a1-b67d-a04df285e706")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..7309a12
--- /dev/null
+++ b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Framework.RegionLoader.Web")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("985afff8-e7ed-4056-acce-39abf7a43d33")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Serialization/ArchiveConstants.cs b/OpenSim/Framework/Serialization/ArchiveConstants.cs
index 2c5e001..48f1c4f 100644
--- a/OpenSim/Framework/Serialization/ArchiveConstants.cs
+++ b/OpenSim/Framework/Serialization/ArchiveConstants.cs
@@ -53,6 +53,11 @@ namespace OpenSim.Framework.Serialization
53 public const string INVENTORY_PATH = "inventory/"; 53 public const string INVENTORY_PATH = "inventory/";
54 54
55 /// <value> 55 /// <value>
56 /// Path for regions in a multi-region archive
57 /// </value>
58 public const string REGIONS_PATH = "regions/";
59
60 /// <value>
56 /// Path for the prims file 61 /// Path for the prims file
57 /// </value> 62 /// </value>
58 public const string OBJECTS_PATH = "objects/"; 63 public const string OBJECTS_PATH = "objects/";
diff --git a/OpenSim/Framework/Serialization/External/OspResolver.cs b/OpenSim/Framework/Serialization/External/OspResolver.cs
index d31d27c..fa7160f 100644
--- a/OpenSim/Framework/Serialization/External/OspResolver.cs
+++ b/OpenSim/Framework/Serialization/External/OspResolver.cs
@@ -65,9 +65,14 @@ namespace OpenSim.Framework.Serialization
65 65
66 UserAccount account = userService.GetUserAccount(UUID.Zero, userId); 66 UserAccount account = userService.GetUserAccount(UUID.Zero, userId);
67 if (account != null) 67 if (account != null)
68 {
68 return MakeOspa(account.FirstName, account.LastName); 69 return MakeOspa(account.FirstName, account.LastName);
70 }
69// else 71// else
72// {
70// m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId); 73// m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId);
74// System.Console.WriteLine("[OSP RESOLVER]: No user account for {0}", userId);
75// }
71 76
72 return null; 77 return null;
73 } 78 }
@@ -79,10 +84,13 @@ namespace OpenSim.Framework.Serialization
79 /// <returns></returns> 84 /// <returns></returns>
80 public static string MakeOspa(string firstName, string lastName) 85 public static string MakeOspa(string firstName, string lastName)
81 { 86 {
82// m_log.DebugFormat("[OSP RESOLVER]: Making OSPA for {0} {1}", firstName, lastName); 87 string ospa
88 = OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName;
89
90// m_log.DebugFormat("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
91// System.Console.WriteLine("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
83 92
84 return 93 return ospa;
85 OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName;
86 } 94 }
87 95
88 /// <summary> 96 /// <summary>
diff --git a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..11efa4b
--- /dev/null
+++ b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Framework.Serialization")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("919db41e-4ac0-4f24-9992-81d62c0ee183")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index cf19002..2c21800 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -38,6 +38,8 @@ using log4net;
38using log4net.Appender; 38using log4net.Appender;
39using log4net.Core; 39using log4net.Core;
40using log4net.Repository; 40using log4net.Repository;
41using OpenMetaverse;
42using OpenMetaverse.StructuredData;
41using OpenSim.Framework; 43using OpenSim.Framework;
42using OpenSim.Framework.Console; 44using OpenSim.Framework.Console;
43using OpenSim.Framework.Monitoring; 45using OpenSim.Framework.Monitoring;
@@ -45,16 +47,12 @@ using OpenSim.Framework.Servers;
45using OpenSim.Framework.Servers.HttpServer; 47using OpenSim.Framework.Servers.HttpServer;
46using Timer=System.Timers.Timer; 48using Timer=System.Timers.Timer;
47 49
48using OpenMetaverse;
49using OpenMetaverse.StructuredData;
50
51
52namespace OpenSim.Framework.Servers 50namespace OpenSim.Framework.Servers
53{ 51{
54 /// <summary> 52 /// <summary>
55 /// Common base for the main OpenSimServers (user, grid, inventory, region, etc) 53 /// Common base for the main OpenSimServers (user, grid, inventory, region, etc)
56 /// </summary> 54 /// </summary>
57 public abstract class BaseOpenSimServer 55 public abstract class BaseOpenSimServer : ServerBase
58 { 56 {
59 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 57 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60 58
@@ -63,27 +61,6 @@ namespace OpenSim.Framework.Servers
63 /// server. 61 /// server.
64 /// </summary> 62 /// </summary>
65 private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000); 63 private Timer m_periodicDiagnosticsTimer = new Timer(60 * 60 * 1000);
66
67 protected CommandConsole m_console;
68 protected OpenSimAppender m_consoleAppender;
69 protected IAppender m_logFileAppender = null;
70
71 /// <summary>
72 /// Time at which this server was started
73 /// </summary>
74 protected DateTime m_startuptime;
75
76 /// <summary>
77 /// Record the initial startup directory for info purposes
78 /// </summary>
79 protected string m_startupDirectory = Environment.CurrentDirectory;
80
81 /// <summary>
82 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
83 /// </summary>
84 protected string m_version;
85
86 protected string m_pidFile = String.Empty;
87 64
88 /// <summary> 65 /// <summary>
89 /// Random uuid for private data 66 /// Random uuid for private data
@@ -96,35 +73,13 @@ namespace OpenSim.Framework.Servers
96 get { return m_httpServer; } 73 get { return m_httpServer; }
97 } 74 }
98 75
99 /// <summary> 76 public BaseOpenSimServer() : base()
100 /// Holds the non-viewer statistics collection object for this service/server
101 /// </summary>
102 protected IStatsCollector m_stats;
103
104 public BaseOpenSimServer()
105 { 77 {
106 m_startuptime = DateTime.Now;
107 m_version = VersionInfo.Version;
108
109 // Random uuid for private data 78 // Random uuid for private data
110 m_osSecret = UUID.Random().ToString(); 79 m_osSecret = UUID.Random().ToString();
111 80
112 m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics); 81 m_periodicDiagnosticsTimer.Elapsed += new ElapsedEventHandler(LogDiagnostics);
113 m_periodicDiagnosticsTimer.Enabled = true; 82 m_periodicDiagnosticsTimer.Enabled = true;
114
115 // This thread will go on to become the console listening thread
116 Thread.CurrentThread.Name = "ConsoleThread";
117
118 ILoggerRepository repository = LogManager.GetRepository();
119 IAppender[] appenders = repository.GetAppenders();
120
121 foreach (IAppender appender in appenders)
122 {
123 if (appender.Name == "LogFileAppender")
124 {
125 m_logFileAppender = appender;
126 }
127 }
128 } 83 }
129 84
130 /// <summary> 85 /// <summary>
@@ -132,76 +87,46 @@ namespace OpenSim.Framework.Servers
132 /// </summary> 87 /// </summary>
133 protected virtual void StartupSpecific() 88 protected virtual void StartupSpecific()
134 { 89 {
135 if (m_console != null) 90 if (m_console == null)
136 { 91 return;
137 ILoggerRepository repository = LogManager.GetRepository(); 92
138 IAppender[] appenders = repository.GetAppenders(); 93 RegisterCommonCommands();
139 94
140 foreach (IAppender appender in appenders) 95 m_console.Commands.AddCommand("General", false, "quit",
141 { 96 "quit",
142 if (appender.Name == "Console") 97 "Quit the application", HandleQuit);
143 { 98
144 m_consoleAppender = (OpenSimAppender)appender; 99 m_console.Commands.AddCommand("General", false, "shutdown",
145 break; 100 "shutdown",
146 } 101 "Quit the application", HandleQuit);
147 } 102
148 103 m_console.Commands.AddCommand("General", false, "show threads",
149 if (null == m_consoleAppender) 104 "show threads",
150 { 105 "Show thread status", HandleShow);
151 Notice("No appender named Console found (see the log4net config file for this executable)!"); 106
152 } 107 m_console.Commands.AddCommand("General", false, "show version",
153 else 108 "show version",
154 { 109 "Show server version", HandleShow);
155 m_consoleAppender.Console = m_console; 110
156 111 m_console.Commands.AddCommand("General", false, "threads abort",
157 // If there is no threshold set then the threshold is effectively everything. 112 "threads abort <thread-id>",
158 if (null == m_consoleAppender.Threshold) 113 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
159 m_consoleAppender.Threshold = Level.All; 114
160 115 m_console.Commands.AddCommand("General", false, "threads show",
161 Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold)); 116 "threads show",
162 } 117 "Show thread status. Synonym for \"show threads\"",
163 118 (string module, string[] args) => Notice(GetThreadsReport()));
164 m_console.Commands.AddCommand("General", false, "quit", 119
165 "quit", 120 m_console.Commands.AddCommand("General", false, "force gc",
166 "Quit the application", HandleQuit); 121 "force gc",
167 122 "Manually invoke runtime garbage collection. For debugging purposes",
168 m_console.Commands.AddCommand("General", false, "shutdown", 123 HandleForceGc);
169 "shutdown", 124 }
170 "Quit the application", HandleQuit); 125
171 126 private void HandleForceGc(string module, string[] args)
172 m_console.Commands.AddCommand("General", false, "set log level", 127 {
173 "set log level <level>", 128 MainConsole.Instance.Output("Manually invoking runtime garbage collection");
174 "Set the console logging level", HandleLogLevel); 129 GC.Collect();
175
176 m_console.Commands.AddCommand("General", false, "show info",
177 "show info",
178 "Show general information about the server", HandleShow);
179
180 m_console.Commands.AddCommand("General", false, "show stats",
181 "show stats",
182 "Show statistics", HandleShow);
183
184 m_console.Commands.AddCommand("General", false, "show threads",
185 "show threads",
186 "Show thread status", HandleShow);
187
188 m_console.Commands.AddCommand("General", false, "show uptime",
189 "show uptime",
190 "Show server uptime", HandleShow);
191
192 m_console.Commands.AddCommand("General", false, "show version",
193 "show version",
194 "Show server version", HandleShow);
195
196 m_console.Commands.AddCommand("General", false, "threads abort",
197 "threads abort <thread-id>",
198 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
199
200 m_console.Commands.AddCommand("General", false, "threads show",
201 "threads show",
202 "Show thread status. Synonym for \"show threads\"",
203 (string module, string[] args) => Notice(GetThreadsReport()));
204 }
205 } 130 }
206 131
207 /// <summary> 132 /// <summary>
@@ -226,12 +151,7 @@ namespace OpenSim.Framework.Servers
226 { 151 {
227 StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n"); 152 StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n");
228 sb.Append(GetUptimeReport()); 153 sb.Append(GetUptimeReport());
229 154 sb.Append(StatsManager.SimExtraStats.Report());
230 if (m_stats != null)
231 {
232 sb.Append(m_stats.Report());
233 }
234
235 sb.Append(Environment.NewLine); 155 sb.Append(Environment.NewLine);
236 sb.Append(GetThreadsReport()); 156 sb.Append(GetThreadsReport());
237 157
@@ -287,26 +207,11 @@ namespace OpenSim.Framework.Servers
287 } 207 }
288 208
289 /// <summary> 209 /// <summary>
290 /// Return a report about the uptime of this server
291 /// </summary>
292 /// <returns></returns>
293 protected string GetUptimeReport()
294 {
295 StringBuilder sb = new StringBuilder(String.Format("Time now is {0}\n", DateTime.Now));
296 sb.Append(String.Format("Server has been running since {0}, {1}\n", m_startuptime.DayOfWeek, m_startuptime));
297 sb.Append(String.Format("That is an elapsed time of {0}\n", DateTime.Now - m_startuptime));
298
299 return sb.ToString();
300 }
301
302 /// <summary>
303 /// Performs initialisation of the scene, such as loading configuration from disk. 210 /// Performs initialisation of the scene, such as loading configuration from disk.
304 /// </summary> 211 /// </summary>
305 public virtual void Startup() 212 public virtual void Startup()
306 { 213 {
307 m_log.Info("[STARTUP]: Beginning startup processing"); 214 m_log.Info("[STARTUP]: Beginning startup processing");
308
309 EnhanceVersionInformation();
310 215
311 m_log.Info("[STARTUP]: Careminster version: " + m_version + Environment.NewLine); 216 m_log.Info("[STARTUP]: Careminster version: " + m_version + Environment.NewLine);
312 // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and 217 // clr version potentially is more confusing than helpful, since it doesn't tell us if we're running under Mono/MS .NET and
@@ -343,60 +248,10 @@ namespace OpenSim.Framework.Servers
343 Shutdown(); 248 Shutdown();
344 } 249 }
345 250
346 private void HandleLogLevel(string module, string[] cmd) 251 public override void HandleShow(string module, string[] cmd)
347 {
348 if (null == m_consoleAppender)
349 {
350 Notice("No appender named Console found (see the log4net config file for this executable)!");
351 return;
352 }
353
354 if (cmd.Length > 3)
355 {
356 string rawLevel = cmd[3];
357
358 ILoggerRepository repository = LogManager.GetRepository();
359 Level consoleLevel = repository.LevelMap[rawLevel];
360
361 if (consoleLevel != null)
362 m_consoleAppender.Threshold = consoleLevel;
363 else
364 Notice(
365 String.Format(
366 "{0} is not a valid logging level. Valid logging levels are ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF",
367 rawLevel));
368 }
369
370 Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold));
371 }
372
373 /// <summary>
374 /// Show help information
375 /// </summary>
376 /// <param name="helpArgs"></param>
377 protected virtual void ShowHelp(string[] helpArgs)
378 { 252 {
379 Notice(""); 253 base.HandleShow(module, cmd);
380
381 if (helpArgs.Length == 0)
382 {
383 Notice("set log level [level] - change the console logging level only. For example, off or debug.");
384 Notice("show info - show server information (e.g. startup path).");
385
386 if (m_stats != null)
387 Notice("show stats - show statistical information for this server");
388
389 Notice("show threads - list tracked threads");
390 Notice("show uptime - show server startup time and uptime.");
391 Notice("show version - show server version.");
392 Notice("");
393 254
394 return;
395 }
396 }
397
398 public virtual void HandleShow(string module, string[] cmd)
399 {
400 List<string> args = new List<string>(cmd); 255 List<string> args = new List<string>(cmd);
401 256
402 args.RemoveAt(0); 257 args.RemoveAt(0);
@@ -405,23 +260,10 @@ namespace OpenSim.Framework.Servers
405 260
406 switch (showParams[0]) 261 switch (showParams[0])
407 { 262 {
408 case "info":
409 ShowInfo();
410 break;
411
412 case "stats":
413 if (m_stats != null)
414 Notice(m_stats.Report());
415 break;
416
417 case "threads": 263 case "threads":
418 Notice(GetThreadsReport()); 264 Notice(GetThreadsReport());
419 break; 265 break;
420 266
421 case "uptime":
422 Notice(GetUptimeReport());
423 break;
424
425 case "version": 267 case "version":
426 Notice(GetVersionText()); 268 Notice(GetVersionText());
427 break; 269 break;
@@ -447,165 +289,11 @@ namespace OpenSim.Framework.Servers
447 MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId); 289 MainConsole.Instance.OutputFormat("Aborted thread with id {0}", threadId);
448 else 290 else
449 MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId); 291 MainConsole.Instance.OutputFormat("ERROR - Thread with id {0} not found in managed threads", threadId);
450 } 292 }
451
452 protected void ShowInfo()
453 {
454 Notice(GetVersionText());
455 Notice("Startup directory: " + m_startupDirectory);
456 if (null != m_consoleAppender)
457 Notice(String.Format("Console log level: {0}", m_consoleAppender.Threshold));
458 }
459
460 protected string GetVersionText()
461 {
462 return String.Format("Version: {0} (interface version {1})", m_version, VersionInfo.MajorInterfaceVersion);
463 }
464
465 /// <summary>
466 /// Console output is only possible if a console has been established.
467 /// That is something that cannot be determined within this class. So
468 /// all attempts to use the console MUST be verified.
469 /// </summary>
470 /// <param name="msg"></param>
471 protected void Notice(string msg)
472 {
473 if (m_console != null)
474 {
475 m_console.Output(msg);
476 }
477 }
478
479 /// <summary>
480 /// Console output is only possible if a console has been established.
481 /// That is something that cannot be determined within this class. So
482 /// all attempts to use the console MUST be verified.
483 /// </summary>
484 /// <param name="format"></param>
485 /// <param name="components"></param>
486 protected void Notice(string format, params string[] components)
487 {
488 if (m_console != null)
489 m_console.OutputFormat(format, components);
490 }
491
492 /// <summary>
493 /// Enhance the version string with extra information if it's available.
494 /// </summary>
495 protected void EnhanceVersionInformation()
496 {
497 string buildVersion = string.Empty;
498
499 // The subversion information is deprecated and will be removed at a later date
500 // Add subversion revision information if available
501 // Try file "svn_revision" in the current directory first, then the .svn info.
502 // This allows to make the revision available in simulators not running from the source tree.
503 // FIXME: Making an assumption about the directory we're currently in - we do this all over the place
504 // elsewhere as well
505 string gitDir = "../.git/";
506 string gitRefPointerPath = gitDir + "HEAD";
507
508 string svnRevisionFileName = "svn_revision";
509 string svnFileName = ".svn/entries";
510 string manualVersionFileName = ".version";
511 string inputLine;
512 int strcmp;
513
514 if (File.Exists(manualVersionFileName))
515 {
516 using (StreamReader CommitFile = File.OpenText(manualVersionFileName))
517 buildVersion = CommitFile.ReadLine();
518
519 m_version += buildVersion ?? "";
520 }
521 else if (File.Exists(gitRefPointerPath))
522 {
523// m_log.DebugFormat("[OPENSIM]: Found {0}", gitRefPointerPath);
524
525 string rawPointer = "";
526
527 using (StreamReader pointerFile = File.OpenText(gitRefPointerPath))
528 rawPointer = pointerFile.ReadLine();
529
530// m_log.DebugFormat("[OPENSIM]: rawPointer [{0}]", rawPointer);
531
532 Match m = Regex.Match(rawPointer, "^ref: (.+)$");
533
534 if (m.Success)
535 {
536// m_log.DebugFormat("[OPENSIM]: Matched [{0}]", m.Groups[1].Value);
537
538 string gitRef = m.Groups[1].Value;
539 string gitRefPath = gitDir + gitRef;
540 if (File.Exists(gitRefPath))
541 {
542// m_log.DebugFormat("[OPENSIM]: Found gitRefPath [{0}]", gitRefPath);
543
544 using (StreamReader refFile = File.OpenText(gitRefPath))
545 {
546 string gitHash = refFile.ReadLine();
547 m_version += gitHash.Substring(0, 7);
548 }
549 }
550 }
551 }
552 else
553 {
554 // Remove the else logic when subversion mirror is no longer used
555 if (File.Exists(svnRevisionFileName))
556 {
557 StreamReader RevisionFile = File.OpenText(svnRevisionFileName);
558 buildVersion = RevisionFile.ReadLine();
559 buildVersion.Trim();
560 RevisionFile.Close();
561 }
562
563 if (string.IsNullOrEmpty(buildVersion) && File.Exists(svnFileName))
564 {
565 StreamReader EntriesFile = File.OpenText(svnFileName);
566 inputLine = EntriesFile.ReadLine();
567 while (inputLine != null)
568 {
569 // using the dir svn revision at the top of entries file
570 strcmp = String.Compare(inputLine, "dir");
571 if (strcmp == 0)
572 {
573 buildVersion = EntriesFile.ReadLine();
574 break;
575 }
576 else
577 {
578 inputLine = EntriesFile.ReadLine();
579 }
580 }
581 EntriesFile.Close();
582 }
583
584 m_version += string.IsNullOrEmpty(buildVersion) ? " " : ("." + buildVersion + " ").Substring(0, 6);
585 }
586 }
587
588 protected void CreatePIDFile(string path)
589 {
590 try
591 {
592 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
593 FileStream fs = File.Create(path);
594
595 Byte[] buf = Encoding.ASCII.GetBytes(pidstring);
596 fs.Write(buf, 0, buf.Length);
597 fs.Close();
598 m_pidFile = path;
599 }
600 catch (Exception)
601 {
602 }
603 }
604 293
605 public string osSecret { 294 public string osSecret {
606 // Secret uuid for the simulator 295 // Secret uuid for the simulator
607 get { return m_osSecret; } 296 get { return m_osSecret; }
608
609 } 297 }
610 298
611 public string StatReport(IOSHttpRequest httpRequest) 299 public string StatReport(IOSHttpRequest httpRequest)
@@ -613,27 +301,12 @@ namespace OpenSim.Framework.Servers
613 // If we catch a request for "callback", wrap the response in the value for jsonp 301 // If we catch a request for "callback", wrap the response in the value for jsonp
614 if (httpRequest.Query.ContainsKey("callback")) 302 if (httpRequest.Query.ContainsKey("callback"))
615 { 303 {
616 return httpRequest.Query["callback"].ToString() + "(" + m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");"; 304 return httpRequest.Query["callback"].ToString() + "(" + StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");";
617 } 305 }
618 else 306 else
619 { 307 {
620 return m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version); 308 return StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version);
621 }
622 }
623
624 protected void RemovePIDFile()
625 {
626 if (m_pidFile != String.Empty)
627 {
628 try
629 {
630 File.Delete(m_pidFile);
631 m_pidFile = String.Empty;
632 }
633 catch (Exception)
634 {
635 }
636 } 309 }
637 } 310 }
638 } 311 }
639} 312} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 788a0b9..77fce9e 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -54,8 +54,23 @@ namespace OpenSim.Framework.Servers.HttpServer
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); 55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
56 56
57 /// <summary>
58 /// Gets or sets the debug level.
59 /// </summary>
60 /// <value>
61 /// See MainServer.DebugLevel.
62 /// </value>
57 public int DebugLevel { get; set; } 63 public int DebugLevel { get; set; }
58 64
65 /// <summary>
66 /// Request number for diagnostic purposes.
67 /// </summary>
68 /// <remarks>
69 /// This is an internal number. In some debug situations an external number may also be supplied in the
70 /// opensim-request-id header but we are not currently logging this.
71 /// </remarks>
72 public int RequestNumber { get; private set; }
73
59 private volatile int NotSocketErrors = 0; 74 private volatile int NotSocketErrors = 0;
60 public volatile bool HTTPDRunning = false; 75 public volatile bool HTTPDRunning = false;
61 76
@@ -67,7 +82,7 @@ namespace OpenSim.Framework.Servers.HttpServer
67 protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>(); 82 protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>();
68 protected Dictionary<string, IRequestHandler> m_streamHandlers = new Dictionary<string, IRequestHandler>(); 83 protected Dictionary<string, IRequestHandler> m_streamHandlers = new Dictionary<string, IRequestHandler>();
69 protected Dictionary<string, GenericHTTPMethod> m_HTTPHandlers = new Dictionary<string, GenericHTTPMethod>(); 84 protected Dictionary<string, GenericHTTPMethod> m_HTTPHandlers = new Dictionary<string, GenericHTTPMethod>();
70 protected Dictionary<string, IHttpAgentHandler> m_agentHandlers = new Dictionary<string, IHttpAgentHandler>(); 85// protected Dictionary<string, IHttpAgentHandler> m_agentHandlers = new Dictionary<string, IHttpAgentHandler>();
71 protected Dictionary<string, PollServiceEventArgs> m_pollHandlers = 86 protected Dictionary<string, PollServiceEventArgs> m_pollHandlers =
72 new Dictionary<string, PollServiceEventArgs>(); 87 new Dictionary<string, PollServiceEventArgs>();
73 88
@@ -245,29 +260,29 @@ namespace OpenSim.Framework.Servers.HttpServer
245 return new List<string>(m_pollHandlers.Keys); 260 return new List<string>(m_pollHandlers.Keys);
246 } 261 }
247 262
248 // Note that the agent string is provided simply to differentiate 263// // Note that the agent string is provided simply to differentiate
249 // the handlers - it is NOT required to be an actual agent header 264// // the handlers - it is NOT required to be an actual agent header
250 // value. 265// // value.
251 public bool AddAgentHandler(string agent, IHttpAgentHandler handler) 266// public bool AddAgentHandler(string agent, IHttpAgentHandler handler)
252 { 267// {
253 lock (m_agentHandlers) 268// lock (m_agentHandlers)
254 { 269// {
255 if (!m_agentHandlers.ContainsKey(agent)) 270// if (!m_agentHandlers.ContainsKey(agent))
256 { 271// {
257 m_agentHandlers.Add(agent, handler); 272// m_agentHandlers.Add(agent, handler);
258 return true; 273// return true;
259 } 274// }
260 } 275// }
261 276//
262 //must already have a handler for that path so return false 277// //must already have a handler for that path so return false
263 return false; 278// return false;
264 } 279// }
265 280//
266 public List<string> GetAgentHandlerKeys() 281// public List<string> GetAgentHandlerKeys()
267 { 282// {
268 lock (m_agentHandlers) 283// lock (m_agentHandlers)
269 return new List<string>(m_agentHandlers.Keys); 284// return new List<string>(m_agentHandlers.Keys);
270 } 285// }
271 286
272 public bool AddLLSDHandler(string path, LLSDMethod handler) 287 public bool AddLLSDHandler(string path, LLSDMethod handler)
273 { 288 {
@@ -296,6 +311,8 @@ namespace OpenSim.Framework.Servers.HttpServer
296 311
297 private void OnRequest(object source, RequestEventArgs args) 312 private void OnRequest(object source, RequestEventArgs args)
298 { 313 {
314 RequestNumber++;
315
299 try 316 try
300 { 317 {
301 IHttpClientContext context = (IHttpClientContext)source; 318 IHttpClientContext context = (IHttpClientContext)source;
@@ -406,7 +423,6 @@ namespace OpenSim.Framework.Servers.HttpServer
406 string requestMethod = request.HttpMethod; 423 string requestMethod = request.HttpMethod;
407 string uriString = request.RawUrl; 424 string uriString = request.RawUrl;
408 425
409// string reqnum = "unknown";
410 int requestStartTick = Environment.TickCount; 426 int requestStartTick = Environment.TickCount;
411 427
412 // Will be adjusted later on. 428 // Will be adjusted later on.
@@ -423,22 +439,22 @@ namespace OpenSim.Framework.Servers.HttpServer
423 439
424 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); 440 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true);
425 441
426 // This is the REST agent interface. We require an agent to properly identify 442// // This is the REST agent interface. We require an agent to properly identify
427 // itself. If the REST handler recognizes the prefix it will attempt to 443// // itself. If the REST handler recognizes the prefix it will attempt to
428 // satisfy the request. If it is not recognizable, and no damage has occurred 444// // satisfy the request. If it is not recognizable, and no damage has occurred
429 // the request can be passed through to the other handlers. This is a low 445// // the request can be passed through to the other handlers. This is a low
430 // probability event; if a request is matched it is normally expected to be 446// // probability event; if a request is matched it is normally expected to be
431 // handled 447// // handled
432 IHttpAgentHandler agentHandler; 448// IHttpAgentHandler agentHandler;
433 449//
434 if (TryGetAgentHandler(request, response, out agentHandler)) 450// if (TryGetAgentHandler(request, response, out agentHandler))
435 { 451// {
436 if (HandleAgentRequest(agentHandler, request, response)) 452// if (HandleAgentRequest(agentHandler, request, response))
437 { 453// {
438 requestEndTick = Environment.TickCount; 454// requestEndTick = Environment.TickCount;
439 return; 455// return;
440 } 456// }
441 } 457// }
442 458
443 //response.KeepAlive = true; 459 //response.KeepAlive = true;
444 response.SendChunked = false; 460 response.SendChunked = false;
@@ -450,9 +466,7 @@ namespace OpenSim.Framework.Servers.HttpServer
450 if (TryGetStreamHandler(handlerKey, out requestHandler)) 466 if (TryGetStreamHandler(handlerKey, out requestHandler))
451 { 467 {
452 if (DebugLevel >= 3) 468 if (DebugLevel >= 3)
453 m_log.DebugFormat( 469 LogIncomingToStreamHandler(request, requestHandler);
454 "[BASE HTTP SERVER]: Found stream handler for {0} {1} {2} {3}",
455 request.HttpMethod, request.Url.PathAndQuery, requestHandler.Name, requestHandler.Description);
456 470
457 response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. 471 response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
458 472
@@ -529,11 +543,8 @@ namespace OpenSim.Framework.Servers.HttpServer
529 { 543 {
530 case null: 544 case null:
531 case "text/html": 545 case "text/html":
532
533 if (DebugLevel >= 3) 546 if (DebugLevel >= 3)
534 m_log.DebugFormat( 547 LogIncomingToContentTypeHandler(request);
535 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
536 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
537 548
538 buffer = HandleHTTPRequest(request, response); 549 buffer = HandleHTTPRequest(request, response);
539 break; 550 break;
@@ -541,11 +552,8 @@ namespace OpenSim.Framework.Servers.HttpServer
541 case "application/llsd+xml": 552 case "application/llsd+xml":
542 case "application/xml+llsd": 553 case "application/xml+llsd":
543 case "application/llsd+json": 554 case "application/llsd+json":
544
545 if (DebugLevel >= 3) 555 if (DebugLevel >= 3)
546 m_log.DebugFormat( 556 LogIncomingToContentTypeHandler(request);
547 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
548 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
549 557
550 buffer = HandleLLSDRequests(request, response); 558 buffer = HandleLLSDRequests(request, response);
551 break; 559 break;
@@ -564,9 +572,7 @@ namespace OpenSim.Framework.Servers.HttpServer
564 if (DoWeHaveALLSDHandler(request.RawUrl)) 572 if (DoWeHaveALLSDHandler(request.RawUrl))
565 { 573 {
566 if (DebugLevel >= 3) 574 if (DebugLevel >= 3)
567 m_log.DebugFormat( 575 LogIncomingToContentTypeHandler(request);
568 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
569 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
570 576
571 buffer = HandleLLSDRequests(request, response); 577 buffer = HandleLLSDRequests(request, response);
572 } 578 }
@@ -574,18 +580,14 @@ namespace OpenSim.Framework.Servers.HttpServer
574 else if (DoWeHaveAHTTPHandler(request.RawUrl)) 580 else if (DoWeHaveAHTTPHandler(request.RawUrl))
575 { 581 {
576 if (DebugLevel >= 3) 582 if (DebugLevel >= 3)
577 m_log.DebugFormat( 583 LogIncomingToContentTypeHandler(request);
578 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
579 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
580 584
581 buffer = HandleHTTPRequest(request, response); 585 buffer = HandleHTTPRequest(request, response);
582 } 586 }
583 else 587 else
584 { 588 {
585 if (DebugLevel >= 3) 589 if (DebugLevel >= 3)
586 m_log.DebugFormat( 590 LogIncomingToXmlRpcHandler(request);
587 "[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
588 request.HttpMethod, request.Url.PathAndQuery);
589 591
590 // generic login request. 592 // generic login request.
591 buffer = HandleXmlRpcRequests(request, response); 593 buffer = HandleXmlRpcRequests(request, response);
@@ -629,11 +631,11 @@ namespace OpenSim.Framework.Servers.HttpServer
629 } 631 }
630 catch (IOException e) 632 catch (IOException e)
631 { 633 {
632 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e); 634 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e);
633 } 635 }
634 catch (Exception e) 636 catch (Exception e)
635 { 637 {
636 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e); 638 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e);
637 SendHTML500(response); 639 SendHTML500(response);
638 } 640 }
639 finally 641 finally
@@ -644,17 +646,96 @@ namespace OpenSim.Framework.Servers.HttpServer
644 if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture")) 646 if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture"))
645 { 647 {
646 m_log.InfoFormat( 648 m_log.InfoFormat(
647 "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} from {4} took {5}ms", 649 "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms",
650 RequestNumber,
648 requestMethod, 651 requestMethod,
649 uriString, 652 uriString,
650 requestHandler != null ? requestHandler.Name : "", 653 requestHandler != null ? requestHandler.Name : "",
651 requestHandler != null ? requestHandler.Description : "", 654 requestHandler != null ? requestHandler.Description : "",
652 request.RemoteIPEndPoint.ToString(), 655 request.RemoteIPEndPoint,
656 tickdiff);
657 }
658 else if (DebugLevel >= 4)
659 {
660 m_log.DebugFormat(
661 "[BASE HTTP SERVER]: HTTP IN {0} :{1} took {2}ms",
662 RequestNumber,
663 Port,
653 tickdiff); 664 tickdiff);
654 } 665 }
655 } 666 }
656 } 667 }
657 668
669 private void LogIncomingToStreamHandler(OSHttpRequest request, IRequestHandler requestHandler)
670 {
671 m_log.DebugFormat(
672 "[BASE HTTP SERVER]: HTTP IN {0} :{1} stream handler {2} {3} {4} {5} from {6}",
673 RequestNumber,
674 Port,
675 request.HttpMethod,
676 request.Url.PathAndQuery,
677 requestHandler.Name,
678 requestHandler.Description,
679 request.RemoteIPEndPoint);
680
681 if (DebugLevel >= 5)
682 LogIncomingInDetail(request);
683 }
684
685 private void LogIncomingToContentTypeHandler(OSHttpRequest request)
686 {
687 m_log.DebugFormat(
688 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
689 RequestNumber,
690 Port,
691 (request.ContentType == null || request.ContentType == "") ? "not set" : request.ContentType,
692 request.HttpMethod,
693 request.Url.PathAndQuery,
694 request.RemoteIPEndPoint);
695
696 if (DebugLevel >= 5)
697 LogIncomingInDetail(request);
698 }
699
700 private void LogIncomingToXmlRpcHandler(OSHttpRequest request)
701 {
702 m_log.DebugFormat(
703 "[BASE HTTP SERVER]: HTTP IN {0} :{1} assumed generic XMLRPC request {2} {3} from {4}",
704 RequestNumber,
705 Port,
706 request.HttpMethod,
707 request.Url.PathAndQuery,
708 request.RemoteIPEndPoint);
709
710 if (DebugLevel >= 5)
711 LogIncomingInDetail(request);
712 }
713
714 private void LogIncomingInDetail(OSHttpRequest request)
715 {
716 using (StreamReader reader = new StreamReader(Util.Copy(request.InputStream), Encoding.UTF8))
717 {
718 string output;
719
720 if (DebugLevel == 5)
721 {
722 const int sampleLength = 80;
723 char[] sampleChars = new char[sampleLength + 3];
724 reader.Read(sampleChars, 0, sampleLength);
725 sampleChars[80] = '.';
726 sampleChars[81] = '.';
727 sampleChars[82] = '.';
728 output = new string(sampleChars);
729 }
730 else
731 {
732 output = reader.ReadToEnd();
733 }
734
735 m_log.DebugFormat("[BASE HTTP SERVER]: {0}", output.Replace("\n", @"\n"));
736 }
737 }
738
658 private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler) 739 private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler)
659 { 740 {
660 string bestMatch = null; 741 string bestMatch = null;
@@ -747,24 +828,24 @@ namespace OpenSim.Framework.Servers.HttpServer
747 } 828 }
748 } 829 }
749 830
750 private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler) 831// private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler)
751 { 832// {
752 agentHandler = null; 833// agentHandler = null;
753 834//
754 lock (m_agentHandlers) 835// lock (m_agentHandlers)
755 { 836// {
756 foreach (IHttpAgentHandler handler in m_agentHandlers.Values) 837// foreach (IHttpAgentHandler handler in m_agentHandlers.Values)
757 { 838// {
758 if (handler.Match(request, response)) 839// if (handler.Match(request, response))
759 { 840// {
760 agentHandler = handler; 841// agentHandler = handler;
761 return true; 842// return true;
762 } 843// }
763 } 844// }
764 } 845// }
765 846//
766 return false; 847// return false;
767 } 848// }
768 849
769 /// <summary> 850 /// <summary>
770 /// Try all the registered xmlrpc handlers when an xmlrpc request is received. 851 /// Try all the registered xmlrpc handlers when an xmlrpc request is received.
@@ -1737,21 +1818,21 @@ namespace OpenSim.Framework.Servers.HttpServer
1737 m_pollHandlers.Remove(path); 1818 m_pollHandlers.Remove(path);
1738 } 1819 }
1739 1820
1740 public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler) 1821// public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler)
1741 { 1822// {
1742 lock (m_agentHandlers) 1823// lock (m_agentHandlers)
1743 { 1824// {
1744 IHttpAgentHandler foundHandler; 1825// IHttpAgentHandler foundHandler;
1745 1826//
1746 if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler) 1827// if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler)
1747 { 1828// {
1748 m_agentHandlers.Remove(agent); 1829// m_agentHandlers.Remove(agent);
1749 return true; 1830// return true;
1750 } 1831// }
1751 } 1832// }
1752 1833//
1753 return false; 1834// return false;
1754 } 1835// }
1755 1836
1756 public void RemoveXmlRPCHandler(string method) 1837 public void RemoveXmlRPCHandler(string method)
1757 { 1838 {
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
index db58f6f..0bd3aae 100644
--- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
@@ -41,10 +41,10 @@ namespace OpenSim.Framework.Servers.HttpServer
41 uint Port { get; } 41 uint Port { get; }
42 bool UseSSL { get; } 42 bool UseSSL { get; }
43 43
44 // Note that the agent string is provided simply to differentiate 44// // Note that the agent string is provided simply to differentiate
45 // the handlers - it is NOT required to be an actual agent header 45// // the handlers - it is NOT required to be an actual agent header
46 // value. 46// // value.
47 bool AddAgentHandler(string agent, IHttpAgentHandler handler); 47// bool AddAgentHandler(string agent, IHttpAgentHandler handler);
48 48
49 /// <summary> 49 /// <summary>
50 /// Add a handler for an HTTP request. 50 /// Add a handler for an HTTP request.
@@ -106,13 +106,13 @@ namespace OpenSim.Framework.Servers.HttpServer
106 106
107 bool SetDefaultLLSDHandler(DefaultLLSDMethod handler); 107 bool SetDefaultLLSDHandler(DefaultLLSDMethod handler);
108 108
109 /// <summary> 109// /// <summary>
110 /// Remove the agent if it is registered. 110// /// Remove the agent if it is registered.
111 /// </summary> 111// /// </summary>
112 /// <param name="agent"></param> 112// /// <param name="agent"></param>
113 /// <param name="handler"></param> 113// /// <param name="handler"></param>
114 /// <returns></returns> 114// /// <returns></returns>
115 bool RemoveAgentHandler(string agent, IHttpAgentHandler handler); 115// bool RemoveAgentHandler(string agent, IHttpAgentHandler handler);
116 116
117 /// <summary> 117 /// <summary>
118 /// Remove an HTTP handler 118 /// Remove an HTTP handler
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
index d0a37d0..c19ac32 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
@@ -53,7 +53,8 @@ namespace OpenSim.Framework.Servers.HttpServer
53 Normal = 0, 53 Normal = 0,
54 LslHttp = 1, 54 LslHttp = 1,
55 Inventory = 2, 55 Inventory = 2,
56 Texture = 3 56 Texture = 3,
57 Mesh = 4
57 } 58 }
58 59
59 public PollServiceEventArgs( 60 public PollServiceEventArgs(
diff --git a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..02ecc25
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Framework.Servers.HttpServer")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("c4ea5baa-81c4-4867-a645-1ec360c1f164")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Servers/MainServer.cs b/OpenSim/Framework/Servers/MainServer.cs
index 8dc0e3a..ae7d515 100644
--- a/OpenSim/Framework/Servers/MainServer.cs
+++ b/OpenSim/Framework/Servers/MainServer.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Net; 31using System.Net;
32using System.Text;
32using log4net; 33using log4net;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Console; 35using OpenSim.Framework.Console;
@@ -47,9 +48,12 @@ namespace OpenSim.Framework.Servers
47 /// Control the printing of certain debug messages. 48 /// Control the printing of certain debug messages.
48 /// </summary> 49 /// </summary>
49 /// <remarks> 50 /// <remarks>
50 /// If DebugLevel >= 1, then short warnings are logged when receiving bad input data. 51 /// If DebugLevel >= 1 then short warnings are logged when receiving bad input data.
51 /// If DebugLevel >= 2, then long warnings are logged when receiving bad input data. 52 /// If DebugLevel >= 2 then long warnings are logged when receiving bad input data.
52 /// If DebugLevel >= 3, then short notices about all incoming non-poll HTTP requests are logged. 53 /// If DebugLevel >= 3 then short notices about all incoming non-poll HTTP requests are logged.
54 /// If DebugLevel >= 4 then the time taken to fulfill the request is logged.
55 /// If DebugLevel >= 5 then the start of the body of incoming non-poll HTTP requests will be logged.
56 /// If DebugLevel >= 6 then the entire body of incoming non-poll HTTP requests will be logged.
53 /// </remarks> 57 /// </remarks>
54 public static int DebugLevel 58 public static int DebugLevel
55 { 59 {
@@ -101,17 +105,28 @@ namespace OpenSim.Framework.Servers
101 get { return new Dictionary<uint, BaseHttpServer>(m_Servers); } 105 get { return new Dictionary<uint, BaseHttpServer>(m_Servers); }
102 } 106 }
103 107
104
105 public static void RegisterHttpConsoleCommands(ICommandConsole console) 108 public static void RegisterHttpConsoleCommands(ICommandConsole console)
106 { 109 {
107 console.Commands.AddCommand( 110 console.Commands.AddCommand(
108 "Debug", false, "debug http", "debug http [<level>]", 111 "Comms", false, "show http-handlers",
109 "Turn on inbound non-poll http request debugging.", 112 "show http-handlers",
110 "If level <= 0, then no extra logging is done.\n" 113 "Show all registered http handlers", HandleShowHttpHandlersCommand);
111 + "If level >= 1, then short warnings are logged when receiving bad input data.\n" 114
112 + "If level >= 2, then long warnings are logged when receiving bad input data.\n" 115 console.Commands.AddCommand(
113 + "If level >= 3, then short notices about all incoming non-poll HTTP requests are logged.\n" 116 "Debug", false, "debug http", "debug http <in|out|all> [<level>]",
114 + "If no level is specified then the current level is returned.", 117 "Turn on http request logging.",
118 "If in or all and\n"
119 + " level <= 0 then no extra logging is done.\n"
120 + " level >= 1 then short warnings are logged when receiving bad input data.\n"
121 + " level >= 2 then long warnings are logged when receiving bad input data.\n"
122 + " level >= 3 then short notices about all incoming non-poll HTTP requests are logged.\n"
123 + " level >= 4 then the time taken to fulfill the request is logged.\n"
124 + " level >= 5 then a sample from the beginning of the incoming data is logged.\n"
125 + " level >= 6 then the entire incoming data is logged.\n"
126 + " no level is specified then the current level is returned.\n\n"
127 + "If out or all and\n"
128 + " level >= 3 then short notices about all outgoing requests going through WebUtil are logged.\n"
129 + " level >= 4 then the time taken to fulfill the request is logged.\n",
115 HandleDebugHttpCommand); 130 HandleDebugHttpCommand);
116 } 131 }
117 132
@@ -119,25 +134,120 @@ namespace OpenSim.Framework.Servers
119 /// Turn on some debugging values for OpenSim. 134 /// Turn on some debugging values for OpenSim.
120 /// </summary> 135 /// </summary>
121 /// <param name="args"></param> 136 /// <param name="args"></param>
122 private static void HandleDebugHttpCommand(string module, string[] args) 137 private static void HandleDebugHttpCommand(string module, string[] cmdparams)
123 { 138 {
124 if (args.Length == 3) 139 if (cmdparams.Length < 3)
140 {
141 MainConsole.Instance.Output("Usage: debug http <in|out|all> 0..6");
142 return;
143 }
144
145 bool inReqs = false;
146 bool outReqs = false;
147 bool allReqs = false;
148
149 string subCommand = cmdparams[2];
150
151 if (subCommand.ToLower() == "in")
152 {
153 inReqs = true;
154 }
155 else if (subCommand.ToLower() == "out")
156 {
157 outReqs = true;
158 }
159 else if (subCommand.ToLower() == "all")
160 {
161 allReqs = true;
162 }
163 else
125 { 164 {
165 MainConsole.Instance.Output("You must specify in, out or all");
166 return;
167 }
168
169 if (cmdparams.Length >= 4)
170 {
171 string rawNewDebug = cmdparams[3];
126 int newDebug; 172 int newDebug;
127 if (int.TryParse(args[2], out newDebug)) 173
174 if (!int.TryParse(rawNewDebug, out newDebug))
175 {
176 MainConsole.Instance.OutputFormat("{0} is not a valid debug level", rawNewDebug);
177 return;
178 }
179
180 if (newDebug < 0 || newDebug > 6)
181 {
182 MainConsole.Instance.OutputFormat("{0} is outside the valid debug level range of 0..6", newDebug);
183 return;
184 }
185
186 if (allReqs || inReqs)
128 { 187 {
129 MainServer.DebugLevel = newDebug; 188 MainServer.DebugLevel = newDebug;
130 MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug); 189 MainConsole.Instance.OutputFormat("IN debug level set to {0}", newDebug);
190 }
191
192 if (allReqs || outReqs)
193 {
194 WebUtil.DebugLevel = newDebug;
195 MainConsole.Instance.OutputFormat("OUT debug level set to {0}", newDebug);
131 } 196 }
132 } 197 }
133 else if (args.Length == 2) 198 else
134 { 199 {
135 MainConsole.Instance.OutputFormat("Current debug http level is {0}", MainServer.DebugLevel); 200 if (allReqs || inReqs)
201 MainConsole.Instance.OutputFormat("Current IN debug level is {0}", MainServer.DebugLevel);
202
203 if (allReqs || outReqs)
204 MainConsole.Instance.OutputFormat("Current OUT debug level is {0}", WebUtil.DebugLevel);
136 } 205 }
137 else 206 }
207
208 private static void HandleShowHttpHandlersCommand(string module, string[] args)
209 {
210 if (args.Length != 2)
211 {
212 MainConsole.Instance.Output("Usage: show http-handlers");
213 return;
214 }
215
216 StringBuilder handlers = new StringBuilder();
217
218 lock (m_Servers)
138 { 219 {
139 MainConsole.Instance.Output("Usage: debug http 0..3"); 220 foreach (BaseHttpServer httpServer in m_Servers.Values)
221 {
222 handlers.AppendFormat(
223 "Registered HTTP Handlers for server at {0}:{1}\n", httpServer.ListenIPAddress, httpServer.Port);
224
225 handlers.AppendFormat("* XMLRPC:\n");
226 foreach (String s in httpServer.GetXmlRpcHandlerKeys())
227 handlers.AppendFormat("\t{0}\n", s);
228
229 handlers.AppendFormat("* HTTP:\n");
230 List<String> poll = httpServer.GetPollServiceHandlerKeys();
231 foreach (String s in httpServer.GetHTTPHandlerKeys())
232 handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty));
233
234// handlers.AppendFormat("* Agent:\n");
235// foreach (String s in httpServer.GetAgentHandlerKeys())
236// handlers.AppendFormat("\t{0}\n", s);
237
238 handlers.AppendFormat("* LLSD:\n");
239 foreach (String s in httpServer.GetLLSDHandlerKeys())
240 handlers.AppendFormat("\t{0}\n", s);
241
242 handlers.AppendFormat("* StreamHandlers ({0}):\n", httpServer.GetStreamHandlerKeys().Count);
243 foreach (String s in httpServer.GetStreamHandlerKeys())
244 handlers.AppendFormat("\t{0}\n", s);
245
246 handlers.Append("\n");
247 }
140 } 248 }
249
250 MainConsole.Instance.Output(handlers.ToString());
141 } 251 }
142 252
143 /// <summary> 253 /// <summary>
diff --git a/OpenSim/Framework/Servers/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..021f63c
--- /dev/null
+++ b/OpenSim/Framework/Servers/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Framework.Servers")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("b48e8b3e-5c5c-4673-b31f-21e13b8e568b")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
new file mode 100644
index 0000000..c182a3a
--- /dev/null
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -0,0 +1,566 @@
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.Text;
33using System.Text.RegularExpressions;
34using log4net;
35using log4net.Appender;
36using log4net.Core;
37using log4net.Repository;
38using Nini.Config;
39using OpenSim.Framework.Console;
40
41namespace OpenSim.Framework.Servers
42{
43 public class ServerBase
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 public IConfigSource Config { get; protected set; }
48
49 /// <summary>
50 /// Console to be used for any command line output. Can be null, in which case there should be no output.
51 /// </summary>
52 protected ICommandConsole m_console;
53
54 protected OpenSimAppender m_consoleAppender;
55 protected FileAppender m_logFileAppender;
56
57 protected DateTime m_startuptime;
58 protected string m_startupDirectory = Environment.CurrentDirectory;
59
60 protected string m_pidFile = String.Empty;
61
62 /// <summary>
63 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
64 /// </summary>
65 protected string m_version;
66
67 public ServerBase()
68 {
69 m_startuptime = DateTime.Now;
70 m_version = VersionInfo.Version;
71 EnhanceVersionInformation();
72 }
73
74 protected void CreatePIDFile(string path)
75 {
76 try
77 {
78 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
79
80 using (FileStream fs = File.Create(path))
81 {
82 Byte[] buf = Encoding.ASCII.GetBytes(pidstring);
83 fs.Write(buf, 0, buf.Length);
84 }
85
86 m_pidFile = path;
87
88 m_log.InfoFormat("[SERVER BASE]: Created pid file {0}", m_pidFile);
89 }
90 catch (Exception e)
91 {
92 m_log.Warn(string.Format("[SERVER BASE]: Could not create PID file at {0} ", path), e);
93 }
94 }
95
96 protected void RemovePIDFile()
97 {
98 if (m_pidFile != String.Empty)
99 {
100 try
101 {
102 File.Delete(m_pidFile);
103 }
104 catch (Exception e)
105 {
106 m_log.Error(string.Format("[SERVER BASE]: Error whilst removing {0} ", m_pidFile), e);
107 }
108
109 m_pidFile = String.Empty;
110 }
111 }
112
113 public void RegisterCommonAppenders(IConfig startupConfig)
114 {
115 ILoggerRepository repository = LogManager.GetRepository();
116 IAppender[] appenders = repository.GetAppenders();
117
118 foreach (IAppender appender in appenders)
119 {
120 if (appender.Name == "Console")
121 {
122 m_consoleAppender = (OpenSimAppender)appender;
123 }
124 else if (appender.Name == "LogFileAppender")
125 {
126 m_logFileAppender = (FileAppender)appender;
127 }
128 }
129
130 if (null == m_consoleAppender)
131 {
132 Notice("No appender named Console found (see the log4net config file for this executable)!");
133 }
134 else
135 {
136 // FIXME: This should be done through an interface rather than casting.
137 m_consoleAppender.Console = (ConsoleBase)m_console;
138
139 // If there is no threshold set then the threshold is effectively everything.
140 if (null == m_consoleAppender.Threshold)
141 m_consoleAppender.Threshold = Level.All;
142
143 Notice(String.Format("Console log level is {0}", m_consoleAppender.Threshold));
144 }
145
146 if (m_logFileAppender != null && startupConfig != null)
147 {
148 string cfgFileName = startupConfig.GetString("LogFile", null);
149 if (cfgFileName != null)
150 {
151 m_logFileAppender.File = cfgFileName;
152 m_logFileAppender.ActivateOptions();
153 }
154
155 m_log.InfoFormat("[SERVER BASE]: Logging started to file {0}", m_logFileAppender.File);
156 }
157 }
158
159 /// <summary>
160 /// Register common commands once m_console has been set if it is going to be set
161 /// </summary>
162 public void RegisterCommonCommands()
163 {
164 if (m_console == null)
165 return;
166
167 m_console.Commands.AddCommand(
168 "General", false, "show info", "show info", "Show general information about the server", HandleShow);
169
170 m_console.Commands.AddCommand(
171 "General", false, "show uptime", "show uptime", "Show server uptime", HandleShow);
172
173 m_console.Commands.AddCommand(
174 "General", false, "get log level", "get log level", "Get the current console logging level",
175 (mod, cmd) => ShowLogLevel());
176
177 m_console.Commands.AddCommand(
178 "General", false, "set log level", "set log level <level>",
179 "Set the console logging level for this session.", HandleSetLogLevel);
180
181 m_console.Commands.AddCommand(
182 "General", false, "config set",
183 "config set <section> <key> <value>",
184 "Set a config option. In most cases this is not useful since changed parameters are not dynamically reloaded. Neither do changed parameters persist - you will have to change a config file manually and restart.", HandleConfig);
185
186 m_console.Commands.AddCommand(
187 "General", false, "config get",
188 "config get [<section>] [<key>]",
189 "Synonym for config show",
190 HandleConfig);
191
192 m_console.Commands.AddCommand(
193 "General", false, "config show",
194 "config show [<section>] [<key>]",
195 "Show config information",
196 "If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine
197 + "If a section is given but not a field, then all fields in that section are printed.",
198 HandleConfig);
199
200 m_console.Commands.AddCommand(
201 "General", false, "config save",
202 "config save <path>",
203 "Save current configuration to a file at the given path", HandleConfig);
204
205 m_console.Commands.AddCommand(
206 "General", false, "command-script",
207 "command-script <script>",
208 "Run a command script from file", HandleScript);
209 }
210
211 public virtual void HandleShow(string module, string[] cmd)
212 {
213 List<string> args = new List<string>(cmd);
214
215 args.RemoveAt(0);
216
217 string[] showParams = args.ToArray();
218
219 switch (showParams[0])
220 {
221 case "info":
222 ShowInfo();
223 break;
224
225 case "uptime":
226 Notice(GetUptimeReport());
227 break;
228 }
229 }
230
231 /// <summary>
232 /// Change and load configuration file data.
233 /// </summary>
234 /// <param name="module"></param>
235 /// <param name="cmd"></param>
236 private void HandleConfig(string module, string[] cmd)
237 {
238 List<string> args = new List<string>(cmd);
239 args.RemoveAt(0);
240 string[] cmdparams = args.ToArray();
241
242 if (cmdparams.Length > 0)
243 {
244 string firstParam = cmdparams[0].ToLower();
245
246 switch (firstParam)
247 {
248 case "set":
249 if (cmdparams.Length < 4)
250 {
251 Notice("Syntax: config set <section> <key> <value>");
252 Notice("Example: config set ScriptEngine.DotNetEngine NumberOfScriptThreads 5");
253 }
254 else
255 {
256 IConfig c;
257 IConfigSource source = new IniConfigSource();
258 c = source.AddConfig(cmdparams[1]);
259 if (c != null)
260 {
261 string _value = String.Join(" ", cmdparams, 3, cmdparams.Length - 3);
262 c.Set(cmdparams[2], _value);
263 Config.Merge(source);
264
265 Notice("In section [{0}], set {1} = {2}", c.Name, cmdparams[2], _value);
266 }
267 }
268 break;
269
270 case "get":
271 case "show":
272 if (cmdparams.Length == 1)
273 {
274 foreach (IConfig config in Config.Configs)
275 {
276 Notice("[{0}]", config.Name);
277 string[] keys = config.GetKeys();
278 foreach (string key in keys)
279 Notice(" {0} = {1}", key, config.GetString(key));
280 }
281 }
282 else if (cmdparams.Length == 2 || cmdparams.Length == 3)
283 {
284 IConfig config = Config.Configs[cmdparams[1]];
285 if (config == null)
286 {
287 Notice("Section \"{0}\" does not exist.",cmdparams[1]);
288 break;
289 }
290 else
291 {
292 if (cmdparams.Length == 2)
293 {
294 Notice("[{0}]", config.Name);
295 foreach (string key in config.GetKeys())
296 Notice(" {0} = {1}", key, config.GetString(key));
297 }
298 else
299 {
300 Notice(
301 "config get {0} {1} : {2}",
302 cmdparams[1], cmdparams[2], config.GetString(cmdparams[2]));
303 }
304 }
305 }
306 else
307 {
308 Notice("Syntax: config {0} [<section>] [<key>]", firstParam);
309 Notice("Example: config {0} ScriptEngine.DotNetEngine NumberOfScriptThreads", firstParam);
310 }
311
312 break;
313
314 case "save":
315 if (cmdparams.Length < 2)
316 {
317 Notice("Syntax: config save <path>");
318 return;
319 }
320
321 string path = cmdparams[1];
322 Notice("Saving configuration file: {0}", path);
323
324 if (Config is IniConfigSource)
325 {
326 IniConfigSource iniCon = (IniConfigSource)Config;
327 iniCon.Save(path);
328 }
329 else if (Config is XmlConfigSource)
330 {
331 XmlConfigSource xmlCon = (XmlConfigSource)Config;
332 xmlCon.Save(path);
333 }
334
335 break;
336 }
337 }
338 }
339
340 private void HandleSetLogLevel(string module, string[] cmd)
341 {
342 if (cmd.Length != 4)
343 {
344 Notice("Usage: set log level <level>");
345 return;
346 }
347
348 if (null == m_consoleAppender)
349 {
350 Notice("No appender named Console found (see the log4net config file for this executable)!");
351 return;
352 }
353
354 string rawLevel = cmd[3];
355
356 ILoggerRepository repository = LogManager.GetRepository();
357 Level consoleLevel = repository.LevelMap[rawLevel];
358
359 if (consoleLevel != null)
360 m_consoleAppender.Threshold = consoleLevel;
361 else
362 Notice(
363 "{0} is not a valid logging level. Valid logging levels are ALL, DEBUG, INFO, WARN, ERROR, FATAL, OFF",
364 rawLevel);
365
366 ShowLogLevel();
367 }
368
369 private void ShowLogLevel()
370 {
371 Notice("Console log level is {0}", m_consoleAppender.Threshold);
372 }
373
374 protected virtual void HandleScript(string module, string[] parms)
375 {
376 if (parms.Length != 2)
377 {
378 Notice("Usage: command-script <path-to-script");
379 return;
380 }
381
382 RunCommandScript(parms[1]);
383 }
384
385 /// <summary>
386 /// Run an optional startup list of commands
387 /// </summary>
388 /// <param name="fileName"></param>
389 protected void RunCommandScript(string fileName)
390 {
391 if (m_console == null)
392 return;
393
394 if (File.Exists(fileName))
395 {
396 m_log.Info("[SERVER BASE]: Running " + fileName);
397
398 using (StreamReader readFile = File.OpenText(fileName))
399 {
400 string currentCommand;
401 while ((currentCommand = readFile.ReadLine()) != null)
402 {
403 currentCommand = currentCommand.Trim();
404 if (!(currentCommand == ""
405 || currentCommand.StartsWith(";")
406 || currentCommand.StartsWith("//")
407 || currentCommand.StartsWith("#")))
408 {
409 m_log.Info("[SERVER BASE]: Running '" + currentCommand + "'");
410 m_console.RunCommand(currentCommand);
411 }
412 }
413 }
414 }
415 }
416
417 /// <summary>
418 /// Return a report about the uptime of this server
419 /// </summary>
420 /// <returns></returns>
421 protected string GetUptimeReport()
422 {
423 StringBuilder sb = new StringBuilder(String.Format("Time now is {0}\n", DateTime.Now));
424 sb.Append(String.Format("Server has been running since {0}, {1}\n", m_startuptime.DayOfWeek, m_startuptime));
425 sb.Append(String.Format("That is an elapsed time of {0}\n", DateTime.Now - m_startuptime));
426
427 return sb.ToString();
428 }
429
430 protected void ShowInfo()
431 {
432 Notice(GetVersionText());
433 Notice("Startup directory: " + m_startupDirectory);
434 if (null != m_consoleAppender)
435 Notice(String.Format("Console log level: {0}", m_consoleAppender.Threshold));
436 }
437
438 /// <summary>
439 /// Enhance the version string with extra information if it's available.
440 /// </summary>
441 protected void EnhanceVersionInformation()
442 {
443 string buildVersion = string.Empty;
444
445 // The subversion information is deprecated and will be removed at a later date
446 // Add subversion revision information if available
447 // Try file "svn_revision" in the current directory first, then the .svn info.
448 // This allows to make the revision available in simulators not running from the source tree.
449 // FIXME: Making an assumption about the directory we're currently in - we do this all over the place
450 // elsewhere as well
451 string gitDir = "../.git/";
452 string gitRefPointerPath = gitDir + "HEAD";
453
454 string svnRevisionFileName = "svn_revision";
455 string svnFileName = ".svn/entries";
456 string manualVersionFileName = ".version";
457 string inputLine;
458 int strcmp;
459
460 if (File.Exists(manualVersionFileName))
461 {
462 using (StreamReader CommitFile = File.OpenText(manualVersionFileName))
463 buildVersion = CommitFile.ReadLine();
464
465 m_version += buildVersion ?? "";
466 }
467 else if (File.Exists(gitRefPointerPath))
468 {
469// m_log.DebugFormat("[SERVER BASE]: Found {0}", gitRefPointerPath);
470
471 string rawPointer = "";
472
473 using (StreamReader pointerFile = File.OpenText(gitRefPointerPath))
474 rawPointer = pointerFile.ReadLine();
475
476// m_log.DebugFormat("[SERVER BASE]: rawPointer [{0}]", rawPointer);
477
478 Match m = Regex.Match(rawPointer, "^ref: (.+)$");
479
480 if (m.Success)
481 {
482// m_log.DebugFormat("[SERVER BASE]: Matched [{0}]", m.Groups[1].Value);
483
484 string gitRef = m.Groups[1].Value;
485 string gitRefPath = gitDir + gitRef;
486 if (File.Exists(gitRefPath))
487 {
488// m_log.DebugFormat("[SERVER BASE]: Found gitRefPath [{0}]", gitRefPath);
489
490 using (StreamReader refFile = File.OpenText(gitRefPath))
491 {
492 string gitHash = refFile.ReadLine();
493 m_version += gitHash.Substring(0, 7);
494 }
495 }
496 }
497 }
498 else
499 {
500 // Remove the else logic when subversion mirror is no longer used
501 if (File.Exists(svnRevisionFileName))
502 {
503 StreamReader RevisionFile = File.OpenText(svnRevisionFileName);
504 buildVersion = RevisionFile.ReadLine();
505 buildVersion.Trim();
506 RevisionFile.Close();
507 }
508
509 if (string.IsNullOrEmpty(buildVersion) && File.Exists(svnFileName))
510 {
511 StreamReader EntriesFile = File.OpenText(svnFileName);
512 inputLine = EntriesFile.ReadLine();
513 while (inputLine != null)
514 {
515 // using the dir svn revision at the top of entries file
516 strcmp = String.Compare(inputLine, "dir");
517 if (strcmp == 0)
518 {
519 buildVersion = EntriesFile.ReadLine();
520 break;
521 }
522 else
523 {
524 inputLine = EntriesFile.ReadLine();
525 }
526 }
527 EntriesFile.Close();
528 }
529
530 m_version += string.IsNullOrEmpty(buildVersion) ? " " : ("." + buildVersion + " ").Substring(0, 6);
531 }
532 }
533
534 protected string GetVersionText()
535 {
536 return String.Format("Version: {0} (interface version {1})", m_version, VersionInfo.MajorInterfaceVersion);
537 }
538
539 /// <summary>
540 /// Console output is only possible if a console has been established.
541 /// That is something that cannot be determined within this class. So
542 /// all attempts to use the console MUST be verified.
543 /// </summary>
544 /// <param name="msg"></param>
545 protected void Notice(string msg)
546 {
547 if (m_console != null)
548 {
549 m_console.Output(msg);
550 }
551 }
552
553 /// <summary>
554 /// Console output is only possible if a console has been established.
555 /// That is something that cannot be determined within this class. So
556 /// all attempts to use the console MUST be verified.
557 /// </summary>
558 /// <param name="format"></param>
559 /// <param name="components"></param>
560 protected void Notice(string format, params object[] components)
561 {
562 if (m_console != null)
563 m_console.OutputFormat(format, components);
564 }
565 }
566} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
index 016a174..bb094ed 100644
--- a/OpenSim/Framework/Servers/VersionInfo.cs
+++ b/OpenSim/Framework/Servers/VersionInfo.cs
@@ -29,7 +29,7 @@ namespace OpenSim
29{ 29{
30 public class VersionInfo 30 public class VersionInfo
31 { 31 {
32 private const string VERSION_NUMBER = "0.7.4CM"; 32 private const string VERSION_NUMBER = "0.7.5CM";
33 private const Flavour VERSION_FLAVOUR = Flavour.Dev; 33 private const Flavour VERSION_FLAVOUR = Flavour.Dev;
34 34
35 public enum Flavour 35 public enum Flavour
diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs
index 4d07746..62ecbd1 100644
--- a/OpenSim/Framework/TaskInventoryDictionary.cs
+++ b/OpenSim/Framework/TaskInventoryDictionary.cs
@@ -39,10 +39,12 @@ using OpenMetaverse;
39namespace OpenSim.Framework 39namespace OpenSim.Framework
40{ 40{
41 /// <summary> 41 /// <summary>
42 /// A dictionary for task inventory. 42 /// A dictionary containing task inventory items. Indexed by item UUID.
43 /// </summary> 43 /// </summary>
44 /// <remarks>
44 /// This class is not thread safe. Callers must synchronize on Dictionary methods or Clone() this object before 45 /// This class is not thread safe. Callers must synchronize on Dictionary methods or Clone() this object before
45 /// iterating over it. 46 /// iterating over it.
47 /// </remarks>
46 public class TaskInventoryDictionary : Dictionary<UUID, TaskInventoryItem>, 48 public class TaskInventoryDictionary : Dictionary<UUID, TaskInventoryItem>,
47 ICloneable, IXmlSerializable 49 ICloneable, IXmlSerializable
48 { 50 {
diff --git a/OpenSim/Framework/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs
index fb818ee..574ee56 100644
--- a/OpenSim/Framework/TaskInventoryItem.cs
+++ b/OpenSim/Framework/TaskInventoryItem.cs
@@ -73,9 +73,6 @@ namespace OpenSim.Framework
73 73
74 private bool _ownerChanged = false; 74 private bool _ownerChanged = false;
75 75
76 // This used ONLY during copy. It can't be relied on at other times!
77 private bool _scriptRunning = true;
78
79 public UUID AssetID { 76 public UUID AssetID {
80 get { 77 get {
81 return _assetID; 78 return _assetID;
@@ -353,14 +350,13 @@ namespace OpenSim.Framework
353 } 350 }
354 } 351 }
355 352
356 public bool ScriptRunning { 353 /// <summary>
357 get { 354 /// This used ONLY during copy. It can't be relied on at other times!
358 return _scriptRunning; 355 /// </summary>
359 } 356 /// <remarks>
360 set { 357 /// For true script running status, use IEntityInventory.TryGetScriptInstanceRunning() for now.
361 _scriptRunning = value; 358 /// </remarks>
362 } 359 public bool ScriptRunning { get; set; }
363 }
364 360
365 // See ICloneable 361 // See ICloneable
366 362
@@ -388,6 +384,7 @@ namespace OpenSim.Framework
388 384
389 public TaskInventoryItem() 385 public TaskInventoryItem()
390 { 386 {
387 ScriptRunning = true;
391 CreationDate = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; 388 CreationDate = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
392 } 389 }
393 } 390 }
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 384f716..e76a37b 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -546,6 +546,19 @@ namespace OpenSim.Framework
546 } 546 }
547 547
548 /// <summary> 548 /// <summary>
549 /// Determines whether a point is inside a bounding box.
550 /// </summary>
551 /// <param name='v'></param>
552 /// <param name='min'></param>
553 /// <param name='max'></param>
554 /// <returns></returns>
555 public static bool IsInsideBox(Vector3 v, Vector3 min, Vector3 max)
556 {
557 return v.X >= min.X & v.Y >= min.Y && v.Z >= min.Z
558 && v.X <= max.X && v.Y <= max.Y && v.Z <= max.Z;
559 }
560
561 /// <summary>
549 /// Are the co-ordinates of the new region visible from the old region? 562 /// Are the co-ordinates of the new region visible from the old region?
550 /// </summary> 563 /// </summary>
551 /// <param name="oldx">Old region x-coord</param> 564 /// <param name="oldx">Old region x-coord</param>
@@ -862,6 +875,12 @@ namespace OpenSim.Framework
862 return Math.Min(Math.Max(x, min), max); 875 return Math.Min(Math.Max(x, min), max);
863 } 876 }
864 877
878 public static Vector3 Clip(Vector3 vec, float min, float max)
879 {
880 return new Vector3(Clip(vec.X, min, max), Clip(vec.Y, min, max),
881 Clip(vec.Z, min, max));
882 }
883
865 /// <summary> 884 /// <summary>
866 /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens. 885 /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens.
867 /// </summary> 886 /// </summary>
@@ -1013,6 +1032,38 @@ namespace OpenSim.Framework
1013 } 1032 }
1014 } 1033 }
1015 1034
1035 /// <summary>
1036 /// Copy data from one stream to another, leaving the read position of both streams at the beginning.
1037 /// </summary>
1038 /// <param name='inputStream'>
1039 /// Input stream. Must be seekable.
1040 /// </param>
1041 /// <exception cref='ArgumentException'>
1042 /// Thrown if the input stream is not seekable.
1043 /// </exception>
1044 public static Stream Copy(Stream inputStream)
1045 {
1046 if (!inputStream.CanSeek)
1047 throw new ArgumentException("Util.Copy(Stream inputStream) must receive an inputStream that can seek");
1048
1049 const int readSize = 256;
1050 byte[] buffer = new byte[readSize];
1051 MemoryStream ms = new MemoryStream();
1052
1053 int count = inputStream.Read(buffer, 0, readSize);
1054
1055 while (count > 0)
1056 {
1057 ms.Write(buffer, 0, count);
1058 count = inputStream.Read(buffer, 0, readSize);
1059 }
1060
1061 ms.Position = 0;
1062 inputStream.Position = 0;
1063
1064 return ms;
1065 }
1066
1016 public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args) 1067 public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args)
1017 { 1068 {
1018 return SendXmlRpcCommand(url, methodName, args); 1069 return SendXmlRpcCommand(url, methodName, args);
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index 30a8c28..b85d93d 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -54,9 +54,17 @@ namespace OpenSim.Framework
54 MethodBase.GetCurrentMethod().DeclaringType); 54 MethodBase.GetCurrentMethod().DeclaringType);
55 55
56 /// <summary> 56 /// <summary>
57 /// Control the printing of certain debug messages.
58 /// </summary>
59 /// <remarks>
60 /// If DebugLevel >= 3 then short notices about outgoing HTTP requests are logged.
61 /// </remarks>
62 public static int DebugLevel { get; set; }
63
64 /// <summary>
57 /// Request number for diagnostic purposes. 65 /// Request number for diagnostic purposes.
58 /// </summary> 66 /// </summary>
59 public static int RequestNumber = 0; 67 public static int RequestNumber { get; internal set; }
60 68
61 /// <summary> 69 /// <summary>
62 /// this is the header field used to communicate the local request id 70 /// this is the header field used to communicate the local request id
@@ -146,7 +154,11 @@ namespace OpenSim.Framework
146 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed) 154 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed)
147 { 155 {
148 int reqnum = RequestNumber++; 156 int reqnum = RequestNumber++;
149 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); 157
158 if (DebugLevel >= 3)
159 m_log.DebugFormat(
160 "[WEB UTIL]: HTTP OUT {0} ServiceOSD {1} {2} (timeout {3}, compressed {4})",
161 reqnum, method, url, timeout, compressed);
150 162
151 string errorMessage = "unknown error"; 163 string errorMessage = "unknown error";
152 int tickstart = Util.EnvironmentTickCount(); 164 int tickstart = Util.EnvironmentTickCount();
@@ -230,7 +242,7 @@ namespace OpenSim.Framework
230 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 242 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
231 if (tickdiff > LongCallTime) 243 if (tickdiff > LongCallTime)
232 m_log.InfoFormat( 244 m_log.InfoFormat(
233 "[OSD REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}", 245 "[WEB UTIL]: Slow ServiceOSD request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
234 reqnum, 246 reqnum,
235 method, 247 method,
236 url, 248 url,
@@ -239,10 +251,14 @@ namespace OpenSim.Framework
239 strBuffer != null 251 strBuffer != null
240 ? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer) 252 ? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer)
241 : ""); 253 : "");
254 else if (DebugLevel >= 4)
255 m_log.DebugFormat(
256 "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
257 reqnum, tickdiff, tickdata);
242 } 258 }
243 259
244 m_log.DebugFormat( 260 m_log.DebugFormat(
245 "[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage); 261 "[WEB UTIL]: ServiceOSD request {0} {1} {2} FAILED: {3}", reqnum, url, method, errorMessage);
246 262
247 return ErrorResponseMap(errorMessage); 263 return ErrorResponseMap(errorMessage);
248 } 264 }
@@ -318,7 +334,11 @@ namespace OpenSim.Framework
318 { 334 {
319 int reqnum = RequestNumber++; 335 int reqnum = RequestNumber++;
320 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown"; 336 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown";
321 // m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method); 337
338 if (DebugLevel >= 3)
339 m_log.DebugFormat(
340 "[WEB UTIL]: HTTP OUT {0} ServiceForm {1} {2} (timeout {3})",
341 reqnum, method, url, timeout);
322 342
323 string errorMessage = "unknown error"; 343 string errorMessage = "unknown error";
324 int tickstart = Util.EnvironmentTickCount(); 344 int tickstart = Util.EnvironmentTickCount();
@@ -381,7 +401,7 @@ namespace OpenSim.Framework
381 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 401 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
382 if (tickdiff > LongCallTime) 402 if (tickdiff > LongCallTime)
383 m_log.InfoFormat( 403 m_log.InfoFormat(
384 "[SERVICE FORM]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}", 404 "[WEB UTIL]: Slow ServiceForm request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
385 reqnum, 405 reqnum,
386 method, 406 method,
387 url, 407 url,
@@ -390,9 +410,13 @@ namespace OpenSim.Framework
390 queryString != null 410 queryString != null
391 ? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString 411 ? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString
392 : ""); 412 : "");
413 else if (DebugLevel >= 4)
414 m_log.DebugFormat(
415 "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
416 reqnum, tickdiff, tickdata);
393 } 417 }
394 418
395 m_log.WarnFormat("[SERVICE FORM]: <{0}> form request to {1} failed: {2}", reqnum, url, errorMessage); 419 m_log.WarnFormat("[WEB UTIL]: ServiceForm request {0} {1} {2} failed: {2}", reqnum, method, url, errorMessage);
396 420
397 return ErrorResponseMap(errorMessage); 421 return ErrorResponseMap(errorMessage);
398 } 422 }
@@ -644,7 +668,6 @@ namespace OpenSim.Framework
644 /// <returns></returns> 668 /// <returns></returns>
645 public static string[] GetPreferredImageTypes(string accept) 669 public static string[] GetPreferredImageTypes(string accept)
646 { 670 {
647
648 if (accept == null || accept == string.Empty) 671 if (accept == null || accept == string.Empty)
649 return new string[0]; 672 return new string[0];
650 673
@@ -703,14 +726,16 @@ namespace OpenSim.Framework
703 int maxConnections) 726 int maxConnections)
704 { 727 {
705 int reqnum = WebUtil.RequestNumber++; 728 int reqnum = WebUtil.RequestNumber++;
706 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); 729
730 if (WebUtil.DebugLevel >= 3)
731 m_log.DebugFormat(
732 "[WEB UTIL]: HTTP OUT {0} AsynchronousRequestObject {1} {2}",
733 reqnum, verb, requestUrl);
707 734
708 int tickstart = Util.EnvironmentTickCount(); 735 int tickstart = Util.EnvironmentTickCount();
709// int tickdata = 0; 736// int tickdata = 0;
710 int tickdiff = 0; 737 int tickdiff = 0;
711 738
712// m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl);
713
714 Type type = typeof(TRequest); 739 Type type = typeof(TRequest);
715 740
716 WebRequest request = WebRequest.Create(requestUrl); 741 WebRequest request = WebRequest.Create(requestUrl);
@@ -868,7 +893,7 @@ namespace OpenSim.Framework
868 } 893 }
869 894
870 m_log.InfoFormat( 895 m_log.InfoFormat(
871 "[ASYNC REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}", 896 "[ASYNC REQUEST]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
872 reqnum, 897 reqnum,
873 verb, 898 verb,
874 requestUrl, 899 requestUrl,
@@ -883,6 +908,12 @@ namespace OpenSim.Framework
883 requestUrl, 908 requestUrl,
884 tickdiff); 909 tickdiff);
885 } 910 }
911 else if (WebUtil.DebugLevel >= 4)
912 {
913 m_log.DebugFormat(
914 "[WEB UTIL]: HTTP OUT {0} took {1}ms",
915 reqnum, tickdiff);
916 }
886 } 917 }
887 } 918 }
888 919
@@ -903,7 +934,11 @@ namespace OpenSim.Framework
903 public static string MakeRequest(string verb, string requestUrl, string obj) 934 public static string MakeRequest(string verb, string requestUrl, string obj)
904 { 935 {
905 int reqnum = WebUtil.RequestNumber++; 936 int reqnum = WebUtil.RequestNumber++;
906 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); 937
938 if (WebUtil.DebugLevel >= 3)
939 m_log.DebugFormat(
940 "[WEB UTIL]: HTTP OUT {0} SynchronousRestForms {1} {2}",
941 reqnum, verb, requestUrl);
907 942
908 int tickstart = Util.EnvironmentTickCount(); 943 int tickstart = Util.EnvironmentTickCount();
909 int tickdata = 0; 944 int tickdata = 0;
@@ -990,7 +1025,7 @@ namespace OpenSim.Framework
990 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 1025 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
991 if (tickdiff > WebUtil.LongCallTime) 1026 if (tickdiff > WebUtil.LongCallTime)
992 m_log.InfoFormat( 1027 m_log.InfoFormat(
993 "[FORMS]: Slow request to <{0}> {1} {2} took {3}ms {4}ms writing {5}", 1028 "[FORMS]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
994 reqnum, 1029 reqnum,
995 verb, 1030 verb,
996 requestUrl, 1031 requestUrl,
@@ -998,6 +1033,10 @@ namespace OpenSim.Framework
998 tickset, 1033 tickset,
999 tickdata, 1034 tickdata,
1000 obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj); 1035 obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
1036 else if (WebUtil.DebugLevel >= 4)
1037 m_log.DebugFormat(
1038 "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
1039 reqnum, tickdiff, tickdata);
1001 1040
1002 return respstring; 1041 return respstring;
1003 } 1042 }
@@ -1032,7 +1071,11 @@ namespace OpenSim.Framework
1032 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout, int maxConnections) 1071 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout, int maxConnections)
1033 { 1072 {
1034 int reqnum = WebUtil.RequestNumber++; 1073 int reqnum = WebUtil.RequestNumber++;
1035 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); 1074
1075 if (WebUtil.DebugLevel >= 3)
1076 m_log.DebugFormat(
1077 "[WEB UTIL]: HTTP OUT {0} SynchronousRestObject {1} {2}",
1078 reqnum, verb, requestUrl);
1036 1079
1037 int tickstart = Util.EnvironmentTickCount(); 1080 int tickstart = Util.EnvironmentTickCount();
1038 int tickdata = 0; 1081 int tickdata = 0;
@@ -1151,7 +1194,7 @@ namespace OpenSim.Framework
1151 } 1194 }
1152 1195
1153 m_log.InfoFormat( 1196 m_log.InfoFormat(
1154 "[SynchronousRestObjectRequester]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}", 1197 "[SynchronousRestObjectRequester]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
1155 reqnum, 1198 reqnum,
1156 verb, 1199 verb,
1157 requestUrl, 1200 requestUrl,
@@ -1159,6 +1202,12 @@ namespace OpenSim.Framework
1159 tickdata, 1202 tickdata,
1160 originalRequest); 1203 originalRequest);
1161 } 1204 }
1205 else if (WebUtil.DebugLevel >= 4)
1206 {
1207 m_log.DebugFormat(
1208 "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
1209 reqnum, tickdiff, tickdata);
1210 }
1162 1211
1163 return deserial; 1212 return deserial;
1164 } 1213 }
diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs
index 8d95c41..fc3999f 100644
--- a/OpenSim/Region/Application/ConfigurationLoader.cs
+++ b/OpenSim/Region/Application/ConfigurationLoader.cs
@@ -188,7 +188,6 @@ namespace OpenSim
188 // Make sure command line options take precedence 188 // Make sure command line options take precedence
189 m_config.Source.Merge(argvSource); 189 m_config.Source.Merge(argvSource);
190 190
191
192 IConfig enVars = m_config.Source.Configs["Environment"]; 191 IConfig enVars = m_config.Source.Configs["Environment"];
193 192
194 if( enVars != null ) 193 if( enVars != null )
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 6255515..08e4023 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -35,6 +35,7 @@ using System.Text;
35using System.Text.RegularExpressions; 35using System.Text.RegularExpressions;
36using System.Timers; 36using System.Timers;
37using log4net; 37using log4net;
38using NDesk.Options;
38using Nini.Config; 39using Nini.Config;
39using OpenMetaverse; 40using OpenMetaverse;
40using OpenSim.Framework; 41using OpenSim.Framework;
@@ -81,8 +82,8 @@ namespace OpenSim
81 { 82 {
82 base.ReadExtraConfigSettings(); 83 base.ReadExtraConfigSettings();
83 84
84 IConfig startupConfig = m_config.Source.Configs["Startup"]; 85 IConfig startupConfig = Config.Configs["Startup"];
85 IConfig networkConfig = m_config.Source.Configs["Network"]; 86 IConfig networkConfig = Config.Configs["Network"];
86 87
87 int stpMaxThreads = 15; 88 int stpMaxThreads = 15;
88 89
@@ -105,22 +106,6 @@ namespace OpenSim
105 m_timeInterval = startupConfig.GetInt("timer_Interval", 1200); 106 m_timeInterval = startupConfig.GetInt("timer_Interval", 1200);
106 } 107 }
107 108
108 if (m_logFileAppender != null)
109 {
110 if (m_logFileAppender is log4net.Appender.FileAppender)
111 {
112 log4net.Appender.FileAppender appender =
113 (log4net.Appender.FileAppender)m_logFileAppender;
114 string fileName = startupConfig.GetString("LogFile", String.Empty);
115 if (fileName != String.Empty)
116 {
117 appender.File = fileName;
118 appender.ActivateOptions();
119 }
120 m_log.InfoFormat("[LOGGING]: Logging started to file {0}", appender.File);
121 }
122 }
123
124 string asyncCallMethodStr = startupConfig.GetString("async_call_method", String.Empty); 109 string asyncCallMethodStr = startupConfig.GetString("async_call_method", String.Empty);
125 FireAndForgetMethod asyncCallMethod; 110 FireAndForgetMethod asyncCallMethod;
126 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod)) 111 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod))
@@ -163,7 +148,7 @@ namespace OpenSim
163 break; 148 break;
164 case "rest": 149 case "rest":
165 m_console = new RemoteConsole("Region"); 150 m_console = new RemoteConsole("Region");
166 ((RemoteConsole)m_console).ReadConfig(m_config.Source); 151 ((RemoteConsole)m_console).ReadConfig(Config);
167 break; 152 break;
168 default: 153 default:
169 m_console = new LocalConsole("Region"); 154 m_console = new LocalConsole("Region");
@@ -173,6 +158,7 @@ namespace OpenSim
173 158
174 MainConsole.Instance = m_console; 159 MainConsole.Instance = m_console;
175 160
161 RegisterCommonAppenders(Config.Configs["Startup"]);
176 RegisterConsoleCommands(); 162 RegisterConsoleCommands();
177 163
178 base.StartupSpecific(); 164 base.StartupSpecific();
@@ -253,8 +239,14 @@ namespace OpenSim
253 m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug); 239 m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
254 240
255 m_console.Commands.AddCommand("Debug", false, "debug scene", 241 m_console.Commands.AddCommand("Debug", false, "debug scene",
256 "debug scene <scripting> <collisions> <physics>", 242 "debug scene active|collisions|physics|scripting|teleport true|false",
257 "Turn on scene debugging", Debug); 243 "Turn on scene debugging.",
244 "If active is false then main scene update and maintenance loops are suspended.\n"
245 + "If collisions is false then collisions with other objects are turned off.\n"
246 + "If physics is false then all physics objects are non-physical.\n"
247 + "If scripting is false then no scripting operations happen.\n"
248 + "If teleport is true then some extra teleport debug information is logged.",
249 Debug);
258 250
259 m_console.Commands.AddCommand("General", false, "change region", 251 m_console.Commands.AddCommand("General", false, "change region",
260 "change region <region name>", 252 "change region <region name>",
@@ -291,7 +283,7 @@ namespace OpenSim
291 283
292 m_console.Commands.AddCommand("Archiving", false, "save oar", 284 m_console.Commands.AddCommand("Archiving", false, "save oar",
293 //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]", 285 //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]",
294 "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [<OAR path>]", 286 "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [--all] [<OAR path>]",
295 "Save a region's data to an OAR archive.", 287 "Save a region's data to an OAR archive.",
296// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine 288// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
297 "-h|--home=<url> adds the url of the profile service to the saved user information.\n" 289 "-h|--home=<url> adds the url of the profile service to the saved user information.\n"
@@ -301,6 +293,7 @@ namespace OpenSim
301 + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n" 293 + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n"
302 + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n" 294 + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n"
303 + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n" 295 + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n"
296 + "--all saves all the regions in the simulator, instead of just the current region.\n"
304 + "The OAR path must be a filesystem path." 297 + "The OAR path must be a filesystem path."
305 + " If this is not given then the oar is saved to region.oar in the current directory.", 298 + " If this is not given then the oar is saved to region.oar in the current directory.",
306 SaveOar); 299 SaveOar);
@@ -310,8 +303,11 @@ namespace OpenSim
310 "Change the scale of a named prim", HandleEditScale); 303 "Change the scale of a named prim", HandleEditScale);
311 304
312 m_console.Commands.AddCommand("Users", false, "kick user", 305 m_console.Commands.AddCommand("Users", false, "kick user",
313 "kick user <first> <last> [message]", 306 "kick user <first> <last> [--force] [message]",
314 "Kick a user off the simulator", KickUserCommand); 307 "Kick a user off the simulator",
308 "The --force option will kick the user without any checks to see whether it's already in the process of closing\n"
309 + "Only use this option if you are sure the avatar is inactive and a normal kick user operation does not removed them",
310 KickUserCommand);
315 311
316 m_console.Commands.AddCommand("Users", false, "show users", 312 m_console.Commands.AddCommand("Users", false, "show users",
317 "show users [full]", 313 "show users [full]",
@@ -328,10 +324,6 @@ namespace OpenSim
328 "show circuits", 324 "show circuits",
329 "Show agent circuit data", HandleShow); 325 "Show agent circuit data", HandleShow);
330 326
331 m_console.Commands.AddCommand("Comms", false, "show http-handlers",
332 "show http-handlers",
333 "Show all registered http handlers", HandleShow);
334
335 m_console.Commands.AddCommand("Comms", false, "show pending-objects", 327 m_console.Commands.AddCommand("Comms", false, "show pending-objects",
336 "show pending-objects", 328 "show pending-objects",
337 "Show # of objects on the pending queues of all scene viewers", HandleShow); 329 "Show # of objects on the pending queues of all scene viewers", HandleShow);
@@ -365,26 +357,6 @@ namespace OpenSim
365 "restart", 357 "restart",
366 "Restart all sims in this instance", RunCommand); 358 "Restart all sims in this instance", RunCommand);
367 359
368 m_console.Commands.AddCommand("General", false, "config set",
369 "config set <section> <key> <value>",
370 "Set a config option. In most cases this is not useful since changed parameters are not dynamically reloaded. Neither do changed parameters persist - you will have to change a config file manually and restart.", HandleConfig);
371
372 m_console.Commands.AddCommand("General", false, "config get",
373 "config get [<section>] [<key>]",
374 "Synonym for config show",
375 HandleConfig);
376
377 m_console.Commands.AddCommand("General", false, "config show",
378 "config show [<section>] [<key>]",
379 "Show config information",
380 "If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine
381 + "If a section is given but not a field, then all fields in that section are printed.",
382 HandleConfig);
383
384 m_console.Commands.AddCommand("General", false, "config save",
385 "config save <path>",
386 "Save current configuration to a file at the given path", HandleConfig);
387
388 m_console.Commands.AddCommand("General", false, "command-script", 360 m_console.Commands.AddCommand("General", false, "command-script",
389 "command-script <script>", 361 "command-script <script>",
390 "Run a command script from file", RunCommand); 362 "Run a command script from file", RunCommand);
@@ -416,6 +388,7 @@ namespace OpenSim
416 { 388 {
417 RunCommandScript(m_shutdownCommandsFile); 389 RunCommandScript(m_shutdownCommandsFile);
418 } 390 }
391
419 base.ShutdownSpecific(); 392 base.ShutdownSpecific();
420 } 393 }
421 394
@@ -453,11 +426,17 @@ namespace OpenSim
453 /// <param name="cmdparams">name of avatar to kick</param> 426 /// <param name="cmdparams">name of avatar to kick</param>
454 private void KickUserCommand(string module, string[] cmdparams) 427 private void KickUserCommand(string module, string[] cmdparams)
455 { 428 {
456 if (cmdparams.Length < 4) 429 bool force = false;
430
431 OptionSet options = new OptionSet().Add("f|force", delegate (string v) { force = v != null; });
432
433 List<string> mainParams = options.Parse(cmdparams);
434
435 if (mainParams.Count < 4)
457 return; 436 return;
458 437
459 string alert = null; 438 string alert = null;
460 if (cmdparams.Length > 4) 439 if (mainParams.Count > 4)
461 alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); 440 alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4));
462 441
463 IList agents = SceneManager.GetCurrentSceneAvatars(); 442 IList agents = SceneManager.GetCurrentSceneAvatars();
@@ -466,8 +445,8 @@ namespace OpenSim
466 { 445 {
467 RegionInfo regionInfo = presence.Scene.RegionInfo; 446 RegionInfo regionInfo = presence.Scene.RegionInfo;
468 447
469 if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) && 448 if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) &&
470 presence.Lastname.ToLower().Contains(cmdparams[3].ToLower())) 449 presence.Lastname.ToLower().Contains(mainParams[3].ToLower()))
471 { 450 {
472 MainConsole.Instance.Output( 451 MainConsole.Instance.Output(
473 String.Format( 452 String.Format(
@@ -480,7 +459,7 @@ namespace OpenSim
480 else 459 else
481 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); 460 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
482 461
483 presence.Scene.IncomingCloseAgent(presence.UUID); 462 presence.Scene.IncomingCloseAgent(presence.UUID, force);
484 } 463 }
485 } 464 }
486 465
@@ -488,35 +467,6 @@ namespace OpenSim
488 } 467 }
489 468
490 /// <summary> 469 /// <summary>
491 /// Run an optional startup list of commands
492 /// </summary>
493 /// <param name="fileName"></param>
494 private void RunCommandScript(string fileName)
495 {
496 if (File.Exists(fileName))
497 {
498 m_log.Info("[COMMANDFILE]: Running " + fileName);
499
500 using (StreamReader readFile = File.OpenText(fileName))
501 {
502 string currentCommand;
503 while ((currentCommand = readFile.ReadLine()) != null)
504 {
505 currentCommand = currentCommand.Trim();
506 if (!(currentCommand == ""
507 || currentCommand.StartsWith(";")
508 || currentCommand.StartsWith("//")
509 || currentCommand.StartsWith("#")))
510 {
511 m_log.Info("[COMMANDFILE]: Running '" + currentCommand + "'");
512 m_console.RunCommand(currentCommand);
513 }
514 }
515 }
516 }
517 }
518
519 /// <summary>
520 /// Opens a file and uses it as input to the console command parser. 470 /// Opens a file and uses it as input to the console command parser.
521 /// </summary> 471 /// </summary>
522 /// <param name="fileName">name of file to use as input to the console</param> 472 /// <param name="fileName">name of file to use as input to the console</param>
@@ -620,111 +570,9 @@ namespace OpenSim
620 bool changed = PopulateRegionEstateInfo(regInfo); 570 bool changed = PopulateRegionEstateInfo(regInfo);
621 IScene scene; 571 IScene scene;
622 CreateRegion(regInfo, true, out scene); 572 CreateRegion(regInfo, true, out scene);
623 if (changed)
624 regInfo.EstateSettings.Save();
625 }
626
627 /// <summary>
628 /// Change and load configuration file data.
629 /// </summary>
630 /// <param name="module"></param>
631 /// <param name="cmd"></param>
632 private void HandleConfig(string module, string[] cmd)
633 {
634 List<string> args = new List<string>(cmd);
635 args.RemoveAt(0);
636 string[] cmdparams = args.ToArray();
637
638 if (cmdparams.Length > 0)
639 {
640 string firstParam = cmdparams[0].ToLower();
641
642 switch (firstParam)
643 {
644 case "set":
645 if (cmdparams.Length < 4)
646 {
647 Notice("Syntax: config set <section> <key> <value>");
648 Notice("Example: config set ScriptEngine.DotNetEngine NumberOfScriptThreads 5");
649 }
650 else
651 {
652 IConfig c;
653 IConfigSource source = new IniConfigSource();
654 c = source.AddConfig(cmdparams[1]);
655 if (c != null)
656 {
657 string _value = String.Join(" ", cmdparams, 3, cmdparams.Length - 3);
658 c.Set(cmdparams[2], _value);
659 m_config.Source.Merge(source);
660 573
661 Notice("In section [{0}], set {1} = {2}", c.Name, cmdparams[2], _value); 574 if (changed)
662 } 575 regInfo.EstateSettings.Save();
663 }
664 break;
665
666 case "get":
667 case "show":
668 if (cmdparams.Length == 1)
669 {
670 foreach (IConfig config in m_config.Source.Configs)
671 {
672 Notice("[{0}]", config.Name);
673 string[] keys = config.GetKeys();
674 foreach (string key in keys)
675 Notice(" {0} = {1}", key, config.GetString(key));
676 }
677 }
678 else if (cmdparams.Length == 2 || cmdparams.Length == 3)
679 {
680 IConfig config = m_config.Source.Configs[cmdparams[1]];
681 if (config == null)
682 {
683 Notice("Section \"{0}\" does not exist.",cmdparams[1]);
684 break;
685 }
686 else
687 {
688 if (cmdparams.Length == 2)
689 {
690 Notice("[{0}]", config.Name);
691 foreach (string key in config.GetKeys())
692 Notice(" {0} = {1}", key, config.GetString(key));
693 }
694 else
695 {
696 Notice(
697 "config get {0} {1} : {2}",
698 cmdparams[1], cmdparams[2], config.GetString(cmdparams[2]));
699 }
700 }
701 }
702 else
703 {
704 Notice("Syntax: config {0} [<section>] [<key>]", firstParam);
705 Notice("Example: config {0} ScriptEngine.DotNetEngine NumberOfScriptThreads", firstParam);
706 }
707
708 break;
709
710 case "save":
711 if (cmdparams.Length < 2)
712 {
713 Notice("Syntax: config save <path>");
714 return;
715 }
716
717 if (Application.iniFilePath == cmdparams[1])
718 {
719 Notice("Path can not be " + Application.iniFilePath);
720 return;
721 }
722
723 Notice("Saving configuration file: " + cmdparams[1]);
724 m_config.Save(cmdparams[1]);
725 break;
726 }
727 }
728 } 576 }
729 577
730 /// <summary> 578 /// <summary>
@@ -743,33 +591,13 @@ namespace OpenSim
743 switch (cmdparams[0].ToLower()) 591 switch (cmdparams[0].ToLower())
744 { 592 {
745 case "list": 593 case "list":
746 foreach (IRegionModule irm in m_moduleLoader.GetLoadedSharedModules) 594 //TODO: Convert to new region modules
747 {
748 MainConsole.Instance.Output(String.Format("Shared region module: {0}", irm.Name));
749 }
750 break; 595 break;
751 case "unload": 596 case "unload":
752 if (cmdparams.Length > 1) 597 //TODO: Convert to new region modules
753 {
754 foreach (IRegionModule rm in new ArrayList(m_moduleLoader.GetLoadedSharedModules))
755 {
756 if (rm.Name.ToLower() == cmdparams[1].ToLower())
757 {
758 MainConsole.Instance.Output(String.Format("Unloading module: {0}", rm.Name));
759 m_moduleLoader.UnloadModule(rm);
760 }
761 }
762 }
763 break; 598 break;
764 case "load": 599 case "load":
765 if (cmdparams.Length > 1) 600 //TODO: Convert to new region modules
766 {
767 foreach (Scene s in new ArrayList(SceneManager.Scenes))
768 {
769 MainConsole.Instance.Output(String.Format("Loading module: {0}", cmdparams[1]));
770 m_moduleLoader.LoadRegionModules(cmdparams[1], s);
771 }
772 }
773 break; 601 break;
774 } 602 }
775 } 603 }
@@ -793,13 +621,6 @@ namespace OpenSim
793 621
794 switch (command) 622 switch (command)
795 { 623 {
796 case "command-script":
797 if (cmdparams.Length > 0)
798 {
799 RunCommandScript(cmdparams[0]);
800 }
801 break;
802
803 case "backup": 624 case "backup":
804 MainConsole.Instance.Output("Triggering save of pending object updates to persistent store"); 625 MainConsole.Instance.Output("Triggering save of pending object updates to persistent store");
805 SceneManager.BackupCurrentScene(); 626 SceneManager.BackupCurrentScene();
@@ -843,12 +664,20 @@ namespace OpenSim
843 664
844 if (!SceneManager.TrySetCurrentScene(newRegionName)) 665 if (!SceneManager.TrySetCurrentScene(newRegionName))
845 MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName)); 666 MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName));
667 else
668 RefreshPrompt();
846 } 669 }
847 else 670 else
848 { 671 {
849 MainConsole.Instance.Output("Usage: change region <region name>"); 672 MainConsole.Instance.Output("Usage: change region <region name>");
850 } 673 }
674 }
851 675
676 /// <summary>
677 /// Refreshs prompt with the current selection details.
678 /// </summary>
679 private void RefreshPrompt()
680 {
852 string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName); 681 string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName);
853 MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName)); 682 MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName));
854 683
@@ -870,6 +699,18 @@ namespace OpenSim
870 m_console.ConsoleScene = SceneManager.CurrentScene; 699 m_console.ConsoleScene = SceneManager.CurrentScene;
871 } 700 }
872 701
702 protected override void HandleRestartRegion(RegionInfo whichRegion)
703 {
704 base.HandleRestartRegion(whichRegion);
705
706 // Where we are restarting multiple scenes at once, a previous call to RefreshPrompt may have set the
707 // m_console.ConsoleScene to null (indicating all scenes).
708 if (m_console.ConsoleScene != null && whichRegion.RegionName == ((Scene)m_console.ConsoleScene).Name)
709 SceneManager.TrySetCurrentScene(whichRegion.RegionName);
710
711 RefreshPrompt();
712 }
713
873 /// <summary> 714 /// <summary>
874 /// Turn on some debugging values for OpenSim. 715 /// Turn on some debugging values for OpenSim.
875 /// </summary> 716 /// </summary>
@@ -922,7 +763,8 @@ namespace OpenSim
922 } 763 }
923 else 764 else
924 { 765 {
925 MainConsole.Instance.Output("Usage: debug scene scripting|collisions|physics|teleport true|false"); 766 MainConsole.Instance.Output(
767 "Usage: debug scene active|scripting|collisions|physics|teleport true|false");
926 } 768 }
927 769
928 break; 770 break;
@@ -1002,56 +844,10 @@ namespace OpenSim
1002 HandleShowCircuits(); 844 HandleShowCircuits();
1003 break; 845 break;
1004 846
1005 case "http-handlers":
1006 System.Text.StringBuilder handlers = new System.Text.StringBuilder("Registered HTTP Handlers:\n");
1007
1008 handlers.AppendFormat("* XMLRPC:\n");
1009 foreach (String s in HttpServer.GetXmlRpcHandlerKeys())
1010 handlers.AppendFormat("\t{0}\n", s);
1011
1012 handlers.AppendFormat("* HTTP:\n");
1013 List<String> poll = HttpServer.GetPollServiceHandlerKeys();
1014 foreach (String s in HttpServer.GetHTTPHandlerKeys())
1015 handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty));
1016
1017 handlers.AppendFormat("* Agent:\n");
1018 foreach (String s in HttpServer.GetAgentHandlerKeys())
1019 handlers.AppendFormat("\t{0}\n", s);
1020
1021 handlers.AppendFormat("* LLSD:\n");
1022 foreach (String s in HttpServer.GetLLSDHandlerKeys())
1023 handlers.AppendFormat("\t{0}\n", s);
1024
1025 handlers.AppendFormat("* StreamHandlers ({0}):\n", HttpServer.GetStreamHandlerKeys().Count);
1026 foreach (String s in HttpServer.GetStreamHandlerKeys())
1027 handlers.AppendFormat("\t{0}\n", s);
1028
1029 MainConsole.Instance.Output(handlers.ToString());
1030 break;
1031
1032 case "modules": 847 case "modules":
1033 MainConsole.Instance.Output("The currently loaded shared modules are:");
1034 foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules)
1035 {
1036 MainConsole.Instance.Output("Shared Module: " + module.Name);
1037 }
1038
1039 SceneManager.ForEachScene(
1040 delegate(Scene scene) {
1041 m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:");
1042 foreach (IRegionModule module in scene.Modules.Values)
1043 {
1044 if (!module.IsSharedModule)
1045 {
1046 m_log.Error("Region Module: " + module.Name);
1047 }
1048 }
1049 }
1050 );
1051
1052 SceneManager.ForEachScene( 848 SceneManager.ForEachScene(
1053 delegate(Scene scene) { 849 delegate(Scene scene) {
1054 MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:"); 850 MainConsole.Instance.Output("Loaded region modules in" + scene.RegionInfo.RegionName + " are:");
1055 foreach (IRegionModuleBase module in scene.RegionModules.Values) 851 foreach (IRegionModuleBase module in scene.RegionModules.Values)
1056 { 852 {
1057 Type type = module.GetType().GetInterface("ISharedRegionModule"); 853 Type type = module.GetType().GetInterface("ISharedRegionModule");
@@ -1123,7 +919,7 @@ namespace OpenSim
1123 aCircuit.Name, 919 aCircuit.Name,
1124 aCircuit.child ? "child" : "root", 920 aCircuit.child ? "child" : "root",
1125 aCircuit.circuitcode.ToString(), 921 aCircuit.circuitcode.ToString(),
1126 aCircuit.IPAddress.ToString(), 922 aCircuit.IPAddress != null ? aCircuit.IPAddress.ToString() : "not set",
1127 aCircuit.Viewer); 923 aCircuit.Viewer);
1128 }); 924 });
1129 925
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index d107b7a..bed9a49 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -104,13 +104,7 @@ namespace OpenSim
104 /// <value> 104 /// <value>
105 /// The config information passed into the OpenSimulator region server. 105 /// The config information passed into the OpenSimulator region server.
106 /// </value> 106 /// </value>
107 public OpenSimConfigSource ConfigSource 107 public OpenSimConfigSource ConfigSource { get; private set; }
108 {
109 get { return m_config; }
110 set { m_config = value; }
111 }
112
113 protected OpenSimConfigSource m_config;
114 108
115 public List<IClientNetworkServer> ClientServers 109 public List<IClientNetworkServer> ClientServers
116 { 110 {
@@ -131,14 +125,6 @@ namespace OpenSim
131 get { return m_httpServerPort; } 125 get { return m_httpServerPort; }
132 } 126 }
133 127
134 public ModuleLoader ModuleLoader
135 {
136 get { return m_moduleLoader; }
137 set { m_moduleLoader = value; }
138 }
139
140 protected ModuleLoader m_moduleLoader;
141
142 protected IRegistryCore m_applicationRegistry = new RegistryCore(); 128 protected IRegistryCore m_applicationRegistry = new RegistryCore();
143 129
144 public IRegistryCore ApplicationRegistry 130 public IRegistryCore ApplicationRegistry
@@ -158,13 +144,14 @@ namespace OpenSim
158 protected virtual void LoadConfigSettings(IConfigSource configSource) 144 protected virtual void LoadConfigSettings(IConfigSource configSource)
159 { 145 {
160 m_configLoader = new ConfigurationLoader(); 146 m_configLoader = new ConfigurationLoader();
161 m_config = m_configLoader.LoadConfigSettings(configSource, envConfigSource, out m_configSettings, out m_networkServersInfo); 147 ConfigSource = m_configLoader.LoadConfigSettings(configSource, envConfigSource, out m_configSettings, out m_networkServersInfo);
148 Config = ConfigSource.Source;
162 ReadExtraConfigSettings(); 149 ReadExtraConfigSettings();
163 } 150 }
164 151
165 protected virtual void ReadExtraConfigSettings() 152 protected virtual void ReadExtraConfigSettings()
166 { 153 {
167 IConfig networkConfig = m_config.Source.Configs["Network"]; 154 IConfig networkConfig = Config.Configs["Network"];
168 if (networkConfig != null) 155 if (networkConfig != null)
169 { 156 {
170 proxyUrl = networkConfig.GetString("proxy_url", ""); 157 proxyUrl = networkConfig.GetString("proxy_url", "");
@@ -197,7 +184,7 @@ namespace OpenSim
197 /// </summary> 184 /// </summary>
198 protected override void StartupSpecific() 185 protected override void StartupSpecific()
199 { 186 {
200 IConfig startupConfig = m_config.Source.Configs["Startup"]; 187 IConfig startupConfig = Config.Configs["Startup"];
201 if (startupConfig != null) 188 if (startupConfig != null)
202 { 189 {
203 string pidFile = startupConfig.GetString("PIDFile", String.Empty); 190 string pidFile = startupConfig.GetString("PIDFile", String.Empty);
@@ -213,29 +200,38 @@ namespace OpenSim
213 } 200 }
214 201
215 // Load the simulation data service 202 // Load the simulation data service
216 IConfig simDataConfig = m_config.Source.Configs["SimulationDataStore"]; 203 IConfig simDataConfig = Config.Configs["SimulationDataStore"];
217 if (simDataConfig == null) 204 if (simDataConfig == null)
218 throw new Exception("Configuration file is missing the [SimulationDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?"); 205 throw new Exception("Configuration file is missing the [SimulationDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?");
206
219 string module = simDataConfig.GetString("LocalServiceModule", String.Empty); 207 string module = simDataConfig.GetString("LocalServiceModule", String.Empty);
220 if (String.IsNullOrEmpty(module)) 208 if (String.IsNullOrEmpty(module))
221 throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [SimulationDataStore] section."); 209 throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [SimulationDataStore] section.");
222 m_simulationDataService = ServerUtils.LoadPlugin<ISimulationDataService>(module, new object[] { m_config.Source }); 210
211 m_simulationDataService = ServerUtils.LoadPlugin<ISimulationDataService>(module, new object[] { Config });
212 if (m_simulationDataService == null)
213 throw new Exception(
214 string.Format(
215 "Could not load an ISimulationDataService implementation from {0}, as configured in the LocalServiceModule parameter of the [SimulationDataStore] config section.",
216 module));
223 217
224 // Load the estate data service 218 // Load the estate data service
225 IConfig estateDataConfig = m_config.Source.Configs["EstateDataStore"]; 219 IConfig estateDataConfig = Config.Configs["EstateDataStore"];
226 if (estateDataConfig == null) 220 if (estateDataConfig == null)
227 throw new Exception("Configuration file is missing the [EstateDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?"); 221 throw new Exception("Configuration file is missing the [EstateDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?");
222
228 module = estateDataConfig.GetString("LocalServiceModule", String.Empty); 223 module = estateDataConfig.GetString("LocalServiceModule", String.Empty);
229 if (String.IsNullOrEmpty(module)) 224 if (String.IsNullOrEmpty(module))
230 throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [EstateDataStore] section"); 225 throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [EstateDataStore] section");
231 m_estateDataService = ServerUtils.LoadPlugin<IEstateDataService>(module, new object[] { m_config.Source });
232 226
233 base.StartupSpecific(); 227 m_estateDataService = ServerUtils.LoadPlugin<IEstateDataService>(module, new object[] { Config });
228 if (m_estateDataService == null)
229 throw new Exception(
230 string.Format(
231 "Could not load an IEstateDataService implementation from {0}, as configured in the LocalServiceModule parameter of the [EstateDataStore] config section.",
232 module));
234 233
235 m_stats = StatsManager.SimExtraStats; 234 base.StartupSpecific();
236
237 // Create a ModuleLoader instance
238 m_moduleLoader = new ModuleLoader(m_config.Source);
239 235
240 LoadPlugins(); 236 LoadPlugins();
241 237
@@ -249,51 +245,51 @@ namespace OpenSim
249 plugin.PostInitialise(); 245 plugin.PostInitialise();
250 } 246 }
251 247
252 AddPluginCommands(); 248 if (m_console != null)
249 {
250 StatsManager.RegisterConsoleCommands(m_console);
251 AddPluginCommands(m_console);
252 }
253 } 253 }
254 254
255 protected virtual void AddPluginCommands() 255 protected virtual void AddPluginCommands(ICommandConsole console)
256 { 256 {
257 // If console exists add plugin commands. 257 List<string> topics = GetHelpTopics();
258 if (m_console != null)
259 {
260 List<string> topics = GetHelpTopics();
261 258
262 foreach (string topic in topics) 259 foreach (string topic in topics)
263 { 260 {
264 string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); 261 string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1);
265 262
266 // This is a hack to allow the user to enter the help command in upper or lowercase. This will go 263 // This is a hack to allow the user to enter the help command in upper or lowercase. This will go
267 // away at some point. 264 // away at some point.
268 m_console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, 265 console.Commands.AddCommand(capitalizedTopic, false, "help " + topic,
269 "help " + capitalizedTopic, 266 "help " + capitalizedTopic,
270 "Get help on plugin command '" + topic + "'", 267 "Get help on plugin command '" + topic + "'",
271 HandleCommanderHelp); 268 HandleCommanderHelp);
272 m_console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, 269// console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic,
273 "help " + capitalizedTopic, 270// "help " + capitalizedTopic,
274 "Get help on plugin command '" + topic + "'", 271// "Get help on plugin command '" + topic + "'",
275 HandleCommanderHelp); 272// HandleCommanderHelp);
276 273
277 ICommander commander = null; 274 ICommander commander = null;
278 275
279 Scene s = SceneManager.CurrentOrFirstScene; 276 Scene s = SceneManager.CurrentOrFirstScene;
280 277
281 if (s != null && s.GetCommanders() != null) 278 if (s != null && s.GetCommanders() != null)
282 { 279 {
283 if (s.GetCommanders().ContainsKey(topic)) 280 if (s.GetCommanders().ContainsKey(topic))
284 commander = s.GetCommanders()[topic]; 281 commander = s.GetCommanders()[topic];
285 } 282 }
286 283
287 if (commander == null) 284 if (commander == null)
288 continue; 285 continue;
289 286
290 foreach (string command in commander.Commands.Keys) 287 foreach (string command in commander.Commands.Keys)
291 { 288 {
292 m_console.Commands.AddCommand(capitalizedTopic, false, 289 console.Commands.AddCommand(capitalizedTopic, false,
293 topic + " " + command, 290 topic + " " + command,
294 topic + " " + commander.Commands[command].ShortHelp(), 291 topic + " " + commander.Commands[command].ShortHelp(),
295 String.Empty, HandleCommanderCommand); 292 String.Empty, HandleCommanderCommand);
296 }
297 } 293 }
298 } 294 }
299 } 295 }
@@ -318,7 +314,7 @@ namespace OpenSim
318 // Called from base.StartUp() 314 // Called from base.StartUp()
319 315
320 m_httpServerPort = m_networkServersInfo.HttpListenerPort; 316 m_httpServerPort = m_networkServersInfo.HttpListenerPort;
321 SceneManager.OnRestartSim += handleRestartRegion; 317 SceneManager.OnRestartSim += HandleRestartRegion;
322 318
323 // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is 319 // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is
324 // heavily used during initial startup. 320 // heavily used during initial startup.
@@ -383,16 +379,10 @@ namespace OpenSim
383 } 379 }
384 380
385 IClientNetworkServer clientServer; 381 IClientNetworkServer clientServer;
386 Scene scene = SetupScene(regionInfo, proxyOffset, m_config.Source, out clientServer); 382 Scene scene = SetupScene(regionInfo, proxyOffset, Config, out clientServer);
387 383
388 m_log.Info("[MODULES]: Loading Region's modules (old style)"); 384 m_log.Info("[MODULES]: Loading Region's modules (old style)");
389 385
390 List<IRegionModule> modules = m_moduleLoader.PickupModules(scene, ".");
391
392 // This needs to be ahead of the script engine load, so the
393 // script module can pick up events exposed by a module
394 m_moduleLoader.InitialiseSharedModules(scene);
395
396 // Use this in the future, the line above will be deprecated soon 386 // Use this in the future, the line above will be deprecated soon
397 m_log.Info("[REGIONMODULES]: Loading Region's modules (new style)"); 387 m_log.Info("[REGIONMODULES]: Loading Region's modules (new style)");
398 IRegionModulesController controller; 388 IRegionModulesController controller;
@@ -402,28 +392,29 @@ namespace OpenSim
402 } 392 }
403 else m_log.Error("[REGIONMODULES]: The new RegionModulesController is missing..."); 393 else m_log.Error("[REGIONMODULES]: The new RegionModulesController is missing...");
404 394
405 if (m_securePermissionsLoading) 395 // XPTO: Fix this
406 { 396// if (m_securePermissionsLoading)
407 foreach (string s in m_permsModules) 397// {
408 { 398// foreach (string s in m_permsModules)
409 if (!scene.RegionModules.ContainsKey(s)) 399// {
410 { 400// if (!scene.RegionModules.ContainsKey(s))
411 bool found = false; 401// {
412 foreach (IRegionModule m in modules) 402// bool found = false;
413 { 403// foreach (IRegionModule m in modules)
414 if (m.Name == s) 404// {
415 { 405// if (m.Name == s)
416 found = true; 406// {
417 } 407// found = true;
418 } 408// }
419 if (!found) 409// }
420 { 410// if (!found)
421 m_log.Fatal("[MODULES]: Required module " + s + " not found."); 411// {
422 Environment.Exit(0); 412// m_log.Fatal("[MODULES]: Required module " + s + " not found.");
423 } 413// Environment.Exit(0);
424 } 414// }
425 } 415// }
426 } 416// }
417// }
427 418
428 scene.SetModuleInterfaces(); 419 scene.SetModuleInterfaces();
429// First Step of bootreport sequence 420// First Step of bootreport sequence
@@ -500,13 +491,6 @@ namespace OpenSim
500 { 491 {
501 scene.SnmpService.BootInfo("Initializing region modules", scene); 492 scene.SnmpService.BootInfo("Initializing region modules", scene);
502 } 493 }
503 if (do_post_init)
504 {
505 foreach (IRegionModule module in modules)
506 {
507 module.PostInitialise();
508 }
509 }
510 scene.EventManager.OnShutdown += delegate() { ShutdownRegion(scene); }; 494 scene.EventManager.OnShutdown += delegate() { ShutdownRegion(scene); };
511 495
512 mscene = scene; 496 mscene = scene;
@@ -541,10 +525,10 @@ namespace OpenSim
541 string estateOwnerPassword = null; 525 string estateOwnerPassword = null;
542 string rawEstateOwnerUuid = null; 526 string rawEstateOwnerUuid = null;
543 527
544 if (m_config.Source.Configs[ESTATE_SECTION_NAME] != null) 528 if (Config.Configs[ESTATE_SECTION_NAME] != null)
545 { 529 {
546 string defaultEstateOwnerName 530 string defaultEstateOwnerName
547 = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerName", "").Trim(); 531 = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerName", "").Trim();
548 string[] ownerNames = defaultEstateOwnerName.Split(' '); 532 string[] ownerNames = defaultEstateOwnerName.Split(' ');
549 533
550 if (ownerNames.Length >= 2) 534 if (ownerNames.Length >= 2)
@@ -554,9 +538,9 @@ namespace OpenSim
554 } 538 }
555 539
556 // Info to be used only on Standalone Mode 540 // Info to be used only on Standalone Mode
557 rawEstateOwnerUuid = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerUUID", null); 541 rawEstateOwnerUuid = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerUUID", null);
558 estateOwnerEMail = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerEMail", null); 542 estateOwnerEMail = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerEMail", null);
559 estateOwnerPassword = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerPassword", null); 543 estateOwnerPassword = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerPassword", null);
560 } 544 }
561 545
562 MainConsole.Instance.OutputFormat("Estate {0} has no owner set.", regionInfo.EstateSettings.EstateName); 546 MainConsole.Instance.OutputFormat("Estate {0} has no owner set.", regionInfo.EstateSettings.EstateName);
@@ -623,7 +607,7 @@ namespace OpenSim
623 if (account == null) 607 if (account == null)
624 { 608 {
625 m_log.ErrorFormat( 609 m_log.ErrorFormat(
626 "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first."); 610 "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first at the grid level.");
627 } 611 }
628 else 612 else
629 { 613 {
@@ -807,8 +791,8 @@ namespace OpenSim
807 791
808 return new Scene( 792 return new Scene(
809 regionInfo, circuitManager, sceneGridService, 793 regionInfo, circuitManager, sceneGridService,
810 simDataService, estateDataService, m_moduleLoader, false, 794 simDataService, estateDataService, false,
811 m_config.Source, m_version); 795 Config, m_version);
812 } 796 }
813 797
814 protected void ShutdownClientServer(RegionInfo whichRegion) 798 protected void ShutdownClientServer(RegionInfo whichRegion)
@@ -835,9 +819,11 @@ namespace OpenSim
835 } 819 }
836 } 820 }
837 821
838 public void handleRestartRegion(RegionInfo whichRegion) 822 protected virtual void HandleRestartRegion(RegionInfo whichRegion)
839 { 823 {
840 m_log.Info("[OPENSIM]: Got restart signal from SceneManager"); 824 m_log.InfoFormat(
825 "[OPENSIM]: Got restart signal from SceneManager for region {0} ({1},{2})",
826 whichRegion.RegionName, whichRegion.RegionLocX, whichRegion.RegionLocY);
841 827
842 ShutdownClientServer(whichRegion); 828 ShutdownClientServer(whichRegion);
843 IScene scene; 829 IScene scene;
@@ -849,7 +835,7 @@ namespace OpenSim
849 protected override PhysicsScene GetPhysicsScene(string osSceneIdentifier) 835 protected override PhysicsScene GetPhysicsScene(string osSceneIdentifier)
850 { 836 {
851 return GetPhysicsScene( 837 return GetPhysicsScene(
852 m_configSettings.PhysicsEngine, m_configSettings.MeshEngineName, m_config.Source, osSceneIdentifier); 838 m_configSettings.PhysicsEngine, m_configSettings.MeshEngineName, Config, osSceneIdentifier);
853 } 839 }
854 840
855 /// <summary> 841 /// <summary>
@@ -983,7 +969,6 @@ namespace OpenSim
983 m_log.Info("[SHUTDOWN]: Closing all threads"); 969 m_log.Info("[SHUTDOWN]: Closing all threads");
984 m_log.Info("[SHUTDOWN]: Killing listener thread"); 970 m_log.Info("[SHUTDOWN]: Killing listener thread");
985 m_log.Info("[SHUTDOWN]: Killing clients"); 971 m_log.Info("[SHUTDOWN]: Killing clients");
986 // TODO: implement this
987 m_log.Info("[SHUTDOWN]: Closing console and terminating"); 972 m_log.Info("[SHUTDOWN]: Closing console and terminating");
988 973
989 try 974 try
@@ -992,7 +977,7 @@ namespace OpenSim
992 } 977 }
993 catch (Exception e) 978 catch (Exception e)
994 { 979 {
995 m_log.ErrorFormat("[SHUTDOWN]: Ignoring failure during shutdown - {0}", e); 980 m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e);
996 } 981 }
997 } 982 }
998 983
@@ -1086,9 +1071,9 @@ namespace OpenSim
1086 1071
1087 string defaultEstateName = null; 1072 string defaultEstateName = null;
1088 1073
1089 if (m_config.Source.Configs[ESTATE_SECTION_NAME] != null) 1074 if (Config.Configs[ESTATE_SECTION_NAME] != null)
1090 { 1075 {
1091 defaultEstateName = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateName", null); 1076 defaultEstateName = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateName", null);
1092 1077
1093 if (defaultEstateName != null) 1078 if (defaultEstateName != null)
1094 { 1079 {
@@ -1171,28 +1156,14 @@ namespace OpenSim
1171 MainConsole.Instance.Output("Joining the estate failed. Please try again."); 1156 MainConsole.Instance.Output("Joining the estate failed. Please try again.");
1172 } 1157 }
1173 } 1158 }
1174 } 1159 }
1175 1160
1176 return true; // need to update the database 1161 return true; // need to update the database
1177 } 1162 }
1178 } 1163 }
1179 1164
1180 public class OpenSimConfigSource 1165 public class OpenSimConfigSource
1181 { 1166 {
1182 public IConfigSource Source; 1167 public IConfigSource Source;
1183
1184 public void Save(string path)
1185 {
1186 if (Source is IniConfigSource)
1187 {
1188 IniConfigSource iniCon = (IniConfigSource) Source;
1189 iniCon.Save(path);
1190 }
1191 else if (Source is XmlConfigSource)
1192 {
1193 XmlConfigSource xmlCon = (XmlConfigSource) Source;
1194 xmlCon.Save(path);
1195 }
1196 }
1197 } 1168 }
1198} 1169}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 650cd50..f6146a9 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -241,8 +241,8 @@ namespace OpenSim.Region.ClientStack.Linden
241 m_HostCapsObj.RegisterHandler( 241 m_HostCapsObj.RegisterHandler(
242 "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null)); 242 "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null));
243 243
244 m_log.DebugFormat( 244// m_log.DebugFormat(
245 "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); 245// "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID);
246 246
247 //m_capsHandlers["MapLayer"] = 247 //m_capsHandlers["MapLayer"] =
248 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST", 248 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
@@ -337,11 +337,12 @@ namespace OpenSim.Region.ClientStack.Linden
337 public string SeedCapRequest(string request, string path, string param, 337 public string SeedCapRequest(string request, string path, string param,
338 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 338 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
339 { 339 {
340// m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName); 340 m_log.DebugFormat(
341 "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID);
341 342
342 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) 343 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
343 { 344 {
344 m_log.DebugFormat( 345 m_log.WarnFormat(
345 "[CAPS]: Unauthorized CAPS client {0} from {1}", 346 "[CAPS]: Unauthorized CAPS client {0} from {1}",
346 m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint); 347 m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint);
347 348
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs
index 66b865f..b735dfa 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCapsModule.cs
@@ -45,7 +45,7 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
45namespace OpenSim.Region.ClientStack.Linden 45namespace OpenSim.Region.ClientStack.Linden
46{ 46{
47 47
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BunchOfCapsModule")]
49 public class BunchOfCapsModule : INonSharedRegionModule 49 public class BunchOfCapsModule : INonSharedRegionModule
50 { 50 {
51// private static readonly ILog m_log = 51// private static readonly ILog m_log =
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index e113c60..986a665 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -55,8 +55,8 @@ namespace OpenSim.Region.ClientStack.Linden
55 public OSDMap body; 55 public OSDMap body;
56 } 56 }
57 57
58 //[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EventQueueGetModule")]
59 public class EventQueueGetModule : IEventQueue, IRegionModule 59 public class EventQueueGetModule : IEventQueue, INonSharedRegionModule
60 { 60 {
61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62 62
@@ -66,8 +66,6 @@ namespace OpenSim.Region.ClientStack.Linden
66 public int DebugLevel { get; set; } 66 public int DebugLevel { get; set; }
67 67
68 protected Scene m_scene; 68 protected Scene m_scene;
69 private IConfigSource m_gConfig;
70 bool enabledYN;
71 69
72 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>(); 70 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
73 71
@@ -75,59 +73,46 @@ namespace OpenSim.Region.ClientStack.Linden
75 private Dictionary<UUID, UUID> m_QueueUUIDAvatarMapping = new Dictionary<UUID, UUID>(); 73 private Dictionary<UUID, UUID> m_QueueUUIDAvatarMapping = new Dictionary<UUID, UUID>();
76 private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>(); 74 private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>();
77 75
78 #region IRegionModule methods 76 #region INonSharedRegionModule methods
79 public virtual void Initialise(Scene scene, IConfigSource config) 77 public virtual void Initialise(IConfigSource config)
80 { 78 {
81 m_gConfig = config; 79 }
82 80
83 IConfig startupConfig = m_gConfig.Configs["Startup"]; 81 public void AddRegion(Scene scene)
82 {
83 m_scene = scene;
84 scene.RegisterModuleInterface<IEventQueue>(this);
84 85
85 ReadConfigAndPopulate(scene, startupConfig, "Startup"); 86 scene.EventManager.OnClientClosed += ClientClosed;
87 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
88 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
86 89
87 if (enabledYN) 90 MainConsole.Instance.Commands.AddCommand(
88 { 91 "Debug",
89 m_scene = scene; 92 false,
90 scene.RegisterModuleInterface<IEventQueue>(this); 93 "debug eq",
91 94 "debug eq [0|1|2]",
92 // Register fallback handler 95 "Turn on event queue debugging\n"
93 // Why does EQG Fail on region crossings! 96 + " <= 0 - turns off all event queue logging\n"
94 97 + " >= 1 - turns on outgoing event logging\n"
95 //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); 98 + " >= 2 - turns on poll notification",
96 99 HandleDebugEq);
97 scene.EventManager.OnNewClient += OnNewClient;
98
99 // TODO: Leaving these open, or closing them when we
100 // become a child is incorrect. It messes up TP in a big
101 // way. CAPS/EQ need to be active as long as the UDP
102 // circuit is there.
103
104 scene.EventManager.OnClientClosed += ClientClosed;
105 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
106 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
107
108 MainConsole.Instance.Commands.AddCommand(
109 "Debug",
110 false,
111 "debug eq",
112 "debug eq [0|1|2]",
113 "Turn on event queue debugging"
114 + "<= 0 - turns off all event queue logging"
115 + ">= 1 - turns on outgoing event logging"
116 + ">= 2 - turns on poll notification",
117 HandleDebugEq);
118 }
119 else
120 {
121 m_gConfig = null;
122 }
123 } 100 }
124 101
125 private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string p) 102 public void RemoveRegion(Scene scene)
126 { 103 {
127 enabledYN = startupConfig.GetBoolean("EventQueue", true); 104 if (m_scene != scene)
105 return;
106
107 scene.EventManager.OnClientClosed -= ClientClosed;
108 scene.EventManager.OnMakeChildAgent -= MakeChildAgent;
109 scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
110
111 scene.UnregisterModuleInterface<IEventQueue>(this);
112 m_scene = null;
128 } 113 }
129 114
130 public void PostInitialise() 115 public void RegionLoaded(Scene scene)
131 { 116 {
132 } 117 }
133 118
@@ -140,10 +125,11 @@ namespace OpenSim.Region.ClientStack.Linden
140 get { return "EventQueueGetModule"; } 125 get { return "EventQueueGetModule"; }
141 } 126 }
142 127
143 public bool IsSharedModule 128 public Type ReplaceableInterface
144 { 129 {
145 get { return false; } 130 get { return null; }
146 } 131 }
132
147 #endregion 133 #endregion
148 134
149 protected void HandleDebugEq(string module, string[] args) 135 protected void HandleDebugEq(string module, string[] args)
@@ -226,16 +212,6 @@ namespace OpenSim.Region.ClientStack.Linden
226 212
227 #endregion 213 #endregion
228 214
229 private void OnNewClient(IClientAPI client)
230 {
231 //client.OnLogout += ClientClosed;
232 }
233
234// private void ClientClosed(IClientAPI client)
235// {
236// ClientClosed(client.AgentId);
237// }
238
239 private void ClientClosed(UUID agentID, Scene scene) 215 private void ClientClosed(UUID agentID, Scene scene)
240 { 216 {
241// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); 217// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index cd70410..d604cf6 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
94 UUID spId = TestHelpers.ParseTail(0x1); 94 UUID spId = TestHelpers.ParseTail(0x1);
95 95
96 SceneHelpers.AddScenePresence(m_scene, spId); 96 SceneHelpers.AddScenePresence(m_scene, spId);
97 m_scene.IncomingCloseAgent(spId); 97 m_scene.IncomingCloseAgent(spId, false);
98 98
99 // TODO: Add more assertions for the other aspects of event queues 99 // TODO: Add more assertions for the other aspects of event queues
100 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); 100 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs b/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs
index cb5afcc..87d3d1c 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.ClientStack.Linden
45 /// <summary> 45 /// <summary>
46 /// This module implements both WebFetchInventoryDescendents and FetchInventoryDescendents2 capabilities. 46 /// This module implements both WebFetchInventoryDescendents and FetchInventoryDescendents2 capabilities.
47 /// </summary> 47 /// </summary>
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "FetchInventory2Module")]
49 public class FetchInventory2Module : INonSharedRegionModule 49 public class FetchInventory2Module : INonSharedRegionModule
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);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
index 0d7b1fc..6b33561 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
@@ -27,11 +27,14 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
30using System.Collections.Specialized; 31using System.Collections.Specialized;
31using System.Reflection; 32using System.Reflection;
32using System.IO; 33using System.IO;
34using System.Threading;
33using System.Web; 35using System.Web;
34using Mono.Addins; 36using Mono.Addins;
37using OpenSim.Framework.Monitoring;
35using log4net; 38using log4net;
36using Nini.Config; 39using Nini.Config;
37using OpenMetaverse; 40using OpenMetaverse;
@@ -47,7 +50,7 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
47 50
48namespace OpenSim.Region.ClientStack.Linden 51namespace OpenSim.Region.ClientStack.Linden
49{ 52{
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetMeshModule")]
51 public class GetMeshModule : INonSharedRegionModule 54 public class GetMeshModule : INonSharedRegionModule
52 { 55 {
53// private static readonly ILog m_log = 56// private static readonly ILog m_log =
@@ -57,8 +60,44 @@ namespace OpenSim.Region.ClientStack.Linden
57 private IAssetService m_AssetService; 60 private IAssetService m_AssetService;
58 private bool m_Enabled = true; 61 private bool m_Enabled = true;
59 private string m_URL; 62 private string m_URL;
63
64 struct aPollRequest
65 {
66 public PollServiceMeshEventArgs thepoll;
67 public UUID reqID;
68 public Hashtable request;
69 }
70
71 public class aPollResponse
72 {
73 public Hashtable response;
74 public int bytes;
75 public int lod;
76 }
77
78
79 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
80
81 private static GetMeshHandler m_getMeshHandler;
60 82
61 #region IRegionModuleBase Members 83 private IAssetService m_assetService = null;
84
85 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
86 private static Thread[] m_workerThreads = null;
87
88 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
89 new OpenMetaverse.BlockingQueue<aPollRequest>();
90
91 private Dictionary<UUID, PollServiceMeshEventArgs> m_pollservices = new Dictionary<UUID, PollServiceMeshEventArgs>();
92
93 #region Region Module interfaceBase Members
94
95 ~GetMeshModule()
96 {
97 foreach (Thread t in m_workerThreads)
98 Watchdog.AbortThread(t.ManagedThreadId);
99
100 }
62 101
63 public Type ReplaceableInterface 102 public Type ReplaceableInterface
64 { 103 {
@@ -75,6 +114,7 @@ namespace OpenSim.Region.ClientStack.Linden
75 // Cap doesn't exist 114 // Cap doesn't exist
76 if (m_URL != string.Empty) 115 if (m_URL != string.Empty)
77 m_Enabled = true; 116 m_Enabled = true;
117
78 } 118 }
79 119
80 public void AddRegion(Scene pScene) 120 public void AddRegion(Scene pScene)
@@ -83,6 +123,8 @@ namespace OpenSim.Region.ClientStack.Linden
83 return; 123 return;
84 124
85 m_scene = pScene; 125 m_scene = pScene;
126
127 m_assetService = pScene.AssetService;
86 } 128 }
87 129
88 public void RemoveRegion(Scene scene) 130 public void RemoveRegion(Scene scene)
@@ -91,6 +133,9 @@ namespace OpenSim.Region.ClientStack.Linden
91 return; 133 return;
92 134
93 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 135 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
136 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
137 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
138
94 m_scene = null; 139 m_scene = null;
95 } 140 }
96 141
@@ -101,6 +146,27 @@ namespace OpenSim.Region.ClientStack.Linden
101 146
102 m_AssetService = m_scene.RequestModuleInterface<IAssetService>(); 147 m_AssetService = m_scene.RequestModuleInterface<IAssetService>();
103 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 148 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
149 // We'll reuse the same handler for all requests.
150 m_getMeshHandler = new GetMeshHandler(m_assetService);
151 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
152 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
153
154 if (m_workerThreads == null)
155 {
156 m_workerThreads = new Thread[2];
157
158 for (uint i = 0; i < 2; i++)
159 {
160 m_workerThreads[i] = Watchdog.StartThread(DoMeshRequests,
161 String.Format("MeshWorkerThread{0}", i),
162 ThreadPriority.Normal,
163 false,
164 false,
165 null,
166 int.MaxValue);
167 }
168 }
169
104 } 170 }
105 171
106 172
@@ -110,25 +176,212 @@ namespace OpenSim.Region.ClientStack.Linden
110 176
111 #endregion 177 #endregion
112 178
179 private void DoMeshRequests()
180 {
181 while (true)
182 {
183 aPollRequest poolreq = m_queue.Dequeue();
184
185 poolreq.thepoll.Process(poolreq);
186 }
187 }
188
189 // Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent.
190 public void ThrottleUpdate(ScenePresence p)
191 {
192 byte[] throttles = p.ControllingClient.GetThrottlesPacked(1);
193 UUID user = p.UUID;
194 int imagethrottle = ExtractTaskThrottle(throttles);
195 PollServiceMeshEventArgs args;
196 if (m_pollservices.TryGetValue(user, out args))
197 {
198 args.UpdateThrottle(imagethrottle, p);
199 }
200 }
201
202 private int ExtractTaskThrottle(byte[] pthrottles)
203 {
204
205 byte[] adjData;
206 int pos = 0;
207
208 if (!BitConverter.IsLittleEndian)
209 {
210 byte[] newData = new byte[7 * 4];
211 Buffer.BlockCopy(pthrottles, 0, newData, 0, 7 * 4);
212
213 for (int i = 0; i < 7; i++)
214 Array.Reverse(newData, i * 4, 4);
215
216 adjData = newData;
217 }
218 else
219 {
220 adjData = pthrottles;
221 }
222
223 // 0.125f converts from bits to bytes
224 //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
225 //pos += 4;
226 // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
227 //pos += 4;
228 // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
229 // pos += 4;
230 // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
231 // pos += 4;
232 pos += 16;
233 int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
234 // pos += 4;
235 //int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); //pos += 4;
236 //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
237 return task;
238 }
239
240 private class PollServiceMeshEventArgs : PollServiceEventArgs
241 {
242 private List<Hashtable> requests =
243 new List<Hashtable>();
244 private Dictionary<UUID, aPollResponse> responses =
245 new Dictionary<UUID, aPollResponse>();
246
247 private Scene m_scene;
248 private MeshCapsDataThrottler m_throttler;
249 public PollServiceMeshEventArgs(UUID pId, Scene scene) :
250 base(null, null, null, null, pId, int.MaxValue)
251 {
252 m_scene = scene;
253 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId);
254 // x is request id, y is userid
255 HasEvents = (x, y) =>
256 {
257 lock (responses)
258 {
259 bool ret = m_throttler.hasEvents(x, responses);
260 m_throttler.ProcessTime();
261 return ret;
262
263 }
264 };
265 GetEvents = (x, y) =>
266 {
267 lock (responses)
268 {
269 try
270 {
271 return responses[x].response;
272 }
273 finally
274 {
275 m_throttler.ProcessTime();
276 responses.Remove(x);
277 }
278 }
279 };
280 // x is request id, y is request data hashtable
281 Request = (x, y) =>
282 {
283 aPollRequest reqinfo = new aPollRequest();
284 reqinfo.thepoll = this;
285 reqinfo.reqID = x;
286 reqinfo.request = y;
287
288 m_queue.Enqueue(reqinfo);
289 };
290
291 // this should never happen except possible on shutdown
292 NoEvents = (x, y) =>
293 {
294 /*
295 lock (requests)
296 {
297 Hashtable request = requests.Find(id => id["RequestID"].ToString() == x.ToString());
298 requests.Remove(request);
299 }
300 */
301 Hashtable response = new Hashtable();
302
303 response["int_response_code"] = 500;
304 response["str_response_string"] = "Script timeout";
305 response["content_type"] = "text/plain";
306 response["keepalive"] = false;
307 response["reusecontext"] = false;
308
309 return response;
310 };
311 }
312
313 public void Process(aPollRequest requestinfo)
314 {
315 Hashtable response;
316
317 UUID requestID = requestinfo.reqID;
318
319 // If the avatar is gone, don't bother to get the texture
320 if (m_scene.GetScenePresence(Id) == null)
321 {
322 response = new Hashtable();
323
324 response["int_response_code"] = 500;
325 response["str_response_string"] = "Script timeout";
326 response["content_type"] = "text/plain";
327 response["keepalive"] = false;
328 response["reusecontext"] = false;
329
330 lock (responses)
331 responses[requestID] = new aPollResponse() { bytes = 0, response = response, lod = 0 };
332
333 return;
334 }
335
336 response = m_getMeshHandler.Handle(requestinfo.request);
337 lock (responses)
338 {
339 responses[requestID] = new aPollResponse()
340 {
341 bytes = (int)response["int_bytes"],
342 lod = (int)response["int_lod"],
343 response = response
344 };
345
346 }
347 m_throttler.ProcessTime();
348 }
349
350 internal void UpdateThrottle(int pimagethrottle, ScenePresence p)
351 {
352 m_throttler.UpdateThrottle(pimagethrottle, p);
353 }
354 }
113 355
114 public void RegisterCaps(UUID agentID, Caps caps) 356 public void RegisterCaps(UUID agentID, Caps caps)
115 { 357 {
116// UUID capID = UUID.Random(); 358// UUID capID = UUID.Random();
117
118 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture));
119 if (m_URL == "localhost") 359 if (m_URL == "localhost")
120 { 360 {
121// m_log.DebugFormat("[GETMESH]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 361 string capUrl = "/CAPS/" + UUID.Random() + "/";
122 GetMeshHandler gmeshHandler = new GetMeshHandler(m_AssetService); 362
123 IRequestHandler reqHandler 363 // Register this as a poll service
124 = new RestHTTPHandler( 364 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(agentID, m_scene);
125 "GET", 365
126 "/CAPS/" + UUID.Random(), 366 args.Type = PollServiceEventArgs.EventType.Mesh;
127 httpMethod => gmeshHandler.ProcessGetMesh(httpMethod, UUID.Zero, null), 367 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
128 "GetMesh",
129 agentID.ToString());
130 368
131 caps.RegisterHandler("GetMesh", reqHandler); 369 string hostName = m_scene.RegionInfo.ExternalHostName;
370 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
371 string protocol = "http";
372
373 if (MainServer.Instance.UseSSL)
374 {
375 hostName = MainServer.Instance.SSLCommonName;
376 port = MainServer.Instance.SSLPort;
377 protocol = "https";
378 }
379 caps.RegisterHandler("GetMesh", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
380 m_pollservices.Add(agentID, args);
381 m_capsDict[agentID] = capUrl;
382
383
384
132 } 385 }
133 else 386 else
134 { 387 {
@@ -136,6 +389,171 @@ namespace OpenSim.Region.ClientStack.Linden
136 caps.RegisterHandler("GetMesh", m_URL); 389 caps.RegisterHandler("GetMesh", m_URL);
137 } 390 }
138 } 391 }
392 private void DeregisterCaps(UUID agentID, Caps caps)
393 {
394 string capUrl;
395 PollServiceMeshEventArgs args;
396 if (m_capsDict.TryGetValue(agentID, out capUrl))
397 {
398 MainServer.Instance.RemoveHTTPHandler("", capUrl);
399 m_capsDict.Remove(agentID);
400 }
401 if (m_pollservices.TryGetValue(agentID, out args))
402 {
403 m_pollservices.Remove(agentID);
404 }
405 }
406
407 internal sealed class MeshCapsDataThrottler
408 {
409
410 private volatile int currenttime = 0;
411 private volatile int lastTimeElapsed = 0;
412 private volatile int BytesSent = 0;
413 private int Lod3 = 0;
414 private int Lod2 = 0;
415 private int Lod1 = 0;
416 private int UserSetThrottle = 0;
417 private int UDPSetThrottle = 0;
418 private int CapSetThrottle = 0;
419 private float CapThrottleDistributon = 0.30f;
420 private readonly Scene m_scene;
421 private ThrottleOutPacketType Throttle;
422 private readonly UUID User;
423
424 public MeshCapsDataThrottler(int pBytes, int max, int min, Scene pScene, UUID puser)
425 {
426 ThrottleBytes = pBytes;
427 lastTimeElapsed = Util.EnvironmentTickCount();
428 Throttle = ThrottleOutPacketType.Task;
429 m_scene = pScene;
430 User = puser;
431 }
432
433
434 public bool hasEvents(UUID key, Dictionary<UUID, aPollResponse> responses)
435 {
436 const float ThirtyPercent = 0.30f;
437 const float FivePercent = 0.05f;
438 PassTime();
439 // Note, this is called IN LOCK
440 bool haskey = responses.ContainsKey(key);
441
442 if (responses.Count > 2)
443 {
444 SplitThrottle(ThirtyPercent);
445 }
446 else
447 {
448 SplitThrottle(FivePercent);
449 }
450
451 if (!haskey)
452 {
453 return false;
454 }
455 aPollResponse response;
456 if (responses.TryGetValue(key, out response))
457 {
458 float LOD3Over = (((ThrottleBytes*CapThrottleDistributon)%50000) + 1);
459 float LOD2Over = (((ThrottleBytes*CapThrottleDistributon)%10000) + 1);
460 // Normal
461 if (BytesSent + response.bytes <= ThrottleBytes)
462 {
463 BytesSent += response.bytes;
464
465 return true;
466 }
467 // Lod3 Over Throttle protection to keep things processing even when the throttle bandwidth is set too little.
468 else if (response.bytes > ThrottleBytes && Lod3 <= ((LOD3Over < 1)? 1: LOD3Over) )
469 {
470 Interlocked.Increment(ref Lod3);
471 BytesSent += response.bytes;
472
473 return true;
474 }
475 // Lod2 Over Throttle protection to keep things processing even when the throttle bandwidth is set too little.
476 else if (response.bytes > ThrottleBytes && Lod2 <= ((LOD2Over < 1) ? 1 : LOD2Over))
477 {
478 Interlocked.Increment(ref Lod2);
479 BytesSent += response.bytes;
480
481 return true;
482 }
483 else
484 {
485 return false;
486 }
487 }
488
489 return haskey;
490 }
491 public void SubtractBytes(int bytes,int lod)
492 {
493 BytesSent -= bytes;
494 }
495 private void SplitThrottle(float percentMultiplier)
496 {
497
498 if (CapThrottleDistributon != percentMultiplier) // don't switch it if it's already set at the % multipler
499 {
500 CapThrottleDistributon = percentMultiplier;
501 ScenePresence p;
502 if (m_scene.TryGetScenePresence(User, out p)) // If we don't get a user they're not here anymore.
503 {
504 AlterThrottle(UserSetThrottle, p);
505 }
506 }
507 }
508
509 public void ProcessTime()
510 {
511 PassTime();
512 }
513
514
515 private void PassTime()
516 {
517 currenttime = Util.EnvironmentTickCount();
518 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
519 //processTimeBasedActions(responses);
520 if (currenttime - timeElapsed >= 1000)
521 {
522 lastTimeElapsed = Util.EnvironmentTickCount();
523 BytesSent -= ThrottleBytes;
524 if (BytesSent < 0) BytesSent = 0;
525 if (BytesSent < ThrottleBytes)
526 {
527 Lod3 = 0;
528 Lod2 = 0;
529 Lod1 = 0;
530 }
531 }
532 }
533 private void AlterThrottle(int setting, ScenePresence p)
534 {
535 p.ControllingClient.SetAgentThrottleSilent((int)Throttle,setting);
536 }
537
538 public int ThrottleBytes
539 {
540 get { return CapSetThrottle; }
541 set { CapSetThrottle = value; }
542 }
543
544 internal void UpdateThrottle(int pimagethrottle, ScenePresence p)
545 {
546 // Client set throttle !
547 UserSetThrottle = pimagethrottle;
548 CapSetThrottle = (int)(pimagethrottle*CapThrottleDistributon);
549 UDPSetThrottle = (int) (pimagethrottle*(100 - CapThrottleDistributon));
550 if (CapSetThrottle < 4068)
551 CapSetThrottle = 4068; // at least two discovery mesh
552 p.ControllingClient.SetAgentThrottleSilent((int) Throttle, UDPSetThrottle);
553 ProcessTime();
554
555 }
556 }
139 557
140 } 558 }
141} 559}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index d1a1583..dd87671 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -47,9 +47,6 @@ using OpenSim.Framework.Monitoring;
47namespace OpenSim.Region.ClientStack.Linden 47namespace OpenSim.Region.ClientStack.Linden
48{ 48{
49 49
50 /// <summary>
51 /// This module implements both WebFetchTextureDescendents and FetchTextureDescendents2 capabilities.
52 /// </summary>
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")] 50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GetTextureModule")]
54 public class GetTextureModule : INonSharedRegionModule 51 public class GetTextureModule : INonSharedRegionModule
55 { 52 {
@@ -61,6 +58,13 @@ namespace OpenSim.Region.ClientStack.Linden
61 public Hashtable request; 58 public Hashtable request;
62 } 59 }
63 60
61 public class aPollResponse
62 {
63 public Hashtable response;
64 public int bytes;
65 }
66
67
64 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 68 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
65 69
66 private Scene m_scene; 70 private Scene m_scene;
@@ -75,6 +79,8 @@ namespace OpenSim.Region.ClientStack.Linden
75 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue = 79 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue =
76 new OpenMetaverse.BlockingQueue<aPollRequest>(); 80 new OpenMetaverse.BlockingQueue<aPollRequest>();
77 81
82 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>();
83
78 #region ISharedRegionModule Members 84 #region ISharedRegionModule Members
79 85
80 public void Initialise(IConfigSource source) 86 public void Initialise(IConfigSource source)
@@ -91,6 +97,7 @@ namespace OpenSim.Region.ClientStack.Linden
91 { 97 {
92 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 98 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
93 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps; 99 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps;
100 m_scene.EventManager.OnThrottleUpdate -= ThrottleUpdate;
94 m_scene = null; 101 m_scene = null;
95 } 102 }
96 103
@@ -101,6 +108,7 @@ namespace OpenSim.Region.ClientStack.Linden
101 108
102 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 109 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
103 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps; 110 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
111 m_scene.EventManager.OnThrottleUpdate += ThrottleUpdate;
104 112
105 if (m_workerThreads == null) 113 if (m_workerThreads == null)
106 { 114 {
@@ -118,6 +126,56 @@ namespace OpenSim.Region.ClientStack.Linden
118 } 126 }
119 } 127 }
120 } 128 }
129 private int ExtractImageThrottle(byte[] pthrottles)
130 {
131
132 byte[] adjData;
133 int pos = 0;
134
135 if (!BitConverter.IsLittleEndian)
136 {
137 byte[] newData = new byte[7 * 4];
138 Buffer.BlockCopy(pthrottles, 0, newData, 0, 7 * 4);
139
140 for (int i = 0; i < 7; i++)
141 Array.Reverse(newData, i * 4, 4);
142
143 adjData = newData;
144 }
145 else
146 {
147 adjData = pthrottles;
148 }
149
150 // 0.125f converts from bits to bytes
151 //int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
152 //pos += 4;
153 // int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
154 //pos += 4;
155 // int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
156 // pos += 4;
157 // int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
158 // pos += 4;
159 // int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
160 // pos += 4;
161 pos = pos + 20;
162 int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); //pos += 4;
163 //int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
164 return texture;
165 }
166
167 // Now we know when the throttle is changed by the client in the case of a root agent or by a neighbor region in the case of a child agent.
168 public void ThrottleUpdate(ScenePresence p)
169 {
170 byte[] throttles = p.ControllingClient.GetThrottlesPacked(1);
171 UUID user = p.UUID;
172 int imagethrottle = ExtractImageThrottle(throttles);
173 PollServiceTextureEventArgs args;
174 if (m_pollservices.TryGetValue(user,out args))
175 {
176 args.UpdateThrottle(imagethrottle);
177 }
178 }
121 179
122 public void PostInitialise() 180 public void PostInitialise()
123 { 181 {
@@ -145,20 +203,25 @@ namespace OpenSim.Region.ClientStack.Linden
145 { 203 {
146 private List<Hashtable> requests = 204 private List<Hashtable> requests =
147 new List<Hashtable>(); 205 new List<Hashtable>();
148 private Dictionary<UUID, Hashtable> responses = 206 private Dictionary<UUID, aPollResponse> responses =
149 new Dictionary<UUID, Hashtable>(); 207 new Dictionary<UUID, aPollResponse>();
150 208
151 private Scene m_scene; 209 private Scene m_scene;
152 210 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000);
153 public PollServiceTextureEventArgs(UUID pId, Scene scene) : 211 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
154 base(null, null, null, null, pId, int.MaxValue) 212 base(null, null, null, null, pId, int.MaxValue)
155 { 213 {
156 m_scene = scene; 214 m_scene = scene;
157 215 // x is request id, y is userid
158 HasEvents = (x, y) => 216 HasEvents = (x, y) =>
159 { 217 {
160 lock (responses) 218 lock (responses)
161 return responses.ContainsKey(x); 219 {
220 bool ret = m_throttler.hasEvents(x, responses);
221 m_throttler.ProcessTime();
222 return ret;
223
224 }
162 }; 225 };
163 GetEvents = (x, y) => 226 GetEvents = (x, y) =>
164 { 227 {
@@ -166,7 +229,7 @@ namespace OpenSim.Region.ClientStack.Linden
166 { 229 {
167 try 230 try
168 { 231 {
169 return responses[x]; 232 return responses[x].response;
170 } 233 }
171 finally 234 finally
172 { 235 {
@@ -174,14 +237,14 @@ namespace OpenSim.Region.ClientStack.Linden
174 } 237 }
175 } 238 }
176 }; 239 };
177 240 // x is request id, y is request data hashtable
178 Request = (x, y) => 241 Request = (x, y) =>
179 { 242 {
180 aPollRequest reqinfo = new aPollRequest(); 243 aPollRequest reqinfo = new aPollRequest();
181 reqinfo.thepoll = this; 244 reqinfo.thepoll = this;
182 reqinfo.reqID = x; 245 reqinfo.reqID = x;
183 reqinfo.request = y; 246 reqinfo.request = y;
184 247
185 m_queue.Enqueue(reqinfo); 248 m_queue.Enqueue(reqinfo);
186 }; 249 };
187 250
@@ -223,16 +286,29 @@ namespace OpenSim.Region.ClientStack.Linden
223 response["content_type"] = "text/plain"; 286 response["content_type"] = "text/plain";
224 response["keepalive"] = false; 287 response["keepalive"] = false;
225 response["reusecontext"] = false; 288 response["reusecontext"] = false;
226 289
227 lock (responses) 290 lock (responses)
228 responses[requestID] = response; 291 responses[requestID] = new aPollResponse() {bytes = 0, response = response};
229 292
230 return; 293 return;
231 } 294 }
232 295
233 response = m_getTextureHandler.Handle(requestinfo.request); 296 response = m_getTextureHandler.Handle(requestinfo.request);
234 lock (responses) 297 lock (responses)
235 responses[requestID] = response; 298 {
299 responses[requestID] = new aPollResponse()
300 {
301 bytes = (int) response["int_bytes"],
302 response = response
303 };
304
305 }
306 m_throttler.ProcessTime();
307 }
308
309 internal void UpdateThrottle(int pimagethrottle)
310 {
311 m_throttler.ThrottleBytes = pimagethrottle;
236 } 312 }
237 } 313 }
238 314
@@ -257,19 +333,23 @@ namespace OpenSim.Region.ClientStack.Linden
257 protocol = "https"; 333 protocol = "https";
258 } 334 }
259 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); 335 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
260 336 m_pollservices.Add(agentID, args);
261 m_capsDict[agentID] = capUrl; 337 m_capsDict[agentID] = capUrl;
262 } 338 }
263 339
264 private void DeregisterCaps(UUID agentID, Caps caps) 340 private void DeregisterCaps(UUID agentID, Caps caps)
265 { 341 {
266 string capUrl; 342 string capUrl;
267 343 PollServiceTextureEventArgs args;
268 if (m_capsDict.TryGetValue(agentID, out capUrl)) 344 if (m_capsDict.TryGetValue(agentID, out capUrl))
269 { 345 {
270 MainServer.Instance.RemoveHTTPHandler("", capUrl); 346 MainServer.Instance.RemoveHTTPHandler("", capUrl);
271 m_capsDict.Remove(agentID); 347 m_capsDict.Remove(agentID);
272 } 348 }
349 if (m_pollservices.TryGetValue(agentID, out args))
350 {
351 m_pollservices.Remove(agentID);
352 }
273 } 353 }
274 354
275 private void DoTextureRequests() 355 private void DoTextureRequests()
@@ -281,5 +361,81 @@ namespace OpenSim.Region.ClientStack.Linden
281 poolreq.thepoll.Process(poolreq); 361 poolreq.thepoll.Process(poolreq);
282 } 362 }
283 } 363 }
364 internal sealed class CapsDataThrottler
365 {
366
367 private volatile int currenttime = 0;
368 private volatile int lastTimeElapsed = 0;
369 private volatile int BytesSent = 0;
370 private int oversizedImages = 0;
371 public CapsDataThrottler(int pBytes, int max, int min)
372 {
373 ThrottleBytes = pBytes;
374 lastTimeElapsed = Util.EnvironmentTickCount();
375 }
376 public bool hasEvents(UUID key, Dictionary<UUID, GetTextureModule.aPollResponse> responses)
377 {
378 PassTime();
379 // Note, this is called IN LOCK
380 bool haskey = responses.ContainsKey(key);
381 if (!haskey)
382 {
383 return false;
384 }
385 GetTextureModule.aPollResponse response;
386 if (responses.TryGetValue(key, out response))
387 {
388
389 // Normal
390 if (BytesSent + response.bytes <= ThrottleBytes)
391 {
392 BytesSent += response.bytes;
393 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + 1000, unlockyn = false };
394 //m_actions.Add(timeBasedAction);
395 return true;
396 }
397 // Big textures
398 else if (response.bytes > ThrottleBytes && oversizedImages <= ((ThrottleBytes % 50000) + 1))
399 {
400 Interlocked.Increment(ref oversizedImages);
401 BytesSent += response.bytes;
402 //TimeBasedAction timeBasedAction = new TimeBasedAction { byteRemoval = response.bytes, requestId = key, timeMS = currenttime + (((response.bytes % ThrottleBytes)+1)*1000) , unlockyn = false };
403 //m_actions.Add(timeBasedAction);
404 return true;
405 }
406 else
407 {
408 return false;
409 }
410 }
411
412 return haskey;
413 }
414 public void ProcessTime()
415 {
416 PassTime();
417 }
418
419
420 private void PassTime()
421 {
422 currenttime = Util.EnvironmentTickCount();
423 int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed);
424 //processTimeBasedActions(responses);
425 if (Util.EnvironmentTickCountSubtract(currenttime, timeElapsed) >= 1000)
426 {
427 lastTimeElapsed = Util.EnvironmentTickCount();
428 BytesSent -= ThrottleBytes;
429 if (BytesSent < 0) BytesSent = 0;
430 if (BytesSent < ThrottleBytes)
431 {
432 oversizedImages = 0;
433 }
434 }
435 }
436 public int ThrottleBytes;
437 }
284 } 438 }
439
440
285} 441}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
index 0251ac4..60c1814 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/MeshUploadFlagModule.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.ClientStack.Linden
45 /// <summary> 45 /// <summary>
46 /// MeshUploadFlag capability. This is required for uploading Mesh. 46 /// MeshUploadFlag capability. This is required for uploading Mesh.
47 /// </summary> 47 /// </summary>
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MeshUploadFlagModule")]
49 public class MeshUploadFlagModule : INonSharedRegionModule 49 public class MeshUploadFlagModule : INonSharedRegionModule
50 { 50 {
51// private static readonly ILog m_log = 51// private static readonly ILog m_log =
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
index 4ccfc43..92805e2 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
@@ -32,6 +32,7 @@ using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.StructuredData; 34using OpenMetaverse.StructuredData;
35using Mono.Addins;
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Framework.Servers; 37using OpenSim.Framework.Servers;
37using OpenSim.Framework.Servers.HttpServer; 38using OpenSim.Framework.Servers.HttpServer;
@@ -41,30 +42,60 @@ using Caps=OpenSim.Framework.Capabilities.Caps;
41 42
42namespace OpenSim.Region.ClientStack.Linden 43namespace OpenSim.Region.ClientStack.Linden
43{ 44{
44 public class ObjectAdd : IRegionModule 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ObjectAdd")]
46 public class ObjectAdd : INonSharedRegionModule
45 { 47 {
46// private static readonly ILog m_log = 48// private static readonly ILog m_log =
47// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 50
49 private Scene m_scene; 51 private Scene m_scene;
50 #region IRegionModule Members
51 52
52 public void Initialise(Scene pScene, IConfigSource pSource) 53 #region INonSharedRegionModule Members
54
55 public void Initialise(IConfigSource pSource)
56 {
57 }
58
59 public void AddRegion(Scene scene)
53 { 60 {
54 m_scene = pScene; 61 m_scene = scene;
55 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 62 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
56 } 63 }
57 64
58 public void PostInitialise() 65 public void RemoveRegion(Scene scene)
59 { 66 {
60 67 if (m_scene == scene)
68 {
69 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
70 m_scene = null;
71 }
61 } 72 }
62 73
74 public void RegionLoaded(Scene scene)
75 {
76 }
77
78 public void Close()
79 {
80 }
81
82 public string Name
83 {
84 get { return "ObjectAddModule"; }
85 }
86
87 public Type ReplaceableInterface
88 {
89 get { return null; }
90 }
91
92 #endregion
93
63 public void RegisterCaps(UUID agentID, Caps caps) 94 public void RegisterCaps(UUID agentID, Caps caps)
64 { 95 {
65 UUID capuuid = UUID.Random(); 96 UUID capuuid = UUID.Random();
66 97
67// m_log.InfoFormat("[OBJECTADD]: {0}", "/CAPS/OA/" + capuuid + "/"); 98 // m_log.InfoFormat("[OBJECTADD]: {0}", "/CAPS/OA/" + capuuid + "/");
68 99
69 caps.RegisterHandler( 100 caps.RegisterHandler(
70 "ObjectAdd", 101 "ObjectAdd",
@@ -73,7 +104,7 @@ namespace OpenSim.Region.ClientStack.Linden
73 "/CAPS/OA/" + capuuid + "/", 104 "/CAPS/OA/" + capuuid + "/",
74 httpMethod => ProcessAdd(httpMethod, agentID, caps), 105 httpMethod => ProcessAdd(httpMethod, agentID, caps),
75 "ObjectAdd", 106 "ObjectAdd",
76 agentID.ToString()));; 107 agentID.ToString())); ;
77 } 108 }
78 109
79 public Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap) 110 public Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap)
@@ -84,7 +115,7 @@ namespace OpenSim.Region.ClientStack.Linden
84 responsedata["keepalive"] = false; 115 responsedata["keepalive"] = false;
85 responsedata["str_response_string"] = "Request wasn't what was expected"; 116 responsedata["str_response_string"] = "Request wasn't what was expected";
86 ScenePresence avatar; 117 ScenePresence avatar;
87 118
88 if (!m_scene.TryGetScenePresence(AgentId, out avatar)) 119 if (!m_scene.TryGetScenePresence(AgentId, out avatar))
89 return responsedata; 120 return responsedata;
90 121
@@ -127,7 +158,7 @@ namespace OpenSim.Region.ClientStack.Linden
127 158
128 if (r.Type != OSDType.Map) // not a proper req 159 if (r.Type != OSDType.Map) // not a proper req
129 return responsedata; 160 return responsedata;
130 161
131 OSDMap rm = (OSDMap)r; 162 OSDMap rm = (OSDMap)r;
132 163
133 if (rm.ContainsKey("ObjectData")) //v2 164 if (rm.ContainsKey("ObjectData")) //v2
@@ -138,7 +169,7 @@ namespace OpenSim.Region.ClientStack.Linden
138 return responsedata; 169 return responsedata;
139 } 170 }
140 171
141 OSDMap ObjMap = (OSDMap) rm["ObjectData"]; 172 OSDMap ObjMap = (OSDMap)rm["ObjectData"];
142 173
143 bypass_raycast = ObjMap["BypassRaycast"].AsBoolean(); 174 bypass_raycast = ObjMap["BypassRaycast"].AsBoolean();
144 everyone_mask = readuintval(ObjMap["EveryoneMask"]); 175 everyone_mask = readuintval(ObjMap["EveryoneMask"]);
@@ -181,7 +212,7 @@ namespace OpenSim.Region.ClientStack.Linden
181 responsedata["str_response_string"] = "Has Profile key, but data not in expected format"; 212 responsedata["str_response_string"] = "Has Profile key, but data not in expected format";
182 return responsedata; 213 return responsedata;
183 } 214 }
184 215
185 OSDMap ProfileMap = (OSDMap)ObjMap["Profile"]; 216 OSDMap ProfileMap = (OSDMap)ObjMap["Profile"];
186 217
187 profile_begin = ProfileMap["Begin"].AsInteger(); 218 profile_begin = ProfileMap["Begin"].AsInteger();
@@ -190,14 +221,14 @@ namespace OpenSim.Region.ClientStack.Linden
190 hollow = ProfileMap["Hollow"].AsInteger(); 221 hollow = ProfileMap["Hollow"].AsInteger();
191 } 222 }
192 ray_end_is_intersection = ObjMap["RayEndIsIntersection"].AsBoolean(); 223 ray_end_is_intersection = ObjMap["RayEndIsIntersection"].AsBoolean();
193 224
194 ray_target_id = ObjMap["RayTargetId"].AsUUID(); 225 ray_target_id = ObjMap["RayTargetId"].AsUUID();
195 state = ObjMap["State"].AsInteger(); 226 state = ObjMap["State"].AsInteger();
196 try 227 try
197 { 228 {
198 ray_end = ((OSDArray) ObjMap["RayEnd"]).AsVector3(); 229 ray_end = ((OSDArray)ObjMap["RayEnd"]).AsVector3();
199 ray_start = ((OSDArray) ObjMap["RayStart"]).AsVector3(); 230 ray_start = ((OSDArray)ObjMap["RayStart"]).AsVector3();
200 scale = ((OSDArray) ObjMap["Scale"]).AsVector3(); 231 scale = ((OSDArray)ObjMap["Scale"]).AsVector3();
201 rotation = ((OSDArray)ObjMap["Rotation"]).AsQuaternion(); 232 rotation = ((OSDArray)ObjMap["Rotation"]).AsQuaternion();
202 } 233 }
203 catch (Exception) 234 catch (Exception)
@@ -214,7 +245,7 @@ namespace OpenSim.Region.ClientStack.Linden
214 return responsedata; 245 return responsedata;
215 } 246 }
216 247
217 OSDMap AgentDataMap = (OSDMap) rm["AgentData"]; 248 OSDMap AgentDataMap = (OSDMap)rm["AgentData"];
218 249
219 //session_id = AgentDataMap["SessionId"].AsUUID(); 250 //session_id = AgentDataMap["SessionId"].AsUUID();
220 group_id = AgentDataMap["GroupId"].AsUUID(); 251 group_id = AgentDataMap["GroupId"].AsUUID();
@@ -251,21 +282,21 @@ namespace OpenSim.Region.ClientStack.Linden
251 profile_begin = rm["profile_begin"].AsInteger(); 282 profile_begin = rm["profile_begin"].AsInteger();
252 profile_curve = rm["profile_curve"].AsInteger(); 283 profile_curve = rm["profile_curve"].AsInteger();
253 profile_end = rm["profile_end"].AsInteger(); 284 profile_end = rm["profile_end"].AsInteger();
254 285
255 ray_end_is_intersection = rm["ray_end_is_intersection"].AsBoolean(); 286 ray_end_is_intersection = rm["ray_end_is_intersection"].AsBoolean();
256 287
257 ray_target_id = rm["ray_target_id"].AsUUID(); 288 ray_target_id = rm["ray_target_id"].AsUUID();
258 289
259 290
260 //session_id = rm["session_id"].AsUUID(); 291 //session_id = rm["session_id"].AsUUID();
261 state = rm["state"].AsInteger(); 292 state = rm["state"].AsInteger();
262 try 293 try
263 { 294 {
264 ray_end = ((OSDArray)rm["ray_end"]).AsVector3(); 295 ray_end = ((OSDArray)rm["ray_end"]).AsVector3();
265 ray_start = ((OSDArray)rm["ray_start"]).AsVector3(); 296 ray_start = ((OSDArray)rm["ray_start"]).AsVector3();
266 rotation = ((OSDArray)rm["rotation"]).AsQuaternion(); 297 rotation = ((OSDArray)rm["rotation"]).AsQuaternion();
267 scale = ((OSDArray)rm["scale"]).AsVector3(); 298 scale = ((OSDArray)rm["scale"]).AsVector3();
268 } 299 }
269 catch (Exception) 300 catch (Exception)
270 { 301 {
271 responsedata["str_response_string"] = "RayEnd, RayStart, Scale or Rotation wasn't in the expected format"; 302 responsedata["str_response_string"] = "RayEnd, RayStart, Scale or Rotation wasn't in the expected format";
@@ -273,9 +304,9 @@ namespace OpenSim.Region.ClientStack.Linden
273 } 304 }
274 } 305 }
275 306
276
277 307
278 Vector3 pos = m_scene.GetNewRezLocation(ray_start, ray_end, ray_target_id, rotation, (bypass_raycast) ? (byte)1 : (byte)0, (ray_end_is_intersection) ? (byte)1 : (byte)0, true, scale, false); 308
309 Vector3 pos = m_scene.GetNewRezLocation(ray_start, ray_end, ray_target_id, rotation, (bypass_raycast) ? (byte)1 : (byte)0, (ray_end_is_intersection) ? (byte)1 : (byte)0, true, scale, false);
279 310
280 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); 311 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
281 312
@@ -286,17 +317,17 @@ namespace OpenSim.Region.ClientStack.Linden
286 pbs.PathRevolutions = (byte)path_revolutions; 317 pbs.PathRevolutions = (byte)path_revolutions;
287 pbs.PathScaleX = (byte)path_scale_x; 318 pbs.PathScaleX = (byte)path_scale_x;
288 pbs.PathScaleY = (byte)path_scale_y; 319 pbs.PathScaleY = (byte)path_scale_y;
289 pbs.PathShearX = (byte) path_shear_x; 320 pbs.PathShearX = (byte)path_shear_x;
290 pbs.PathShearY = (byte)path_shear_y; 321 pbs.PathShearY = (byte)path_shear_y;
291 pbs.PathSkew = (sbyte)path_skew; 322 pbs.PathSkew = (sbyte)path_skew;
292 pbs.PathTaperX = (sbyte)path_taper_x; 323 pbs.PathTaperX = (sbyte)path_taper_x;
293 pbs.PathTaperY = (sbyte)path_taper_y; 324 pbs.PathTaperY = (sbyte)path_taper_y;
294 pbs.PathTwist = (sbyte)path_twist; 325 pbs.PathTwist = (sbyte)path_twist;
295 pbs.PathTwistBegin = (sbyte)path_twist_begin; 326 pbs.PathTwistBegin = (sbyte)path_twist_begin;
296 pbs.HollowShape = (HollowShape) hollow; 327 pbs.HollowShape = (HollowShape)hollow;
297 pbs.PCode = (byte)p_code; 328 pbs.PCode = (byte)p_code;
298 pbs.ProfileBegin = (ushort) profile_begin; 329 pbs.ProfileBegin = (ushort)profile_begin;
299 pbs.ProfileCurve = (byte) profile_curve; 330 pbs.ProfileCurve = (byte)profile_curve;
300 pbs.ProfileEnd = (ushort)profile_end; 331 pbs.ProfileEnd = (ushort)profile_end;
301 pbs.Scale = scale; 332 pbs.Scale = scale;
302 pbs.State = (byte)state; 333 pbs.State = (byte)state;
@@ -306,7 +337,7 @@ namespace OpenSim.Region.ClientStack.Linden
306 if (m_scene.Permissions.CanRezObject(1, avatar.UUID, pos)) 337 if (m_scene.Permissions.CanRezObject(1, avatar.UUID, pos))
307 { 338 {
308 // rez ON the ground, not IN the ground 339 // rez ON the ground, not IN the ground
309 // pos.Z += 0.25F; 340 // pos.Z += 0.25F;
310 341
311 obj = m_scene.AddNewPrim(avatar.UUID, group_id, pos, rotation, pbs); 342 obj = m_scene.AddNewPrim(avatar.UUID, group_id, pos, rotation, pbs);
312 } 343 }
@@ -323,13 +354,13 @@ namespace OpenSim.Region.ClientStack.Linden
323 rootpart.GroupMask = group_mask; 354 rootpart.GroupMask = group_mask;
324 rootpart.NextOwnerMask = next_owner_mask; 355 rootpart.NextOwnerMask = next_owner_mask;
325 rootpart.Material = (byte)material; 356 rootpart.Material = (byte)material;
326 357
327 m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor); 358 m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor);
328 359
329 responsedata["int_response_code"] = 200; //501; //410; //404; 360 responsedata["int_response_code"] = 200; //501; //410; //404;
330 responsedata["content_type"] = "text/plain"; 361 responsedata["content_type"] = "text/plain";
331 responsedata["keepalive"] = false; 362 responsedata["keepalive"] = false;
332 responsedata["str_response_string"] = String.Format("<llsd><map><key>local_id</key>{0}</map></llsd>",ConvertUintToBytes(obj.LocalId)); 363 responsedata["str_response_string"] = String.Format("<llsd><map><key>local_id</key>{0}</map></llsd>", ConvertUintToBytes(obj.LocalId));
333 364
334 return responsedata; 365 return responsedata;
335 } 366 }
@@ -347,24 +378,8 @@ namespace OpenSim.Region.ClientStack.Linden
347 byte[] resultbytes = Utils.UIntToBytes(val); 378 byte[] resultbytes = Utils.UIntToBytes(val);
348 if (BitConverter.IsLittleEndian) 379 if (BitConverter.IsLittleEndian)
349 Array.Reverse(resultbytes); 380 Array.Reverse(resultbytes);
350 return String.Format("<binary encoding=\"base64\">{0}</binary>",Convert.ToBase64String(resultbytes)); 381 return String.Format("<binary encoding=\"base64\">{0}</binary>", Convert.ToBase64String(resultbytes));
351 }
352
353 public void Close()
354 {
355
356 }
357
358 public string Name
359 {
360 get { return "ObjectAddModule"; }
361 }
362
363 public bool IsSharedModule
364 {
365 get { return false; }
366 } 382 }
367 383
368 #endregion
369 } 384 }
370} 385}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
index ba902b2..55a503e 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
@@ -51,14 +51,14 @@ using ExtraParamType = OpenMetaverse.ExtraParamType;
51 51
52namespace OpenSim.Region.ClientStack.Linden 52namespace OpenSim.Region.ClientStack.Linden
53{ 53{
54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UploadObjectAssetModule")]
55 public class UploadObjectAssetModule : INonSharedRegionModule 55 public class UploadObjectAssetModule : INonSharedRegionModule
56 { 56 {
57 private static readonly ILog m_log = 57 private static readonly ILog m_log =
58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 private Scene m_scene; 59 private Scene m_scene;
60 60
61 #region IRegionModuleBase Members 61 #region Region Module interfaceBase Members
62 62
63 63
64 public Type ReplaceableInterface 64 public Type ReplaceableInterface
@@ -92,7 +92,7 @@ namespace OpenSim.Region.ClientStack.Linden
92 #endregion 92 #endregion
93 93
94 94
95 #region IRegionModule Members 95 #region Region Module interface
96 96
97 97
98 98
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..060a61c
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.ClientStack.LindenCaps")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("1ae76353-f37f-4fe3-b6df-d11cedf01f2c")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
index 0a5ad0f..fcac182 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
@@ -109,7 +109,7 @@ namespace OpenSim.Region.ClientStack.Linden
109 109
110 UUID capID = UUID.Random(); 110 UUID capID = UUID.Random();
111 111
112 m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 112// m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
113 caps.RegisterHandler( 113 caps.RegisterHandler(
114 "SimConsoleAsync", 114 "SimConsoleAsync",
115 new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene)); 115 new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene));
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
index 8ed0fb3..191bccf 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.ClientStack.Linden
53 /// NOTE: Part of this code was adapted from the Aurora project, specifically 53 /// NOTE: Part of this code was adapted from the Aurora project, specifically
54 /// the normal part of the response in the capability handler. 54 /// the normal part of the response in the capability handler.
55 /// </remarks> 55 /// </remarks>
56 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 56 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimulatorFeaturesModule")]
57 public class SimulatorFeaturesModule : ISharedRegionModule, ISimulatorFeaturesModule 57 public class SimulatorFeaturesModule : ISharedRegionModule, ISimulatorFeaturesModule
58 { 58 {
59// private static readonly ILog m_log = 59// private static readonly ILog m_log =
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
index 6aac591..3b0ccd7 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
@@ -50,7 +50,7 @@ using OpenSim.Capabilities.Handlers;
50 50
51namespace OpenSim.Region.ClientStack.Linden 51namespace OpenSim.Region.ClientStack.Linden
52{ 52{
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UploadBakedTextureModule")]
54 public class UploadBakedTextureModule : INonSharedRegionModule 54 public class UploadBakedTextureModule : INonSharedRegionModule
55 { 55 {
56// private static readonly ILog m_log = 56// private static readonly ILog m_log =
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 0caeddf..04cd474 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.ClientStack.Linden
49 /// <summary> 49 /// <summary>
50 /// This module implements both WebFetchInventoryDescendents and FetchInventoryDescendents2 capabilities. 50 /// This module implements both WebFetchInventoryDescendents and FetchInventoryDescendents2 capabilities.
51 /// </summary> 51 /// </summary>
52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WebFetchInvDescModule")]
53 public class WebFetchInvDescModule : INonSharedRegionModule 53 public class WebFetchInvDescModule : INonSharedRegionModule
54 { 54 {
55 struct aPollRequest 55 struct aPollRequest
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
index 1b8535c..e22670b 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
@@ -45,7 +45,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
45 public Packet Packet; 45 public Packet Packet;
46 46
47 /// <summary> 47 /// <summary>
48 /// Default constructor 48 /// No arg constructor.
49 /// </summary>
50 public IncomingPacket() {}
51
52 /// <summary>
53 /// Constructor
49 /// </summary> 54 /// </summary>
50 /// <param name="client">Reference to the client this packet came from</param> 55 /// <param name="client">Reference to the client this packet came from</param>
51 /// <param name="packet">Packet data</param> 56 /// <param name="packet">Packet data</param>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index ee28914..8e0b72f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -47,6 +47,7 @@ using OpenSim.Region.Framework.Scenes;
47using OpenSim.Services.Interfaces; 47using OpenSim.Services.Interfaces;
48using Timer = System.Timers.Timer; 48using Timer = System.Timers.Timer;
49using AssetLandmark = OpenSim.Framework.AssetLandmark; 49using AssetLandmark = OpenSim.Framework.AssetLandmark;
50using RegionFlags = OpenMetaverse.RegionFlags;
50using Nini.Config; 51using Nini.Config;
51 52
52using System.IO; 53using System.IO;
@@ -295,6 +296,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
295 public event MuteListEntryRemove OnRemoveMuteListEntry; 296 public event MuteListEntryRemove OnRemoveMuteListEntry;
296 public event GodlikeMessage onGodlikeMessage; 297 public event GodlikeMessage onGodlikeMessage;
297 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 298 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
299 public event GenericCall2 OnUpdateThrottles;
298 300
299 #endregion Events 301 #endregion Events
300 302
@@ -354,7 +356,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
354 private bool m_deliverPackets = true; 356 private bool m_deliverPackets = true;
355 private int m_animationSequenceNumber = 1; 357 private int m_animationSequenceNumber = 1;
356 private bool m_SendLogoutPacketWhenClosing = true; 358 private bool m_SendLogoutPacketWhenClosing = true;
357 private AgentUpdateArgs lastarg; 359
360 /// <summary>
361 /// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for
362 /// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it
363 /// is doing absolutely nothing.
364 /// </summary>
365 /// <remarks>
366 /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods
367 /// cannot retain a reference to it outside of that method.
368 /// </remarks>
369 private AgentUpdateArgs m_lastAgentUpdateArgs;
358 370
359 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 371 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
360 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 372 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -509,19 +521,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
509 /// </summary> 521 /// </summary>
510 public void Close() 522 public void Close()
511 { 523 {
512 Close(true); 524 Close(true, false);
513 } 525 }
514 526
515 /// <summary> 527 public void Close(bool sendStop, bool force)
516 /// Shut down the client view
517 /// </summary>
518 public void Close(bool sendStop)
519 { 528 {
520 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 529 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
521 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 530 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
522 lock (CloseSyncLock) 531 lock (CloseSyncLock)
523 { 532 {
524 if (!IsActive) 533 // 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
535 if (!IsActive && !force)
525 return; 536 return;
526 537
527 IsActive = false; 538 IsActive = false;
@@ -836,8 +847,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
836 OutPacket(mov, ThrottleOutPacketType.Unknown); 847 OutPacket(mov, ThrottleOutPacketType.Unknown);
837 } 848 }
838 849
839 public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, 850 public void SendChatMessage(
840 UUID fromAgentID, byte source, byte audible) 851 string message, byte type, Vector3 fromPos, string fromName,
852 UUID fromAgentID, UUID ownerID, byte source, byte audible)
841 { 853 {
842 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); 854 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
843 reply.ChatData.Audible = audible; 855 reply.ChatData.Audible = audible;
@@ -846,7 +858,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
846 reply.ChatData.SourceType = source; 858 reply.ChatData.SourceType = source;
847 reply.ChatData.Position = fromPos; 859 reply.ChatData.Position = fromPos;
848 reply.ChatData.FromName = Util.StringToBytes256(fromName); 860 reply.ChatData.FromName = Util.StringToBytes256(fromName);
849 reply.ChatData.OwnerID = fromAgentID; 861 reply.ChatData.OwnerID = ownerID;
850 reply.ChatData.SourceID = fromAgentID; 862 reply.ChatData.SourceID = fromAgentID;
851 863
852 OutPacket(reply, ThrottleOutPacketType.Unknown); 864 OutPacket(reply, ThrottleOutPacketType.Unknown);
@@ -3984,7 +3996,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3984 { 3996 {
3985 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3997 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3986 3998
3987 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3999 ImprovedTerseObjectUpdatePacket packet
4000 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3988 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4001 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3989 packet.RegionData.TimeDilation = timeDilation; 4002 packet.RegionData.TimeDilation = timeDilation;
3990 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4003 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
@@ -4029,7 +4042,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4029 { 4042 {
4030 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; 4043 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4031 4044
4032 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 4045 ImprovedTerseObjectUpdatePacket packet
4046 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4047 PacketType.ImprovedTerseObjectUpdate);
4033 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4048 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4034 packet.RegionData.TimeDilation = timeDilation; 4049 packet.RegionData.TimeDilation = timeDilation;
4035 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4050 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
@@ -4037,7 +4052,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4037 for (int i = 0; i < blocks.Count; i++) 4052 for (int i = 0; i < blocks.Count; i++)
4038 packet.ObjectData[i] = blocks[i]; 4053 packet.ObjectData[i] = blocks[i];
4039 4054
4040 OutPacket(packet, ThrottleOutPacketType.Task, true); 4055 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4041 } 4056 }
4042 4057
4043 #endregion Packet Sending 4058 #endregion Packet Sending
@@ -4534,7 +4549,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4534 { 4549 {
4535 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); 4550 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
4536 } 4551 }
4537 j = 0; 4552 j = 0;
4538 4553
4539 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; 4554 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4540 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; 4555 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
@@ -5038,7 +5053,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5038 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; 5053 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
5039 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; 5054 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
5040 5055
5041 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); 5056 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block
5057 = PacketPool.Instance.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
5058
5042 block.Data = data; 5059 block.Data = data;
5043 5060
5044 if (textureEntry != null && textureEntry.Length > 0) 5061 if (textureEntry != null && textureEntry.Length > 0)
@@ -5288,14 +5305,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5288 protected virtual void RegisterLocalPacketHandlers() 5305 protected virtual void RegisterLocalPacketHandlers()
5289 { 5306 {
5290 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); 5307 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout);
5308
5309 // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs
5310 // for each AgentUpdate packet.
5291 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); 5311 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
5312
5292 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); 5313 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
5293 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); 5314 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
5294 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); 5315 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
5295 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); 5316 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false);
5296 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); 5317 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false);
5297 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false); 5318 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest);
5298 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false); 5319 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest);
5299 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); 5320 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage);
5300 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); 5321 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest);
5301 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); 5322 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
@@ -5395,9 +5416,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5395 AddLocalPacketHandler(PacketType.RemoveTaskInventory, HandleRemoveTaskInventory); 5416 AddLocalPacketHandler(PacketType.RemoveTaskInventory, HandleRemoveTaskInventory);
5396 AddLocalPacketHandler(PacketType.MoveTaskInventory, HandleMoveTaskInventory); 5417 AddLocalPacketHandler(PacketType.MoveTaskInventory, HandleMoveTaskInventory);
5397 AddLocalPacketHandler(PacketType.RezScript, HandleRezScript); 5418 AddLocalPacketHandler(PacketType.RezScript, HandleRezScript);
5398 AddLocalPacketHandler(PacketType.MapLayerRequest, HandleMapLayerRequest, false); 5419 AddLocalPacketHandler(PacketType.MapLayerRequest, HandleMapLayerRequest);
5399 AddLocalPacketHandler(PacketType.MapBlockRequest, HandleMapBlockRequest, false); 5420 AddLocalPacketHandler(PacketType.MapBlockRequest, HandleMapBlockRequest);
5400 AddLocalPacketHandler(PacketType.MapNameRequest, HandleMapNameRequest, false); 5421 AddLocalPacketHandler(PacketType.MapNameRequest, HandleMapNameRequest);
5401 AddLocalPacketHandler(PacketType.TeleportLandmarkRequest, HandleTeleportLandmarkRequest); 5422 AddLocalPacketHandler(PacketType.TeleportLandmarkRequest, HandleTeleportLandmarkRequest);
5402 AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel); 5423 AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel);
5403 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest); 5424 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest);
@@ -5517,81 +5538,84 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5517 5538
5518 #region Scene/Avatar 5539 #region Scene/Avatar
5519 5540
5520 private bool HandleAgentUpdate(IClientAPI sener, Packet Pack) 5541 private bool HandleAgentUpdate(IClientAPI sener, Packet packet)
5521 { 5542 {
5522 if (OnAgentUpdate != null) 5543 if (OnAgentUpdate != null)
5523 { 5544 {
5524 bool update = false; 5545 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5525 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
5526 5546
5527 #region Packet Session and User Check 5547 #region Packet Session and User Check
5528 if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) 5548 if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId)
5549 {
5550 PacketPool.Instance.ReturnPacket(packet);
5529 return false; 5551 return false;
5552 }
5530 #endregion 5553 #endregion
5531 5554
5532 AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; 5555 bool update = false;
5533 5556 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
5534 // We can only check when we have something to check
5535 // against.
5536 5557
5537 if (lastarg != null) 5558 if (m_lastAgentUpdateArgs != null)
5538 { 5559 {
5560 // These should be ordered from most-likely to
5561 // least likely to change. I've made an initial
5562 // guess at that.
5539 update = 5563 update =
5540 ( 5564 (
5541 (x.BodyRotation != lastarg.BodyRotation) || 5565 (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) ||
5542 (x.CameraAtAxis != lastarg.CameraAtAxis) || 5566 (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) ||
5543 (x.CameraCenter != lastarg.CameraCenter) || 5567 (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) ||
5544 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5568 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) ||
5545 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5569 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) ||
5546 (x.ControlFlags != lastarg.ControlFlags) || 5570 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) ||
5547 (x.ControlFlags != 0) || 5571 (x.ControlFlags != 0) ||
5548 (x.Far != lastarg.Far) || 5572 (x.Far != m_lastAgentUpdateArgs.Far) ||
5549 (x.Flags != lastarg.Flags) || 5573 (x.Flags != m_lastAgentUpdateArgs.Flags) ||
5550 (x.State != lastarg.State) || 5574 (x.State != m_lastAgentUpdateArgs.State) ||
5551 (x.HeadRotation != lastarg.HeadRotation) || 5575 (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) ||
5552 (x.SessionID != lastarg.SessionID) || 5576 (x.SessionID != m_lastAgentUpdateArgs.SessionID) ||
5553 (x.AgentID != lastarg.AgentID) 5577 (x.AgentID != m_lastAgentUpdateArgs.AgentID)
5554 ); 5578 );
5555 } 5579 }
5556 else 5580 else
5557 { 5581 {
5582 m_lastAgentUpdateArgs = new AgentUpdateArgs();
5558 update = true; 5583 update = true;
5559 } 5584 }
5560 5585
5561 // These should be ordered from most-likely to
5562 // least likely to change. I've made an initial
5563 // guess at that.
5564
5565 if (update) 5586 if (update)
5566 { 5587 {
5567// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); 5588// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name);
5568 5589
5569 AgentUpdateArgs arg = new AgentUpdateArgs(); 5590 m_lastAgentUpdateArgs.AgentID = x.AgentID;
5570 arg.AgentID = x.AgentID; 5591 m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation;
5571 arg.BodyRotation = x.BodyRotation; 5592 m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
5572 arg.CameraAtAxis = x.CameraAtAxis; 5593 m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter;
5573 arg.CameraCenter = x.CameraCenter; 5594 m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
5574 arg.CameraLeftAxis = x.CameraLeftAxis; 5595 m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
5575 arg.CameraUpAxis = x.CameraUpAxis; 5596 m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags;
5576 arg.ControlFlags = x.ControlFlags; 5597 m_lastAgentUpdateArgs.Far = x.Far;
5577 arg.Far = x.Far; 5598 m_lastAgentUpdateArgs.Flags = x.Flags;
5578 arg.Flags = x.Flags; 5599 m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation;
5579 arg.HeadRotation = x.HeadRotation; 5600 m_lastAgentUpdateArgs.SessionID = x.SessionID;
5580 arg.SessionID = x.SessionID; 5601 m_lastAgentUpdateArgs.State = x.State;
5581 arg.State = x.State; 5602
5582 UpdateAgent handlerAgentUpdate = OnAgentUpdate; 5603 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5583 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; 5604 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5584 lastarg = arg; // save this set of arguments for nexttime 5605
5585 if (handlerPreAgentUpdate != null) 5606 if (handlerPreAgentUpdate != null)
5586 OnPreAgentUpdate(this, arg); 5607 OnPreAgentUpdate(this, m_lastAgentUpdateArgs);
5608
5587 if (handlerAgentUpdate != null) 5609 if (handlerAgentUpdate != null)
5588 OnAgentUpdate(this, arg); 5610 OnAgentUpdate(this, m_lastAgentUpdateArgs);
5589 5611
5590 handlerAgentUpdate = null; 5612 handlerAgentUpdate = null;
5591 handlerPreAgentUpdate = null; 5613 handlerPreAgentUpdate = null;
5592 } 5614 }
5593 } 5615 }
5594 5616
5617 PacketPool.Instance.ReturnPacket(packet);
5618
5595 return true; 5619 return true;
5596 } 5620 }
5597 5621
@@ -5963,7 +5987,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5963 msgpack.MessageBlock.ID, 5987 msgpack.MessageBlock.ID,
5964 msgpack.MessageBlock.Offline != 0 ? true : false, 5988 msgpack.MessageBlock.Offline != 0 ? true : false,
5965 msgpack.MessageBlock.Position, 5989 msgpack.MessageBlock.Position,
5966 msgpack.MessageBlock.BinaryBucket); 5990 msgpack.MessageBlock.BinaryBucket,
5991 true);
5967 5992
5968 handlerInstantMessage(this, im); 5993 handlerInstantMessage(this, im);
5969 } 5994 }
@@ -6729,6 +6754,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6729 #endregion 6754 #endregion
6730 6755
6731 m_udpClient.SetThrottles(atpack.Throttle.Throttles); 6756 m_udpClient.SetThrottles(atpack.Throttle.Throttles);
6757 GenericCall2 handler = OnUpdateThrottles;
6758 if (handler != null)
6759 {
6760 handler();
6761 }
6732 return true; 6762 return true;
6733 } 6763 }
6734 6764
@@ -9245,7 +9275,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9245 } 9275 }
9246 #endregion 9276 #endregion
9247 9277
9248 switch (Utils.BytesToString(messagePacket.MethodData.Method)) 9278 string method = Utils.BytesToString(messagePacket.MethodData.Method);
9279
9280 switch (method)
9249 { 9281 {
9250 case "getinfo": 9282 case "getinfo":
9251 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) 9283 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
@@ -9561,7 +9593,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9561 return true; 9593 return true;
9562 9594
9563 default: 9595 default:
9564 m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); 9596 m_log.WarnFormat(
9597 "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}",
9598 method, Name, Scene.Name);
9599
9600 for (int i = 0; i < messagePacket.ParamList.Length; i++)
9601 {
9602 EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i];
9603 string data = (string)Utils.BytesToString(block.Parameter);
9604 m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data);
9605 }
9606
9565 return true; 9607 return true;
9566 } 9608 }
9567 9609
@@ -11870,8 +11912,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11870 public void SetChildAgentThrottle(byte[] throttles) 11912 public void SetChildAgentThrottle(byte[] throttles)
11871 { 11913 {
11872 m_udpClient.SetThrottles(throttles); 11914 m_udpClient.SetThrottles(throttles);
11915 GenericCall2 handler = OnUpdateThrottles;
11916 if (handler != null)
11917 {
11918 handler();
11919 }
11920 }
11921
11922 /// <summary>
11923 /// Sets the throttles from values supplied by the client
11924 /// </summary>
11925 /// <param name="throttles"></param>
11926 public void SetAgentThrottleSilent(int throttle, int setting)
11927 {
11928 m_udpClient.ForceThrottleSetting(throttle,setting);
11929 //m_udpClient.SetThrottles(throttles);
11930
11873 } 11931 }
11874 11932
11933
11875 /// <summary> 11934 /// <summary>
11876 /// Get the current throttles for this client as a packed byte array 11935 /// Get the current throttles for this client as a packed byte array
11877 /// </summary> 11936 /// </summary>
@@ -11949,7 +12008,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11949 logPacket = false; 12008 logPacket = false;
11950 12009
11951 if (DebugPacketLevel <= 50 12010 if (DebugPacketLevel <= 50
11952 & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) 12011 && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
11953 logPacket = false; 12012 logPacket = false;
11954 12013
11955 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) 12014 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
@@ -12023,8 +12082,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12023 12082
12024 if (!ProcessPacketMethod(packet)) 12083 if (!ProcessPacketMethod(packet))
12025 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 12084 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
12026
12027 PacketPool.Instance.ReturnPacket(packet);
12028 } 12085 }
12029 12086
12030 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) 12087 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
@@ -12193,7 +12250,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12193 { 12250 {
12194 Kick(reason); 12251 Kick(reason);
12195 Thread.Sleep(1000); 12252 Thread.Sleep(1000);
12196 Close(); 12253 Disconnect();
12197 } 12254 }
12198 12255
12199 public void Disconnect() 12256 public void Disconnect()
@@ -12481,7 +12538,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12481 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 12538 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
12482 12539
12483 12540
12484 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 12541 ImprovedTerseObjectUpdatePacket packet
12542 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
12543 PacketType.ImprovedTerseObjectUpdate);
12544
12485 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 12545 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
12486 packet.RegionData.TimeDilation = timeDilation; 12546 packet.RegionData.TimeDilation = timeDilation;
12487 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; 12547 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index c472176..f675377 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -682,6 +682,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
682 if (m_nextOnQueueEmpty == 0) 682 if (m_nextOnQueueEmpty == 0)
683 m_nextOnQueueEmpty = 1; 683 m_nextOnQueueEmpty = 1;
684 } 684 }
685 internal void ForceThrottleSetting(int throttle, int setting)
686 {
687 m_throttleCategories[throttle].RequestedDripRate = Math.Max(setting, LLUDPServer.MTU); ;
688 }
685 689
686 /// <summary> 690 /// <summary>
687 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a 691 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index dac3306..fc4e1b2 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -37,6 +37,7 @@ using log4net;
37using Nini.Config; 37using Nini.Config;
38using OpenMetaverse.Packets; 38using OpenMetaverse.Packets;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Console;
40using OpenSim.Framework.Monitoring; 41using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
42using OpenMetaverse; 43using OpenMetaverse;
@@ -69,6 +70,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
69 public void AddScene(IScene scene) 70 public void AddScene(IScene scene)
70 { 71 {
71 m_udpServer.AddScene(scene); 72 m_udpServer.AddScene(scene);
73
74 StatsManager.RegisterStat(
75 new Stat(
76 "IncomingPacketsProcessedCount",
77 "Number of inbound UDP packets processed",
78 "Number of inbound UDP packets processed",
79 "",
80 "clientstack",
81 scene.Name,
82 StatType.Pull,
83 MeasuresOfInterest.AverageChangeOverTime,
84 stat => stat.Value = m_udpServer.IncomingPacketsProcessed,
85 StatVerbosity.Debug));
72 } 86 }
73 87
74 public bool HandlesRegion(Location x) 88 public bool HandlesRegion(Location x)
@@ -100,9 +114,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
100 114
101 /// <summary>The measured resolution of Environment.TickCount</summary> 115 /// <summary>The measured resolution of Environment.TickCount</summary>
102 public readonly float TickCountResolution; 116 public readonly float TickCountResolution;
117
103 /// <summary>Number of prim updates to put on the queue each time the 118 /// <summary>Number of prim updates to put on the queue each time the
104 /// OnQueueEmpty event is triggered for updates</summary> 119 /// OnQueueEmpty event is triggered for updates</summary>
105 public readonly int PrimUpdatesPerCallback; 120 public readonly int PrimUpdatesPerCallback;
121
106 /// <summary>Number of texture packets to put on the queue each time the 122 /// <summary>Number of texture packets to put on the queue each time the
107 /// OnQueueEmpty event is triggered for textures</summary> 123 /// OnQueueEmpty event is triggered for textures</summary>
108 public readonly int TextureSendLimit; 124 public readonly int TextureSendLimit;
@@ -124,28 +140,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
124 140
125 /// <summary>Manages authentication for agent circuits</summary> 141 /// <summary>Manages authentication for agent circuits</summary>
126 private AgentCircuitManager m_circuitManager; 142 private AgentCircuitManager m_circuitManager;
143
127 /// <summary>Reference to the scene this UDP server is attached to</summary> 144 /// <summary>Reference to the scene this UDP server is attached to</summary>
128 protected Scene m_scene; 145 protected Scene m_scene;
146
129 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 147 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
130 private Location m_location; 148 private Location m_location;
149
131 /// <summary>The size of the receive buffer for the UDP socket. This value 150 /// <summary>The size of the receive buffer for the UDP socket. This value
132 /// is passed up to the operating system and used in the system networking 151 /// is passed up to the operating system and used in the system networking
133 /// stack. Use zero to leave this value as the default</summary> 152 /// stack. Use zero to leave this value as the default</summary>
134 private int m_recvBufferSize; 153 private int m_recvBufferSize;
154
135 /// <summary>Flag to process packets asynchronously or synchronously</summary> 155 /// <summary>Flag to process packets asynchronously or synchronously</summary>
136 private bool m_asyncPacketHandling; 156 private bool m_asyncPacketHandling;
157
137 /// <summary>Tracks whether or not a packet was sent each round so we know 158 /// <summary>Tracks whether or not a packet was sent each round so we know
138 /// whether or not to sleep</summary> 159 /// whether or not to sleep</summary>
139 private bool m_packetSent; 160 private bool m_packetSent;
140 161
141 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> 162 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary>
142 private int m_elapsedMSSinceLastStatReport = 0; 163 private int m_elapsedMSSinceLastStatReport = 0;
164
143 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> 165 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary>
144 private int m_tickLastOutgoingPacketHandler; 166 private int m_tickLastOutgoingPacketHandler;
167
145 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> 168 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary>
146 private int m_elapsedMSOutgoingPacketHandler; 169 private int m_elapsedMSOutgoingPacketHandler;
170
147 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> 171 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary>
148 private int m_elapsed100MSOutgoingPacketHandler; 172 private int m_elapsed100MSOutgoingPacketHandler;
173
149 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> 174 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary>
150 private int m_elapsed500MSOutgoingPacketHandler; 175 private int m_elapsed500MSOutgoingPacketHandler;
151 176
@@ -159,6 +184,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
159 protected bool m_sendPing; 184 protected bool m_sendPing;
160 185
161 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 186 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
187 private Pool<IncomingPacket> m_incomingPacketPool;
188
189 /// <summary>
190 /// Stat for number of packets in the main pool awaiting use.
191 /// </summary>
192 private Stat m_poolCountStat;
193
194 /// <summary>
195 /// Stat for number of packets in the inbound packet pool awaiting use.
196 /// </summary>
197 private Stat m_incomingPacketPoolStat;
162 198
163 private int m_defaultRTO = 0; 199 private int m_defaultRTO = 0;
164 private int m_maxRTO = 0; 200 private int m_maxRTO = 0;
@@ -180,7 +216,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
180 /// </summary> 216 /// </summary>
181 private IClientAPI m_currentIncomingClient; 217 private IClientAPI m_currentIncomingClient;
182 218
183 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) 219 public LLUDPServer(
220 IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port,
221 IConfigSource configSource, AgentCircuitManager circuitManager)
184 : base(listenIP, (int)port) 222 : base(listenIP, (int)port)
185 { 223 {
186 #region Environment.TickCount Measurement 224 #region Environment.TickCount Measurement
@@ -202,6 +240,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
202 240
203 m_circuitManager = circuitManager; 241 m_circuitManager = circuitManager;
204 int sceneThrottleBps = 0; 242 int sceneThrottleBps = 0;
243 bool usePools = false;
205 244
206 IConfig config = configSource.Configs["ClientStack.LindenUDP"]; 245 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
207 if (config != null) 246 if (config != null)
@@ -227,6 +266,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
227 m_pausedAckTimeout = 1000 * 300; // 5 minutes 266 m_pausedAckTimeout = 1000 * 300; // 5 minutes
228 } 267 }
229 268
269 // FIXME: This actually only needs to be done once since the PacketPool is shared across all servers.
270 // However, there is no harm in temporarily doing it multiple times.
271 IConfig packetConfig = configSource.Configs["PacketPool"];
272 if (packetConfig != null)
273 {
274 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
275 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
276 usePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", usePools);
277 }
278
230 #region BinaryStats 279 #region BinaryStats
231 config = configSource.Configs["Statistics.Binary"]; 280 config = configSource.Configs["Statistics.Binary"];
232 m_shouldCollectStats = false; 281 m_shouldCollectStats = false;
@@ -254,20 +303,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
254 303
255 m_throttle = new TokenBucket(null, sceneThrottleBps); 304 m_throttle = new TokenBucket(null, sceneThrottleBps);
256 ThrottleRates = new ThrottleRates(configSource); 305 ThrottleRates = new ThrottleRates(configSource);
306
307 if (usePools)
308 EnablePools();
257 } 309 }
258 310
259 public void Start() 311 public void Start()
260 { 312 {
261 if (m_scene == null) 313 StartInbound();
262 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); 314 StartOutbound();
315
316 m_elapsedMSSinceLastStatReport = Environment.TickCount;
317 }
263 318
319 private void StartInbound()
320 {
264 m_log.InfoFormat( 321 m_log.InfoFormat(
265 "[LLUDPSERVER]: Starting the LLUDP server in {0} mode", 322 "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}",
266 m_asyncPacketHandling ? "asynchronous" : "synchronous"); 323 m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools);
267 324
268 base.Start(m_recvBufferSize, m_asyncPacketHandling); 325 base.StartInbound(m_recvBufferSize, m_asyncPacketHandling);
269 326
270 // Start the packet processing threads 327 // This thread will process the packets received that are placed on the packetInbox
271 Watchdog.StartThread( 328 Watchdog.StartThread(
272 IncomingPacketHandler, 329 IncomingPacketHandler,
273 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), 330 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
@@ -276,6 +333,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
276 true, 333 true,
277 GetWatchdogIncomingAlarmData, 334 GetWatchdogIncomingAlarmData,
278 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 335 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
336 }
337
338 private new void StartOutbound()
339 {
340 m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server");
341
342 base.StartOutbound();
279 343
280 Watchdog.StartThread( 344 Watchdog.StartThread(
281 OutgoingPacketHandler, 345 OutgoingPacketHandler,
@@ -285,8 +349,90 @@ namespace OpenSim.Region.ClientStack.LindenUDP
285 true, 349 true,
286 GetWatchdogOutgoingAlarmData, 350 GetWatchdogOutgoingAlarmData,
287 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 351 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
352 }
288 353
289 m_elapsedMSSinceLastStatReport = Environment.TickCount; 354 public void Stop()
355 {
356 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
357 base.StopOutbound();
358 base.StopInbound();
359 }
360
361 protected override bool EnablePools()
362 {
363 if (!UsePools)
364 {
365 base.EnablePools();
366
367 m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500);
368
369 return true;
370 }
371
372 return false;
373 }
374
375 protected override bool DisablePools()
376 {
377 if (UsePools)
378 {
379 base.DisablePools();
380
381 StatsManager.DeregisterStat(m_incomingPacketPoolStat);
382
383 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
384
385 return true;
386 }
387
388 return false;
389 }
390
391 /// <summary>
392 /// This is a seperate method so that it can be called once we have an m_scene to distinguish different scene
393 /// stats.
394 /// </summary>
395 private void EnablePoolStats()
396 {
397 m_poolCountStat
398 = new Stat(
399 "UDPPacketBufferPoolCount",
400 "Objects within the UDPPacketBuffer pool",
401 "The number of objects currently stored within the UDPPacketBuffer pool",
402 "",
403 "clientstack",
404 m_scene.Name,
405 StatType.Pull,
406 stat => stat.Value = Pool.Count,
407 StatVerbosity.Debug);
408
409 StatsManager.RegisterStat(m_poolCountStat);
410
411 m_incomingPacketPoolStat
412 = new Stat(
413 "IncomingPacketPoolCount",
414 "Objects within incoming packet pool",
415 "The number of objects currently stored within the incoming packet pool",
416 "",
417 "clientstack",
418 m_scene.Name,
419 StatType.Pull,
420 stat => stat.Value = m_incomingPacketPool.Count,
421 StatVerbosity.Debug);
422
423 StatsManager.RegisterStat(m_incomingPacketPoolStat);
424 }
425
426 /// <summary>
427 /// Disables pool stats.
428 /// </summary>
429 private void DisablePoolStats()
430 {
431 StatsManager.DeregisterStat(m_poolCountStat);
432 m_poolCountStat = null;
433
434 StatsManager.DeregisterStat(m_incomingPacketPoolStat);
435 m_incomingPacketPoolStat = null;
290 } 436 }
291 437
292 /// <summary> 438 /// <summary>
@@ -311,12 +457,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
311 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); 457 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
312 } 458 }
313 459
314 public new void Stop()
315 {
316 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
317 base.Stop();
318 }
319
320 public void AddScene(IScene scene) 460 public void AddScene(IScene scene)
321 { 461 {
322 if (m_scene != null) 462 if (m_scene != null)
@@ -333,6 +473,182 @@ namespace OpenSim.Region.ClientStack.LindenUDP
333 473
334 m_scene = (Scene)scene; 474 m_scene = (Scene)scene;
335 m_location = new Location(m_scene.RegionInfo.RegionHandle); 475 m_location = new Location(m_scene.RegionInfo.RegionHandle);
476
477 // XXX: These stats are also pool stats but we register them separately since they are currently not
478 // turned on and off by EnablePools()/DisablePools()
479 StatsManager.RegisterStat(
480 new PercentageStat(
481 "PacketsReused",
482 "Packets reused",
483 "Number of packets reused out of all requests to the packet pool",
484 "clientstack",
485 m_scene.Name,
486 StatType.Pull,
487 stat =>
488 { PercentageStat pstat = (PercentageStat)stat;
489 pstat.Consequent = PacketPool.Instance.PacketsRequested;
490 pstat.Antecedent = PacketPool.Instance.PacketsReused; },
491 StatVerbosity.Debug));
492
493 StatsManager.RegisterStat(
494 new PercentageStat(
495 "PacketDataBlocksReused",
496 "Packet data blocks reused",
497 "Number of data blocks reused out of all requests to the packet pool",
498 "clientstack",
499 m_scene.Name,
500 StatType.Pull,
501 stat =>
502 { PercentageStat pstat = (PercentageStat)stat;
503 pstat.Consequent = PacketPool.Instance.BlocksRequested;
504 pstat.Antecedent = PacketPool.Instance.BlocksReused; },
505 StatVerbosity.Debug));
506
507 StatsManager.RegisterStat(
508 new Stat(
509 "PacketsPoolCount",
510 "Objects within the packet pool",
511 "The number of objects currently stored within the packet pool",
512 "",
513 "clientstack",
514 m_scene.Name,
515 StatType.Pull,
516 stat => stat.Value = PacketPool.Instance.PacketsPooled,
517 StatVerbosity.Debug));
518
519 StatsManager.RegisterStat(
520 new Stat(
521 "PacketDataBlocksPoolCount",
522 "Objects within the packet data block pool",
523 "The number of objects currently stored within the packet data block pool",
524 "",
525 "clientstack",
526 m_scene.Name,
527 StatType.Pull,
528 stat => stat.Value = PacketPool.Instance.BlocksPooled,
529 StatVerbosity.Debug));
530
531 // We delay enabling pool stats to AddScene() instead of Initialize() so that we can distinguish pool stats by
532 // scene name
533 if (UsePools)
534 EnablePoolStats();
535
536 MainConsole.Instance.Commands.AddCommand(
537 "Debug",
538 false,
539 "debug lludp start",
540 "debug lludp start <in|out|all>",
541 "Control LLUDP packet processing.",
542 "No effect if packet processing has already started.\n"
543 + "in - start inbound processing.\n"
544 + "out - start outbound processing.\n"
545 + "all - start in and outbound processing.\n",
546 HandleStartCommand);
547
548 MainConsole.Instance.Commands.AddCommand(
549 "Debug",
550 false,
551 "debug lludp stop",
552 "debug lludp stop <in|out|all>",
553 "Stop LLUDP packet processing.",
554 "No effect if packet processing has already stopped.\n"
555 + "in - stop inbound processing.\n"
556 + "out - stop outbound processing.\n"
557 + "all - stop in and outbound processing.\n",
558 HandleStopCommand);
559
560 MainConsole.Instance.Commands.AddCommand(
561 "Debug",
562 false,
563 "debug lludp pool",
564 "debug lludp pool <on|off>",
565 "Turn object pooling within the lludp component on or off.",
566 HandlePoolCommand);
567
568 MainConsole.Instance.Commands.AddCommand(
569 "Debug",
570 false,
571 "debug lludp status",
572 "debug lludp status",
573 "Return status of LLUDP packet processing.",
574 HandleStatusCommand);
575 }
576
577 private void HandleStartCommand(string module, string[] args)
578 {
579 if (args.Length != 4)
580 {
581 MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>");
582 return;
583 }
584
585 string subCommand = args[3];
586
587 if (subCommand == "in" || subCommand == "all")
588 StartInbound();
589
590 if (subCommand == "out" || subCommand == "all")
591 StartOutbound();
592 }
593
594 private void HandleStopCommand(string module, string[] args)
595 {
596 if (args.Length != 4)
597 {
598 MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>");
599 return;
600 }
601
602 string subCommand = args[3];
603
604 if (subCommand == "in" || subCommand == "all")
605 StopInbound();
606
607 if (subCommand == "out" || subCommand == "all")
608 StopOutbound();
609 }
610
611 private void HandlePoolCommand(string module, string[] args)
612 {
613 if (args.Length != 4)
614 {
615 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
616 return;
617 }
618
619 string enabled = args[3];
620
621 if (enabled == "on")
622 {
623 if (EnablePools())
624 {
625 EnablePoolStats();
626 MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name);
627 }
628 }
629 else if (enabled == "off")
630 {
631 if (DisablePools())
632 {
633 DisablePoolStats();
634 MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name);
635 }
636 }
637 else
638 {
639 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
640 }
641 }
642
643 private void HandleStatusCommand(string module, string[] args)
644 {
645 MainConsole.Instance.OutputFormat(
646 "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled");
647
648 MainConsole.Instance.OutputFormat(
649 "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled");
650
651 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off");
336 } 652 }
337 653
338 public bool HandlesRegion(Location x) 654 public bool HandlesRegion(Location x)
@@ -416,6 +732,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
416 byte[] data = packet.ToBytes(); 732 byte[] data = packet.ToBytes();
417 SendPacketData(udpClient, data, packet.Type, category, method); 733 SendPacketData(udpClient, data, packet.Type, category, method);
418 } 734 }
735
736 PacketPool.Instance.ReturnPacket(packet);
419 } 737 }
420 738
421 /// <summary> 739 /// <summary>
@@ -700,7 +1018,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
700 LLUDPClient udpClient = null; 1018 LLUDPClient udpClient = null;
701 Packet packet = null; 1019 Packet packet = null;
702 int packetEnd = buffer.DataLength - 1; 1020 int packetEnd = buffer.DataLength - 1;
703 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; 1021 IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint;
704 1022
705 #region Decoding 1023 #region Decoding
706 1024
@@ -710,7 +1028,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
710// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", 1028// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
711// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1029// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
712 1030
713 return; // Drop undersizd packet 1031 return; // Drop undersized packet
714 } 1032 }
715 1033
716 int headerLen = 7; 1034 int headerLen = 7;
@@ -733,7 +1051,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
733 1051
734 try 1052 try
735 { 1053 {
736 packet = Packet.BuildPacket(buffer.Data, ref packetEnd, 1054// packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
1055// // Only allocate a buffer for zerodecoding if the packet is zerocoded
1056// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
1057 // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we
1058 // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all
1059 // bytes are copied out).
1060 packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd,
737 // Only allocate a buffer for zerodecoding if the packet is zerocoded 1061 // Only allocate a buffer for zerodecoding if the packet is zerocoded
738 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 1062 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
739 } 1063 }
@@ -748,11 +1072,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
748 1072
749 return; // Drop short packet 1073 return; // Drop short packet
750 } 1074 }
751 catch(Exception e) 1075 catch (Exception e)
752 { 1076 {
753 if (m_malformedCount < 100) 1077 if (m_malformedCount < 100)
754 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); 1078 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
1079
755 m_malformedCount++; 1080 m_malformedCount++;
1081
756 if ((m_malformedCount % 100000) == 0) 1082 if ((m_malformedCount % 100000) == 0)
757 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); 1083 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount);
758 } 1084 }
@@ -772,7 +1098,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
772 1098
773 // If there is already a client for this endpoint, don't process UseCircuitCode 1099 // If there is already a client for this endpoint, don't process UseCircuitCode
774 IClientAPI client = null; 1100 IClientAPI client = null;
775 if (!m_scene.TryGetClient(address, out client)) 1101 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
776 { 1102 {
777 // UseCircuitCode handling 1103 // UseCircuitCode handling
778 if (packet.Type == PacketType.UseCircuitCode) 1104 if (packet.Type == PacketType.UseCircuitCode)
@@ -780,13 +1106,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
780 // And if there is a UseCircuitCode pending, also drop it 1106 // And if there is a UseCircuitCode pending, also drop it
781 lock (m_pendingCache) 1107 lock (m_pendingCache)
782 { 1108 {
783 if (m_pendingCache.Contains(address)) 1109 if (m_pendingCache.Contains(endPoint))
784 return; 1110 return;
785 1111
786 m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60); 1112 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
787 } 1113 }
788 1114
789 object[] array = new object[] { buffer, packet }; 1115 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1116 // buffer.
1117 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
790 1118
791 Util.FireAndForget(HandleUseCircuitCode, array); 1119 Util.FireAndForget(HandleUseCircuitCode, array);
792 1120
@@ -798,7 +1126,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
798 lock (m_pendingCache) 1126 lock (m_pendingCache)
799 { 1127 {
800 Queue<UDPPacketBuffer> queue; 1128 Queue<UDPPacketBuffer> queue;
801 if (m_pendingCache.TryGetValue(address, out queue)) 1129 if (m_pendingCache.TryGetValue(endPoint, out queue))
802 { 1130 {
803 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); 1131 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
804 queue.Enqueue(buffer); 1132 queue.Enqueue(buffer);
@@ -834,6 +1162,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
834 // Handle appended ACKs 1162 // Handle appended ACKs
835 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 1163 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
836 { 1164 {
1165// m_log.DebugFormat(
1166// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
1167// packet.Header.AckList.Length, client.Name, m_scene.Name);
1168
837 for (int i = 0; i < packet.Header.AckList.Length; i++) 1169 for (int i = 0; i < packet.Header.AckList.Length; i++)
838 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); 1170 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
839 } 1171 }
@@ -843,6 +1175,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
843 { 1175 {
844 PacketAckPacket ackPacket = (PacketAckPacket)packet; 1176 PacketAckPacket ackPacket = (PacketAckPacket)packet;
845 1177
1178// m_log.DebugFormat(
1179// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
1180// ackPacket.Packets.Length, client.Name, m_scene.Name);
1181
846 for (int i = 0; i < ackPacket.Packets.Length; i++) 1182 for (int i = 0; i < ackPacket.Packets.Length; i++)
847 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); 1183 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
848 1184
@@ -856,6 +1192,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
856 1192
857 if (packet.Header.Reliable) 1193 if (packet.Header.Reliable)
858 { 1194 {
1195// m_log.DebugFormat(
1196// "[LLUDPSERVER]: Adding ack request for {0} {1} from {2} in {3}",
1197// packet.Type, packet.Header.Sequence, client.Name, m_scene.Name);
1198
859 udpClient.PendingAcks.Enqueue(packet.Header.Sequence); 1199 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
860 1200
861 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 1201 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
@@ -902,6 +1242,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
902 1242
903 if (packet.Type == PacketType.StartPingCheck) 1243 if (packet.Type == PacketType.StartPingCheck)
904 { 1244 {
1245// m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name);
1246
905 // We don't need to do anything else with ping checks 1247 // We don't need to do anything else with ping checks
906 StartPingCheckPacket startPing = (StartPingCheckPacket)packet; 1248 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
907 CompletePing(udpClient, startPing.PingID.PingID); 1249 CompletePing(udpClient, startPing.PingID.PingID);
@@ -921,13 +1263,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
921 1263
922 #endregion Ping Check Handling 1264 #endregion Ping Check Handling
923 1265
1266 IncomingPacket incomingPacket;
1267
924 // Inbox insertion 1268 // Inbox insertion
925 if (packet.Type == PacketType.AgentUpdate || 1269 if (UsePools)
926 packet.Type == PacketType.ChatFromViewer) 1270 {
927 packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet)); 1271 incomingPacket = m_incomingPacketPool.GetObject();
1272 incomingPacket.Client = (LLClientView)client;
1273 incomingPacket.Packet = packet;
1274 }
1275 else
1276 {
1277 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1278 }
1279
1280 if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1281 incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1282 packetInbox.EnqueueHigh(incomingPacket);
928 else 1283 else
929 packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet)); 1284 packetInbox.EnqueueLow(incomingPacket);
930// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
931 } 1285 }
932 1286
933 #region BinaryStats 1287 #region BinaryStats
@@ -1013,21 +1367,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1013 1367
1014 private void HandleUseCircuitCode(object o) 1368 private void HandleUseCircuitCode(object o)
1015 { 1369 {
1016 IPEndPoint remoteEndPoint = null; 1370 IPEndPoint endPoint = null;
1017 IClientAPI client = null; 1371 IClientAPI client = null;
1018 1372
1019 try 1373 try
1020 { 1374 {
1021 // DateTime startTime = DateTime.Now; 1375 // DateTime startTime = DateTime.Now;
1022 object[] array = (object[])o; 1376 object[] array = (object[])o;
1023 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; 1377 endPoint = (IPEndPoint)array[0];
1024 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 1378 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
1025 1379
1026 m_log.DebugFormat( 1380 m_log.DebugFormat(
1027 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", 1381 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
1028 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint); 1382 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint);
1029
1030 remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
1031 1383
1032 AuthenticateResponse sessionInfo; 1384 AuthenticateResponse sessionInfo;
1033 if (IsClientAuthorized(uccp, out sessionInfo)) 1385 if (IsClientAuthorized(uccp, out sessionInfo))
@@ -1038,13 +1390,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1038 uccp.CircuitCode.Code, 1390 uccp.CircuitCode.Code,
1039 uccp.CircuitCode.ID, 1391 uccp.CircuitCode.ID,
1040 uccp.CircuitCode.SessionID, 1392 uccp.CircuitCode.SessionID,
1041 remoteEndPoint, 1393 endPoint,
1042 sessionInfo); 1394 sessionInfo);
1043 1395
1044 // Send ack straight away to let the viewer know that the connection is active. 1396 // Send ack straight away to let the viewer know that the connection is active.
1045 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use 1397 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use
1046 // circuit code to the existing child agent. This is not particularly obvious. 1398 // circuit code to the existing child agent. This is not particularly obvious.
1047 SendAckImmediate(remoteEndPoint, uccp.Header.Sequence); 1399 SendAckImmediate(endPoint, uccp.Header.Sequence);
1048 1400
1049 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1401 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1050 if (client != null) 1402 if (client != null)
@@ -1058,12 +1410,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1058 1410
1059 lock (m_pendingCache) 1411 lock (m_pendingCache)
1060 { 1412 {
1061 if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue)) 1413 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1062 { 1414 {
1063 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); 1415 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1064 return; 1416 return;
1065 } 1417 }
1066 m_pendingCache.Remove(remoteEndPoint); 1418 m_pendingCache.Remove(endPoint);
1067 } 1419 }
1068 1420
1069 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); 1421 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
@@ -1081,9 +1433,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1081 // Don't create clients for unauthorized requesters. 1433 // Don't create clients for unauthorized requesters.
1082 m_log.WarnFormat( 1434 m_log.WarnFormat(
1083 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1435 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1084 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); 1436 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1085 lock (m_pendingCache) 1437 lock (m_pendingCache)
1086 m_pendingCache.Remove(remoteEndPoint); 1438 m_pendingCache.Remove(endPoint);
1087 } 1439 }
1088 1440
1089 // m_log.DebugFormat( 1441 // m_log.DebugFormat(
@@ -1095,7 +1447,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1095 { 1447 {
1096 m_log.ErrorFormat( 1448 m_log.ErrorFormat(
1097 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", 1449 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
1098 remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a", 1450 endPoint != null ? endPoint.ToString() : "n/a",
1099 client != null ? client.Name : "unknown", 1451 client != null ? client.Name : "unknown",
1100 client != null ? client.AgentId.ToString() : "unknown", 1452 client != null ? client.AgentId.ToString() : "unknown",
1101 e.Message, 1453 e.Message,
@@ -1160,20 +1512,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1160 { 1512 {
1161 IClientAPI client = null; 1513 IClientAPI client = null;
1162 1514
1163 // In priciple there shouldn't be more than one thread here, ever. 1515 // We currently synchronize this code across the whole scene to avoid issues such as
1164 // But in case that happens, we need to synchronize this piece of code 1516 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done
1165 // because it's too important 1517 // consistently, this lock could probably be removed.
1166 lock (this) 1518 lock (this)
1167 { 1519 {
1168 if (!m_scene.TryGetClient(agentID, out client)) 1520 if (!m_scene.TryGetClient(agentID, out client))
1169 { 1521 {
1170 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 1522 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
1171 1523
1172 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1524 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1173 client.OnLogout += LogoutHandler; 1525 client.OnLogout += LogoutHandler;
1174 1526
1175 ((LLClientView)client).DisableFacelights = m_disableFacelights; 1527 ((LLClientView)client).DisableFacelights = m_disableFacelights;
1176 1528
1177 client.Start(); 1529 client.Start();
1178 } 1530 }
1179 } 1531 }
@@ -1212,7 +1564,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1212 // on to en-US to avoid number parsing issues 1564 // on to en-US to avoid number parsing issues
1213 Culture.SetCurrentCulture(); 1565 Culture.SetCurrentCulture();
1214 1566
1215 while (base.IsRunning) 1567 while (IsRunningInbound)
1216 { 1568 {
1217 m_scene.ThreadAlive(1); 1569 m_scene.ThreadAlive(1);
1218 try 1570 try
@@ -1228,7 +1580,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1228 } 1580 }
1229 1581
1230 if (packetInbox.Dequeue(100, ref incomingPacket)) 1582 if (packetInbox.Dequeue(100, ref incomingPacket))
1583 {
1231 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); 1584 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket);
1585
1586 if (UsePools)
1587 m_incomingPacketPool.ReturnObject(incomingPacket);
1588 }
1232 } 1589 }
1233 catch (Exception ex) 1590 catch (Exception ex)
1234 { 1591 {
@@ -1255,7 +1612,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1255 // Action generic every round 1612 // Action generic every round
1256 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; 1613 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
1257 1614
1258 while (base.IsRunning) 1615 while (base.IsRunningOutbound)
1259 { 1616 {
1260 m_scene.ThreadAlive(2); 1617 m_scene.ThreadAlive(2);
1261 try 1618 try
@@ -1383,6 +1740,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1383 private int npacksSent = 0; 1740 private int npacksSent = 0;
1384 private int npackNotSent = 0; 1741 private int npackNotSent = 0;
1385 1742
1743 /// <summary>
1744 /// Number of inbound packets processed since startup.
1745 /// </summary>
1746 public long IncomingPacketsProcessed { get; private set; }
1747
1386 private void MonitoredClientOutgoingPacketHandler(IClientAPI client) 1748 private void MonitoredClientOutgoingPacketHandler(IClientAPI client)
1387 { 1749 {
1388 nticks++; 1750 nticks++;
@@ -1442,7 +1804,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1442 npacksSent++; 1804 npacksSent++;
1443 } 1805 }
1444 else 1806 else
1807 {
1445 npackNotSent++; 1808 npackNotSent++;
1809 }
1446 1810
1447 watch2.Stop(); 1811 watch2.Stop();
1448 avgDequeueTicks = (nticks - 1) / (float)nticks * avgDequeueTicks + (watch2.ElapsedTicks / (float)nticks); 1812 avgDequeueTicks = (nticks - 1) / (float)nticks * avgDequeueTicks + (watch2.ElapsedTicks / (float)nticks);
@@ -1450,7 +1814,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1450 1814
1451 } 1815 }
1452 else 1816 else
1817 {
1453 m_log.WarnFormat("[LLUDPSERVER]: Client is not connected"); 1818 m_log.WarnFormat("[LLUDPSERVER]: Client is not connected");
1819 }
1454 } 1820 }
1455 } 1821 }
1456 catch (Exception ex) 1822 catch (Exception ex)
@@ -1514,6 +1880,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1514// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1880// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1515// packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1881// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1516// } 1882// }
1883
1884 IncomingPacketsProcessed++;
1517 } 1885 }
1518 1886
1519 protected void LogoutHandler(IClientAPI client) 1887 protected void LogoutHandler(IClientAPI client)
@@ -1523,7 +1891,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1523 if (!client.IsLoggingOut) 1891 if (!client.IsLoggingOut)
1524 { 1892 {
1525 client.IsLoggingOut = true; 1893 client.IsLoggingOut = true;
1526 client.Close(false); 1894 client.Close(false, false);
1527 } 1895 }
1528 } 1896 }
1529 } 1897 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index cfe7c9d..2aeb4cc 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -30,6 +30,8 @@ using System.Net;
30using System.Net.Sockets; 30using System.Net.Sockets;
31using System.Threading; 31using System.Threading;
32using log4net; 32using log4net;
33using OpenSim.Framework;
34using OpenSim.Framework.Monitoring;
33 35
34namespace OpenMetaverse 36namespace OpenMetaverse
35{ 37{
@@ -58,17 +60,29 @@ namespace OpenMetaverse
58 /// <summary>Flag to process packets asynchronously or synchronously</summary> 60 /// <summary>Flag to process packets asynchronously or synchronously</summary>
59 private bool m_asyncPacketHandling; 61 private bool m_asyncPacketHandling;
60 62
61 /// <summary>The all important shutdown flag</summary> 63 /// <summary>
62 private volatile bool m_shutdownFlag = true; 64 /// Are we to use object pool(s) to reduce memory churn when receiving data?
65 /// </summary>
66 public bool UsePools { get; protected set; }
67
68 /// <summary>
69 /// Pool to use for handling data. May be null if UsePools = false;
70 /// </summary>
71 protected OpenSim.Framework.Pool<UDPPacketBuffer> Pool { get; private set; }
72
73 /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary>
74 public bool IsRunningInbound { get; private set; }
63 75
64 /// <summary>Returns true if the server is currently listening, otherwise false</summary> 76 /// <summary>Returns true if the server is currently sending outbound packets, otherwise false</summary>
65 public bool IsRunning { get { return !m_shutdownFlag; } } 77 /// <remarks>If IsRunningOut = false, then any request to send a packet is simply dropped.</remarks>
78 public bool IsRunningOutbound { get; private set; }
66 79
67 /// <summary> 80 /// <summary>
68 /// Default constructor 81 /// Default constructor
69 /// </summary> 82 /// </summary>
70 /// <param name="bindAddress">Local IP address to bind the server to</param> 83 /// <param name="bindAddress">Local IP address to bind the server to</param>
71 /// <param name="port">Port to listening for incoming UDP packets on</param> 84 /// <param name="port">Port to listening for incoming UDP packets on</param>
85 /// /// <param name="usePool">Are we to use an object pool to get objects for handing inbound data?</param>
72 public OpenSimUDPBase(IPAddress bindAddress, int port) 86 public OpenSimUDPBase(IPAddress bindAddress, int port)
73 { 87 {
74 m_localBindAddress = bindAddress; 88 m_localBindAddress = bindAddress;
@@ -76,7 +90,7 @@ namespace OpenMetaverse
76 } 90 }
77 91
78 /// <summary> 92 /// <summary>
79 /// Start the UDP server 93 /// Start inbound UDP packet handling.
80 /// </summary> 94 /// </summary>
81 /// <param name="recvBufferSize">The size of the receive buffer for 95 /// <param name="recvBufferSize">The size of the receive buffer for
82 /// the UDP socket. This value is passed up to the operating system 96 /// the UDP socket. This value is passed up to the operating system
@@ -91,11 +105,11 @@ namespace OpenMetaverse
91 /// manner (not throwing an exception when the remote side resets the 105 /// manner (not throwing an exception when the remote side resets the
92 /// connection). This call is ignored on Mono where the flag is not 106 /// connection). This call is ignored on Mono where the flag is not
93 /// necessary</remarks> 107 /// necessary</remarks>
94 public void Start(int recvBufferSize, bool asyncPacketHandling) 108 public void StartInbound(int recvBufferSize, bool asyncPacketHandling)
95 { 109 {
96 m_asyncPacketHandling = asyncPacketHandling; 110 m_asyncPacketHandling = asyncPacketHandling;
97 111
98 if (m_shutdownFlag) 112 if (!IsRunningInbound)
99 { 113 {
100 const int SIO_UDP_CONNRESET = -1744830452; 114 const int SIO_UDP_CONNRESET = -1744830452;
101 115
@@ -123,8 +137,7 @@ namespace OpenMetaverse
123 137
124 m_udpSocket.Bind(ipep); 138 m_udpSocket.Bind(ipep);
125 139
126 // we're not shutting down, we're starting up 140 IsRunningInbound = true;
127 m_shutdownFlag = false;
128 141
129 // kick off an async receive. The Start() method will return, the 142 // kick off an async receive. The Start() method will return, the
130 // actual receives will occur asynchronously and will be caught in 143 // actual receives will occur asynchronously and will be caught in
@@ -134,28 +147,69 @@ namespace OpenMetaverse
134 } 147 }
135 148
136 /// <summary> 149 /// <summary>
137 /// Stops the UDP server 150 /// Start outbound UDP packet handling.
138 /// </summary> 151 /// </summary>
139 public void Stop() 152 public void StartOutbound()
140 { 153 {
141 if (!m_shutdownFlag) 154 IsRunningOutbound = true;
155 }
156
157 public void StopInbound()
158 {
159 if (IsRunningInbound)
142 { 160 {
143 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 161 // wait indefinitely for a writer lock. Once this is called, the .NET runtime
144 // will deny any more reader locks, in effect blocking all other send/receive 162 // will deny any more reader locks, in effect blocking all other send/receive
145 // threads. Once we have the lock, we set shutdownFlag to inform the other 163 // threads. Once we have the lock, we set IsRunningInbound = false to inform the other
146 // threads that the socket is closed. 164 // threads that the socket is closed.
147 m_shutdownFlag = true; 165 IsRunningInbound = false;
148 m_udpSocket.Close(); 166 m_udpSocket.Close();
149 } 167 }
150 } 168 }
151 169
170 public void StopOutbound()
171 {
172 IsRunningOutbound = false;
173 }
174
175 protected virtual bool EnablePools()
176 {
177 if (!UsePools)
178 {
179 Pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500);
180
181 UsePools = true;
182
183 return true;
184 }
185
186 return false;
187 }
188
189 protected virtual bool DisablePools()
190 {
191 if (UsePools)
192 {
193 UsePools = false;
194
195 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
196
197 return true;
198 }
199
200 return false;
201 }
202
152 private void AsyncBeginReceive() 203 private void AsyncBeginReceive()
153 { 204 {
154 // allocate a packet buffer 205 UDPPacketBuffer buf;
155 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); 206
156 UDPPacketBuffer buf = new UDPPacketBuffer(); 207 if (UsePools)
208 buf = Pool.GetObject();
209 else
210 buf = new UDPPacketBuffer();
157 211
158 if (!m_shutdownFlag) 212 if (IsRunningInbound)
159 { 213 {
160 try 214 try
161 { 215 {
@@ -208,7 +262,7 @@ namespace OpenMetaverse
208 { 262 {
209 // Asynchronous receive operations will complete here through the call 263 // Asynchronous receive operations will complete here through the call
210 // to AsyncBeginReceive 264 // to AsyncBeginReceive
211 if (!m_shutdownFlag) 265 if (IsRunningInbound)
212 { 266 {
213 // Asynchronous mode will start another receive before the 267 // Asynchronous mode will start another receive before the
214 // callback for this packet is even fired. Very parallel :-) 268 // callback for this packet is even fired. Very parallel :-)
@@ -217,8 +271,6 @@ namespace OpenMetaverse
217 271
218 // get the buffer that was created in AsyncBeginReceive 272 // get the buffer that was created in AsyncBeginReceive
219 // this is the received data 273 // this is the received data
220 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
221 //UDPPacketBuffer buffer = wrappedBuffer.Instance;
222 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; 274 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
223 275
224 try 276 try
@@ -235,7 +287,8 @@ namespace OpenMetaverse
235 catch (ObjectDisposedException) { } 287 catch (ObjectDisposedException) { }
236 finally 288 finally
237 { 289 {
238 //wrappedBuffer.Dispose(); 290 if (UsePools)
291 Pool.ReturnObject(buffer);
239 292
240 // Synchronous mode waits until the packet callback completes 293 // Synchronous mode waits until the packet callback completes
241 // before starting the receive to fetch another packet 294 // before starting the receive to fetch another packet
@@ -248,7 +301,7 @@ namespace OpenMetaverse
248 301
249 public void AsyncBeginSend(UDPPacketBuffer buf) 302 public void AsyncBeginSend(UDPPacketBuffer buf)
250 { 303 {
251 if (!m_shutdownFlag) 304 if (IsRunningOutbound)
252 { 305 {
253 try 306 try
254 { 307 {
@@ -277,4 +330,4 @@ namespace OpenMetaverse
277 catch (ObjectDisposedException) { } 330 catch (ObjectDisposedException) { }
278 } 331 }
279 } 332 }
280} 333} \ No newline at end of file
diff --git a/OpenSim/Framework/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
index 41d17c5..1fdc410 100644
--- a/OpenSim/Framework/PacketPool.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
@@ -31,63 +31,114 @@ using System.Reflection;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenMetaverse.Packets; 32using OpenMetaverse.Packets;
33using log4net; 33using log4net;
34using OpenSim.Framework.Monitoring;
34 35
35namespace OpenSim.Framework 36namespace OpenSim.Region.ClientStack.LindenUDP
36{ 37{
37
38 public sealed class PacketPool 38 public sealed class PacketPool
39 { 39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41 41
42 private static readonly PacketPool instance = new PacketPool(); 42 private static readonly PacketPool instance = new PacketPool();
43 43
44 private bool packetPoolEnabled = true; 44 /// <summary>
45 private bool dataBlockPoolEnabled = true; 45 /// Pool of packets available for reuse.
46 46 /// </summary>
47 private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>(); 47 private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>();
48 48
49 private static Dictionary<Type, Stack<Object>> DataBlocks = 49 private static Dictionary<Type, Stack<Object>> DataBlocks = new Dictionary<Type, Stack<Object>>();
50 new Dictionary<Type, Stack<Object>>();
51 50
52 static PacketPool() 51 public static PacketPool Instance
53 { 52 {
53 get { return instance; }
54 } 54 }
55 55
56 public static PacketPool Instance 56 public bool RecyclePackets { get; set; }
57
58 public bool RecycleDataBlocks { get; set; }
59
60 /// <summary>
61 /// The number of packets pooled
62 /// </summary>
63 public int PacketsPooled
57 { 64 {
58 get { return instance; } 65 get
66 {
67 lock (pool)
68 return pool.Count;
69 }
59 } 70 }
60 71
61 public bool RecyclePackets 72 /// <summary>
73 /// The number of blocks pooled.
74 /// </summary>
75 public int BlocksPooled
62 { 76 {
63 set { packetPoolEnabled = value; } 77 get
64 get { return packetPoolEnabled; } 78 {
79 lock (DataBlocks)
80 return DataBlocks.Count;
81 }
65 } 82 }
66 83
67 public bool RecycleDataBlocks 84 /// <summary>
85 /// Number of packets requested.
86 /// </summary>
87 public long PacketsRequested { get; private set; }
88
89 /// <summary>
90 /// Number of packets reused.
91 /// </summary>
92 public long PacketsReused { get; private set; }
93
94 /// <summary>
95 /// Number of packet blocks requested.
96 /// </summary>
97 public long BlocksRequested { get; private set; }
98
99 /// <summary>
100 /// Number of packet blocks reused.
101 /// </summary>
102 public long BlocksReused { get; private set; }
103
104 private PacketPool()
68 { 105 {
69 set { dataBlockPoolEnabled = value; } 106 // defaults
70 get { return dataBlockPoolEnabled; } 107 RecyclePackets = true;
108 RecycleDataBlocks = true;
71 } 109 }
72 110
111 /// <summary>
112 /// Gets a packet of the given type.
113 /// </summary>
114 /// <param name='type'></param>
115 /// <returns>Guaranteed to always return a packet, whether from the pool or newly constructed.</returns>
73 public Packet GetPacket(PacketType type) 116 public Packet GetPacket(PacketType type)
74 { 117 {
118 PacketsRequested++;
119
75 Packet packet; 120 Packet packet;
76 121
77 if (!packetPoolEnabled) 122 if (!RecyclePackets)
78 return Packet.BuildPacket(type); 123 return Packet.BuildPacket(type);
79 124
80 lock (pool) 125 lock (pool)
81 { 126 {
82 if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) 127 if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0)
83 { 128 {
129// m_log.DebugFormat("[PACKETPOOL]: Building {0} packet", type);
130
84 // Creating a new packet if we cannot reuse an old package 131 // Creating a new packet if we cannot reuse an old package
85 packet = Packet.BuildPacket(type); 132 packet = Packet.BuildPacket(type);
86 } 133 }
87 else 134 else
88 { 135 {
136// m_log.DebugFormat("[PACKETPOOL]: Pulling {0} packet", type);
137
89 // Recycle old packages 138 // Recycle old packages
90 packet = (pool[type]).Pop(); 139 PacketsReused++;
140
141 packet = pool[type].Pop();
91 } 142 }
92 } 143 }
93 144
@@ -136,7 +187,7 @@ namespace OpenSim.Framework
136 { 187 {
137 PacketType type = GetType(bytes); 188 PacketType type = GetType(bytes);
138 189
139 Array.Clear(zeroBuffer, 0, zeroBuffer.Length); 190// Array.Clear(zeroBuffer, 0, zeroBuffer.Length);
140 191
141 int i = 0; 192 int i = 0;
142 Packet packet = GetPacket(type); 193 Packet packet = GetPacket(type);
@@ -154,7 +205,7 @@ namespace OpenSim.Framework
154 /// <param name="packet"></param> 205 /// <param name="packet"></param>
155 public void ReturnPacket(Packet packet) 206 public void ReturnPacket(Packet packet)
156 { 207 {
157 if (dataBlockPoolEnabled) 208 if (RecycleDataBlocks)
158 { 209 {
159 switch (packet.Type) 210 switch (packet.Type)
160 { 211 {
@@ -178,11 +229,12 @@ namespace OpenSim.Framework
178 } 229 }
179 } 230 }
180 231
181 if (packetPoolEnabled) 232 if (RecyclePackets)
182 { 233 {
183 switch (packet.Type) 234 switch (packet.Type)
184 { 235 {
185 // List pooling packets here 236 // List pooling packets here
237 case PacketType.AgentUpdate:
186 case PacketType.PacketAck: 238 case PacketType.PacketAck:
187 case PacketType.ObjectUpdate: 239 case PacketType.ObjectUpdate:
188 case PacketType.ImprovedTerseObjectUpdate: 240 case PacketType.ImprovedTerseObjectUpdate:
@@ -197,7 +249,9 @@ namespace OpenSim.Framework
197 249
198 if ((pool[type]).Count < 50) 250 if ((pool[type]).Count < 50)
199 { 251 {
200 (pool[type]).Push(packet); 252// m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type);
253
254 pool[type].Push(packet);
201 } 255 }
202 } 256 }
203 break; 257 break;
@@ -209,16 +263,21 @@ namespace OpenSim.Framework
209 } 263 }
210 } 264 }
211 265
212 public static T GetDataBlock<T>() where T: new() 266 public T GetDataBlock<T>() where T: new()
213 { 267 {
214 lock (DataBlocks) 268 lock (DataBlocks)
215 { 269 {
270 BlocksRequested++;
271
216 Stack<Object> s; 272 Stack<Object> s;
217 273
218 if (DataBlocks.TryGetValue(typeof(T), out s)) 274 if (DataBlocks.TryGetValue(typeof(T), out s))
219 { 275 {
220 if (s.Count > 0) 276 if (s.Count > 0)
277 {
278 BlocksReused++;
221 return (T)s.Pop(); 279 return (T)s.Pop();
280 }
222 } 281 }
223 else 282 else
224 { 283 {
@@ -229,7 +288,7 @@ namespace OpenSim.Framework
229 } 288 }
230 } 289 }
231 290
232 public static void ReturnDataBlock<T>(T block) where T: new() 291 public void ReturnDataBlock<T>(T block) where T: new()
233 { 292 {
234 if (block == null) 293 if (block == null)
235 return; 294 return;
@@ -244,4 +303,4 @@ namespace OpenSim.Framework
244 } 303 }
245 } 304 }
246 } 305 }
247} 306} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..af2f6f8
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.ClientStack.LindenUDP")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("9d3dbc6b-9d85-483b-af48-c1dfc261b7ac")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
index 109a8e1..556df30 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
@@ -43,7 +43,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
43 /// This will contain basic tests for the LindenUDP client stack 43 /// This will contain basic tests for the LindenUDP client stack
44 /// </summary> 44 /// </summary>
45 [TestFixture] 45 [TestFixture]
46 public class BasicCircuitTests 46 public class BasicCircuitTests : OpenSimTestCase
47 { 47 {
48 private Scene m_scene; 48 private Scene m_scene;
49 private TestLLUDPServer m_udpServer; 49 private TestLLUDPServer m_udpServer;
@@ -65,8 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
65 } 65 }
66 66
67 [SetUp] 67 [SetUp]
68 public void SetUp() 68 public override void SetUp()
69 { 69 {
70 base.SetUp();
70 m_scene = new SceneHelpers().SetupScene(); 71 m_scene = new SceneHelpers().SetupScene();
71 } 72 }
72 73
@@ -143,7 +144,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
143 public void TestAddClient() 144 public void TestAddClient()
144 { 145 {
145 TestHelpers.InMethod(); 146 TestHelpers.InMethod();
146// XmlConfigurator.Configure(); 147// TestHelpers.EnableLogging();
147 148
148 AddUdpServer(); 149 AddUdpServer();
149 150
diff --git a/OpenSim/Region/ClientStack/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e72bd86
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.ClientStack")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSIm")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("02ced54a-a802-4474-9e94-f03a44fde922")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
index 4672f8a..853b72d 100644
--- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs
+++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
@@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack
76 76
77 protected override void StartupSpecific() 77 protected override void StartupSpecific()
78 { 78 {
79 SceneManager = new SceneManager(); 79 SceneManager = SceneManager.Instance;
80 m_clientStackManager = CreateClientStackManager(); 80 m_clientStackManager = CreateClientStackManager();
81 81
82 Initialize(); 82 Initialize();
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index 8a4fd8f..da1ff2e 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -57,39 +57,36 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
57 } 57 }
58 58
59 /// <summary> 59 /// <summary>
60 /// Return a xfer uploader if one does not already exist. 60 /// Return the xfer uploader for the given transaction.
61 /// </summary> 61 /// </summary>
62 /// <remarks>
63 /// If an uploader does not already exist for this transaction then it is created, otherwise the existing
64 /// uploader is returned.
65 /// </remarks>
62 /// <param name="transactionID"></param> 66 /// <param name="transactionID"></param>
63 /// <param name="assetID"> 67 /// <returns>The asset xfer uploader</returns>
64 /// We must transfer the new asset ID into the uploader on creation, otherwise 68 public AssetXferUploader RequestXferUploader(UUID transactionID)
65 /// we can see race conditions with other threads which can retrieve an item before it is updated with the new
66 /// asset id.
67 /// </param>
68 /// <returns>
69 /// The xfer uploader requested. Null if one is already in existence.
70 /// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple
71 /// transfers are made. Needs to be corrected.
72 /// </returns>
73 public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID)
74 { 69 {
70 AssetXferUploader uploader;
71
75 lock (XferUploaders) 72 lock (XferUploaders)
76 { 73 {
77 if (!XferUploaders.ContainsKey(transactionID)) 74 if (!XferUploaders.ContainsKey(transactionID))
78 { 75 {
79 AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile); 76 uploader = new AssetXferUploader(this, m_Scene, transactionID, m_dumpAssetsToFile);
80 77
81// m_log.DebugFormat( 78// m_log.DebugFormat(
82// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); 79// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID);
83 80
84 XferUploaders.Add(transactionID, uploader); 81 XferUploaders.Add(transactionID, uploader);
85 82 }
86 return uploader; 83 else
84 {
85 uploader = XferUploaders[transactionID];
87 } 86 }
88 } 87 }
89 88
90 m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID); 89 return uploader;
91
92 return null;
93 } 90 }
94 91
95 public void HandleXfer(ulong xferID, uint packetID, byte[] data) 92 public void HandleXfer(ulong xferID, uint packetID, byte[] data)
@@ -151,117 +148,30 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
151 string description, string name, sbyte invType, 148 string description, string name, sbyte invType,
152 sbyte type, byte wearableType, uint nextOwnerMask) 149 sbyte type, byte wearableType, uint nextOwnerMask)
153 { 150 {
154 AssetXferUploader uploader = null; 151 AssetXferUploader uploader = RequestXferUploader(transactionID);
155
156 lock (XferUploaders)
157 {
158 if (XferUploaders.ContainsKey(transactionID))
159 uploader = XferUploaders[transactionID];
160 }
161 152
162 if (uploader != null) 153 uploader.RequestCreateInventoryItem(
163 { 154 remoteClient, folderID, callbackID,
164 uploader.RequestCreateInventoryItem( 155 description, name, invType, type, wearableType, nextOwnerMask);
165 remoteClient, transactionID, folderID,
166 callbackID, description, name, invType, type,
167 wearableType, nextOwnerMask);
168 156
169 return true; 157 return true;
170 }
171
172 return false;
173 }
174
175 /// <summary>
176 /// Get an uploaded asset. If the data is successfully retrieved,
177 /// the transaction will be removed.
178 /// </summary>
179 /// <param name="transactionID"></param>
180 /// <returns>The asset if the upload has completed, null if it has not.</returns>
181 private AssetBase GetTransactionAsset(UUID transactionID)
182 {
183 lock (XferUploaders)
184 {
185 if (XferUploaders.ContainsKey(transactionID))
186 {
187 AssetXferUploader uploader = XferUploaders[transactionID];
188 AssetBase asset = uploader.GetAssetData();
189 RemoveXferUploader(transactionID);
190
191 return asset;
192 }
193 }
194
195 return null;
196 } 158 }
197 159
198 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, 160 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,
199 SceneObjectPart part, UUID transactionID, 161 SceneObjectPart part, UUID transactionID,
200 TaskInventoryItem item) 162 TaskInventoryItem item)
201 { 163 {
202 AssetXferUploader uploader = null; 164 AssetXferUploader uploader = RequestXferUploader(transactionID);
203
204 lock (XferUploaders)
205 {
206 if (XferUploaders.ContainsKey(transactionID))
207 uploader = XferUploaders[transactionID];
208 }
209
210 if (uploader != null)
211 {
212 AssetBase asset = GetTransactionAsset(transactionID);
213
214 // Only legacy viewers use this, and they prefer CAPS, which
215 // we have, so this really never runs.
216 // Allow it, but only for "safe" types.
217 if ((InventoryType)item.InvType != InventoryType.Notecard &&
218 (InventoryType)item.InvType != InventoryType.LSL)
219 return;
220 165
221 if (asset != null) 166 uploader.RequestUpdateTaskInventoryItem(remoteClient, item);
222 {
223// m_log.DebugFormat(
224// "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}",
225// item.Name, part.Name, transactionID);
226
227 asset.FullID = UUID.Random();
228 asset.Name = item.Name;
229 asset.Description = item.Description;
230 asset.Type = (sbyte)item.Type;
231 item.AssetID = asset.FullID;
232
233 m_Scene.AssetService.Store(asset);
234 }
235 }
236 else
237 {
238 m_log.ErrorFormat(
239 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}",
240 transactionID, item.Name, part.Name);
241 }
242 } 167 }
243 168
244 public void RequestUpdateInventoryItem(IClientAPI remoteClient, 169 public void RequestUpdateInventoryItem(IClientAPI remoteClient,
245 UUID transactionID, InventoryItemBase item) 170 UUID transactionID, InventoryItemBase item)
246 { 171 {
247 AssetXferUploader uploader = null; 172 AssetXferUploader uploader = RequestXferUploader(transactionID);
248
249 lock (XferUploaders)
250 {
251 if (XferUploaders.ContainsKey(transactionID))
252 uploader = XferUploaders[transactionID];
253 }
254 173
255 if (uploader != null) 174 uploader.RequestUpdateInventoryItem(remoteClient, item);
256 {
257 uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item);
258 }
259 else
260 {
261 m_log.ErrorFormat(
262 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}",
263 transactionID, item.Name, remoteClient.Name);
264 }
265 } 175 }
266 } 176 }
267} 177}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index 441c4ff..7332415 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
54 private Dictionary<UUID, AgentAssetTransactions> AgentTransactions = 54 private Dictionary<UUID, AgentAssetTransactions> AgentTransactions =
55 new Dictionary<UUID, AgentAssetTransactions>(); 55 new Dictionary<UUID, AgentAssetTransactions>();
56 56
57 #region IRegionModule Members 57 #region Region Module interface
58 58
59 public void Initialise(IConfigSource source) 59 public void Initialise(IConfigSource source)
60 { 60 {
@@ -215,7 +215,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
215 IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) 215 IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item)
216 { 216 {
217 m_log.DebugFormat( 217 m_log.DebugFormat(
218 "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", 218 "[ASSET TRANSACTION MODULE] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}",
219 item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName); 219 item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName);
220 220
221 AgentAssetTransactions transactions = 221 AgentAssetTransactions transactions =
@@ -274,13 +274,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
274 } 274 }
275 275
276 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); 276 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
277 AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID); 277 AssetXferUploader uploader = transactions.RequestXferUploader(transaction);
278 278 uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile);
279 if (uploader != null)
280 {
281 uploader.Initialise(remoteClient, assetID, transaction, type,
282 data, storeLocal, tempFile);
283 }
284 } 279 }
285 280
286 /// <summary> 281 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index 4cedfe6..0aa4693 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -49,39 +49,75 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 /// <summary> 51 /// <summary>
52 /// Upload state.
53 /// </summary>
54 /// <remarks>
55 /// New -> Uploading -> Complete
56 /// </remarks>
57 private enum UploadState
58 {
59 New,
60 Uploading,
61 Complete
62 }
63
64 /// <summary>
52 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we 65 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we
53 /// are performing a delayed update. 66 /// are performing a delayed update.
54 /// </summary> 67 /// </summary>
55 AgentAssetTransactions m_transactions; 68 AgentAssetTransactions m_transactions;
56 69
70 private UploadState m_uploadState = UploadState.New;
71
57 private AssetBase m_asset; 72 private AssetBase m_asset;
58 private UUID InventFolder = UUID.Zero; 73 private UUID InventFolder = UUID.Zero;
59 private sbyte invType = 0; 74 private sbyte invType = 0;
60 75
61 private bool m_createItem = false; 76 private bool m_createItem;
62 private uint m_createItemCallback = 0; 77 private uint m_createItemCallback;
63 private bool m_updateItem = false; 78
79 private bool m_updateItem;
64 private InventoryItemBase m_updateItemData; 80 private InventoryItemBase m_updateItemData;
65 81
82 private bool m_updateTaskItem;
83 private TaskInventoryItem m_updateTaskItemData;
84
66 private string m_description = String.Empty; 85 private string m_description = String.Empty;
67 private bool m_dumpAssetToFile; 86 private bool m_dumpAssetToFile;
68 private bool m_finished = false;
69 private string m_name = String.Empty; 87 private string m_name = String.Empty;
70 private bool m_storeLocal; 88// private bool m_storeLocal;
71 private uint nextPerm = 0; 89 private uint nextPerm = 0;
72 private IClientAPI ourClient; 90 private IClientAPI ourClient;
73 private UUID TransactionID = UUID.Zero; 91
92 private UUID m_transactionID;
93
74 private sbyte type = 0; 94 private sbyte type = 0;
75 private byte wearableType = 0; 95 private byte wearableType = 0;
76 private byte[] m_oldData = null; 96 private byte[] m_oldData = null;
77 public ulong XferID; 97 public ulong XferID;
78 private Scene m_Scene; 98 private Scene m_Scene;
79 99
80 public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile) 100 /// <summary>
101 /// AssetXferUploader constructor
102 /// </summary>
103 /// <param name='transactions'>/param>
104 /// <param name='scene'></param>
105 /// <param name='transactionID'></param>
106 /// <param name='dumpAssetToFile'>
107 /// If true then when the asset is uploaded it is dumped to a file with the format
108 /// String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat",
109 /// now.Year, now.Month, now.Day, now.Hour, now.Minute,
110 /// now.Second, m_asset.Name, m_asset.Type);
111 /// for debugging purposes.
112 /// </param>
113 public AssetXferUploader(
114 AgentAssetTransactions transactions, Scene scene, UUID transactionID, bool dumpAssetToFile)
81 { 115 {
116 m_asset = new AssetBase();
117
82 m_transactions = transactions; 118 m_transactions = transactions;
119 m_transactionID = transactionID;
83 m_Scene = scene; 120 m_Scene = scene;
84 m_asset = new AssetBase() { FullID = assetID };
85 m_dumpAssetToFile = dumpAssetToFile; 121 m_dumpAssetToFile = dumpAssetToFile;
86 } 122 }
87 123
@@ -100,18 +136,27 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
100 136
101 if (XferID == xferID) 137 if (XferID == xferID)
102 { 138 {
103 if (m_asset.Data.Length > 1) 139 lock (this)
104 {
105 byte[] destinationArray = new byte[m_asset.Data.Length + data.Length];
106 Array.Copy(m_asset.Data, 0, destinationArray, 0, m_asset.Data.Length);
107 Array.Copy(data, 0, destinationArray, m_asset.Data.Length, data.Length);
108 m_asset.Data = destinationArray;
109 }
110 else
111 { 140 {
112 byte[] buffer2 = new byte[data.Length - 4]; 141 int assetLength = m_asset.Data.Length;
113 Array.Copy(data, 4, buffer2, 0, data.Length - 4); 142 int dataLength = data.Length;
114 m_asset.Data = buffer2; 143
144 if (m_asset.Data.Length > 1)
145 {
146 byte[] destinationArray = new byte[assetLength + dataLength];
147 Array.Copy(m_asset.Data, 0, destinationArray, 0, assetLength);
148 Array.Copy(data, 0, destinationArray, assetLength, dataLength);
149 m_asset.Data = destinationArray;
150 }
151 else
152 {
153 if (dataLength > 4)
154 {
155 byte[] buffer2 = new byte[dataLength - 4];
156 Array.Copy(data, 4, buffer2, 0, dataLength - 4);
157 m_asset.Data = buffer2;
158 }
159 }
115 } 160 }
116 161
117 ourClient.SendConfirmXfer(xferID, packetID); 162 ourClient.SendConfirmXfer(xferID, packetID);
@@ -127,30 +172,50 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
127 } 172 }
128 173
129 /// <summary> 174 /// <summary>
130 /// Initialise asset transfer from the client 175 /// Start asset transfer from the client
131 /// </summary> 176 /// </summary>
132 /// <param name="xferID"></param> 177 /// <param name="remoteClient"></param>
133 /// <param name="packetID"></param> 178 /// <param name="assetID"></param>
134 /// <param name="data"></param> 179 /// <param name="transaction"></param>
135 public void Initialise(IClientAPI remoteClient, UUID assetID, 180 /// <param name="type"></param>
136 UUID transaction, sbyte type, byte[] data, bool storeLocal, 181 /// <param name="data">
137 bool tempFile) 182 /// Optional data. If present then the asset is created immediately with this data
183 /// rather than requesting an upload from the client. The data must be longer than 2 bytes.
184 /// </param>
185 /// <param name="storeLocal"></param>
186 /// <param name="tempFile"></param>
187 public void StartUpload(
188 IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, bool storeLocal,
189 bool tempFile)
138 { 190 {
139// m_log.DebugFormat( 191// m_log.DebugFormat(
140// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", 192// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}",
141// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); 193// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length);
142 194
195 lock (this)
196 {
197 if (m_uploadState != UploadState.New)
198 {
199 m_log.WarnFormat(
200 "[ASSET XFER UPLOADER]: Tried to start upload of asset {0}, transaction {1} for {2} but this is already in state {3}. Aborting.",
201 assetID, transaction, remoteClient.Name, m_uploadState);
202
203 return;
204 }
205
206 m_uploadState = UploadState.Uploading;
207 }
208
143 ourClient = remoteClient; 209 ourClient = remoteClient;
144 m_asset.Name = "blank"; 210
145 m_asset.Description = "empty"; 211 m_asset.FullID = assetID;
146 m_asset.Type = type; 212 m_asset.Type = type;
147 m_asset.CreatorID = remoteClient.AgentId.ToString(); 213 m_asset.CreatorID = remoteClient.AgentId.ToString();
148 m_asset.Data = data; 214 m_asset.Data = data;
149 m_asset.Local = storeLocal; 215 m_asset.Local = storeLocal;
150 m_asset.Temporary = tempFile; 216 m_asset.Temporary = tempFile;
151 217
152 TransactionID = transaction; 218// m_storeLocal = storeLocal;
153 m_storeLocal = storeLocal;
154 219
155 if (m_asset.Data.Length > 2) 220 if (m_asset.Data.Length > 2)
156 { 221 {
@@ -175,36 +240,35 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
175 240
176 protected void SendCompleteMessage() 241 protected void SendCompleteMessage()
177 { 242 {
178 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true,
179 m_asset.FullID);
180
181 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create 243 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create
182 // message from other client UDP. 244 // message from other client UDP.
183 lock (this) 245 lock (this)
184 { 246 {
185 m_finished = true; 247 m_uploadState = UploadState.Complete;
248
249 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID);
250
186 if (m_createItem) 251 if (m_createItem)
187 { 252 {
188 DoCreateItem(m_createItemCallback); 253 CompleteCreateItem(m_createItemCallback);
189 } 254 }
190 else if (m_updateItem) 255 else if (m_updateItem)
191 { 256 {
192 StoreAssetForItemUpdate(m_updateItemData); 257 CompleteItemUpdate(m_updateItemData);
193
194 // Remove ourselves from the list of transactions if completion was delayed until the transaction
195 // was complete.
196 // TODO: Should probably do the same for create item.
197 m_transactions.RemoveXferUploader(TransactionID);
198 } 258 }
199 else if (m_storeLocal) 259 else if (m_updateTaskItem)
200 { 260 {
201 m_Scene.AssetService.Store(m_asset); 261 CompleteTaskItemUpdate(m_updateTaskItemData);
202 } 262 }
263// else if (m_storeLocal)
264// {
265// m_Scene.AssetService.Store(m_asset);
266// }
203 } 267 }
204 268
205 m_log.DebugFormat( 269 m_log.DebugFormat(
206 "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", 270 "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}",
207 m_asset.FullID, TransactionID); 271 m_asset.FullID, m_transactionID);
208 272
209 if (m_dumpAssetToFile) 273 if (m_dumpAssetToFile)
210 { 274 {
@@ -232,40 +296,37 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
232 } 296 }
233 297
234 public void RequestCreateInventoryItem(IClientAPI remoteClient, 298 public void RequestCreateInventoryItem(IClientAPI remoteClient,
235 UUID transactionID, UUID folderID, uint callbackID, 299 UUID folderID, uint callbackID,
236 string description, string name, sbyte invType, 300 string description, string name, sbyte invType,
237 sbyte type, byte wearableType, uint nextOwnerMask) 301 sbyte type, byte wearableType, uint nextOwnerMask)
238 { 302 {
239 if (TransactionID == transactionID) 303 InventFolder = folderID;
304 m_name = name;
305 m_description = description;
306 this.type = type;
307 this.invType = invType;
308 this.wearableType = wearableType;
309 nextPerm = nextOwnerMask;
310 m_asset.Name = name;
311 m_asset.Description = description;
312 m_asset.Type = type;
313
314 // We must lock to avoid a race with a separate thread uploading the asset.
315 lock (this)
240 { 316 {
241 InventFolder = folderID; 317 if (m_uploadState == UploadState.Complete)
242 m_name = name;
243 m_description = description;
244 this.type = type;
245 this.invType = invType;
246 this.wearableType = wearableType;
247 nextPerm = nextOwnerMask;
248 m_asset.Name = name;
249 m_asset.Description = description;
250 m_asset.Type = type;
251
252 // We must lock to avoid a race with a separate thread uploading the asset.
253 lock (this)
254 { 318 {
255 if (m_finished) 319 CompleteCreateItem(callbackID);
256 { 320 }
257 DoCreateItem(callbackID); 321 else
258 } 322 {
259 else 323 m_createItem = true; //set flag so the inventory item is created when upload is complete
260 { 324 m_createItemCallback = callbackID;
261 m_createItem = true; //set flag so the inventory item is created when upload is complete
262 m_createItemCallback = callbackID;
263 }
264 } 325 }
265 } 326 }
266 } 327 }
267 328
268 public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) 329 public void RequestUpdateInventoryItem(IClientAPI remoteClient, InventoryItemBase item)
269 { 330 {
270 // We must lock to avoid a race with a separate thread uploading the asset. 331 // We must lock to avoid a race with a separate thread uploading the asset.
271 lock (this) 332 lock (this)
@@ -280,9 +341,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
280 item.AssetID = m_asset.FullID; 341 item.AssetID = m_asset.FullID;
281 m_Scene.InventoryService.UpdateItem(item); 342 m_Scene.InventoryService.UpdateItem(item);
282 343
283 if (m_finished) 344 if (m_uploadState == UploadState.Complete)
284 { 345 {
285 StoreAssetForItemUpdate(item); 346 CompleteItemUpdate(item);
286 } 347 }
287 else 348 else
288 { 349 {
@@ -296,20 +357,59 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
296 } 357 }
297 } 358 }
298 359
360 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, TaskInventoryItem taskItem)
361 {
362 // We must lock to avoid a race with a separate thread uploading the asset.
363 lock (this)
364 {
365 m_asset.Name = taskItem.Name;
366 m_asset.Description = taskItem.Description;
367 m_asset.Type = (sbyte)taskItem.Type;
368 taskItem.AssetID = m_asset.FullID;
369
370 if (m_uploadState == UploadState.Complete)
371 {
372 CompleteTaskItemUpdate(taskItem);
373 }
374 else
375 {
376 m_updateTaskItem = true;
377 m_updateTaskItemData = taskItem;
378 }
379 }
380 }
381
299 /// <summary> 382 /// <summary>
300 /// Store the asset for the given item. 383 /// Store the asset for the given item when it has been uploaded.
301 /// </summary> 384 /// </summary>
302 /// <param name="item"></param> 385 /// <param name="item"></param>
303 private void StoreAssetForItemUpdate(InventoryItemBase item) 386 private void CompleteItemUpdate(InventoryItemBase item)
304 { 387 {
305// m_log.DebugFormat( 388// m_log.DebugFormat(
306// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", 389// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
307// m_asset.FullID, item.Name, ourClient.Name); 390// m_asset.FullID, item.Name, ourClient.Name);
308 391
309 m_Scene.AssetService.Store(m_asset); 392 m_Scene.AssetService.Store(m_asset);
393
394 m_transactions.RemoveXferUploader(m_transactionID);
310 } 395 }
311 396
312 private void DoCreateItem(uint callbackID) 397 /// <summary>
398 /// Store the asset for the given task item when it has been uploaded.
399 /// </summary>
400 /// <param name="taskItem"></param>
401 private void CompleteTaskItemUpdate(TaskInventoryItem taskItem)
402 {
403// m_log.DebugFormat(
404// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}",
405// m_asset.FullID, taskItem.Name, ourClient.Name);
406
407 m_Scene.AssetService.Store(m_asset);
408
409 m_transactions.RemoveXferUploader(m_transactionID);
410 }
411
412 private void CompleteCreateItem(uint callbackID)
313 { 413 {
314 ValidateAssets(); 414 ValidateAssets();
315 m_Scene.AssetService.Store(m_asset); 415 m_Scene.AssetService.Store(m_asset);
@@ -339,6 +439,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
339 ourClient.SendInventoryItemCreateUpdate(item, callbackID); 439 ourClient.SendInventoryItemCreateUpdate(item, callbackID);
340 else 440 else
341 ourClient.SendAlertMessage("Unable to create inventory item"); 441 ourClient.SendAlertMessage("Unable to create inventory item");
442
443 m_transactions.RemoveXferUploader(m_transactionID);
342 } 444 }
343 445
344 private void ValidateAssets() 446 private void ValidateAssets()
@@ -416,7 +518,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
416 /// <returns>null if the asset has not finished uploading</returns> 518 /// <returns>null if the asset has not finished uploading</returns>
417 public AssetBase GetAssetData() 519 public AssetBase GetAssetData()
418 { 520 {
419 if (m_finished) 521 if (m_uploadState == UploadState.Complete)
420 { 522 {
421 ValidateAssets(); 523 ValidateAssets();
422 return m_asset; 524 return m_asset;
@@ -469,4 +571,3 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
469 } 571 }
470 } 572 }
471} 573}
472
diff --git a/OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs b/OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs
index bfe2a71..4b457b1 100644
--- a/OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Text; 31using System.Text;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
@@ -36,13 +37,18 @@ using OpenSim.Region.Framework.Scenes;
36 37
37namespace OpenSim.Region.CoreModules.Agent.IPBan 38namespace OpenSim.Region.CoreModules.Agent.IPBan
38{ 39{
39 public class IPBanModule : IRegionModule 40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "IPBanModule")]
41 public class IPBanModule : ISharedRegionModule
40 { 42 {
41 #region Implementation of IRegionModule 43 #region Implementation of ISharedRegionModule
42 44
43 private List<string> m_bans = new List<string>(); 45 private List<string> m_bans = new List<string>();
44 46
45 public void Initialise(Scene scene, IConfigSource source) 47 public void Initialise(IConfigSource source)
48 {
49 }
50
51 public void AddRegion(Scene scene)
46 { 52 {
47 new SceneBanner(scene, m_bans); 53 new SceneBanner(scene, m_bans);
48 54
@@ -50,7 +56,7 @@ namespace OpenSim.Region.CoreModules.Agent.IPBan
50 { 56 {
51 foreach (EstateBan ban in scene.RegionInfo.EstateSettings.EstateBans) 57 foreach (EstateBan ban in scene.RegionInfo.EstateSettings.EstateBans)
52 { 58 {
53 if (!String.IsNullOrEmpty(ban.BannedHostIPMask)) 59 if (!String.IsNullOrEmpty(ban.BannedHostIPMask))
54 m_bans.Add(ban.BannedHostIPMask); 60 m_bans.Add(ban.BannedHostIPMask);
55 if (!String.IsNullOrEmpty(ban.BannedHostNameMask)) 61 if (!String.IsNullOrEmpty(ban.BannedHostNameMask))
56 m_bans.Add(ban.BannedHostNameMask); 62 m_bans.Add(ban.BannedHostNameMask);
@@ -58,6 +64,14 @@ namespace OpenSim.Region.CoreModules.Agent.IPBan
58 } 64 }
59 } 65 }
60 66
67 public void RemoveRegion(Scene scene)
68 {
69 }
70
71 public void RegionLoaded(Scene scene)
72 {
73 }
74
61 public void PostInitialise() 75 public void PostInitialise()
62 { 76 {
63 if (File.Exists("bans.txt")) 77 if (File.Exists("bans.txt"))
@@ -80,9 +94,9 @@ namespace OpenSim.Region.CoreModules.Agent.IPBan
80 get { return "IPBanModule"; } 94 get { return "IPBanModule"; }
81 } 95 }
82 96
83 public bool IsSharedModule 97 public Type ReplaceableInterface
84 { 98 {
85 get { return true; } 99 get { return null; }
86 } 100 }
87 101
88 #endregion 102 #endregion
diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
index a1a2501..3764685 100644
--- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
@@ -32,6 +32,7 @@ using System.Reflection;
32using System.Text; 32using System.Text;
33using System.Threading; 33using System.Threading;
34using log4net; 34using log4net;
35using Mono.Addins;
35using Nini.Config; 36using Nini.Config;
36using OpenMetaverse; 37using OpenMetaverse;
37using OpenMetaverse.Imaging; 38using OpenMetaverse.Imaging;
@@ -45,7 +46,8 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
45{ 46{
46 public delegate void J2KDecodeDelegate(UUID assetID); 47 public delegate void J2KDecodeDelegate(UUID assetID);
47 48
48 public class J2KDecoderModule : IRegionModule, IJ2KDecoder 49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "J2KDecoderModule")]
50 public class J2KDecoderModule : ISharedRegionModule, IJ2KDecoder
49 { 51 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 53
@@ -55,27 +57,32 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
55 private readonly Dictionary<UUID, List<DecodedCallback>> m_notifyList = new Dictionary<UUID, List<DecodedCallback>>(); 57 private readonly Dictionary<UUID, List<DecodedCallback>> m_notifyList = new Dictionary<UUID, List<DecodedCallback>>();
56 /// <summary>Cache that will store decoded JPEG2000 layer boundary data</summary> 58 /// <summary>Cache that will store decoded JPEG2000 layer boundary data</summary>
57 private IImprovedAssetCache m_cache; 59 private IImprovedAssetCache m_cache;
60 private IImprovedAssetCache Cache
61 {
62 get
63 {
64 if (m_cache == null)
65 m_cache = m_scene.RequestModuleInterface<IImprovedAssetCache>();
66
67 return m_cache;
68 }
69 }
58 /// <summary>Reference to a scene (doesn't matter which one as long as it can load the cache module)</summary> 70 /// <summary>Reference to a scene (doesn't matter which one as long as it can load the cache module)</summary>
71 private UUID m_CreatorID = UUID.Zero;
59 private Scene m_scene; 72 private Scene m_scene;
60 73
61 #region IRegionModule 74 #region ISharedRegionModule
62 75
63 private bool m_useCSJ2K = true; 76 private bool m_useCSJ2K = true;
64 77
65 public string Name { get { return "J2KDecoderModule"; } } 78 public string Name { get { return "J2KDecoderModule"; } }
66 public bool IsSharedModule { get { return true; } }
67 79
68 public J2KDecoderModule() 80 public J2KDecoderModule()
69 { 81 {
70 } 82 }
71 83
72 public void Initialise(Scene scene, IConfigSource source) 84 public void Initialise(IConfigSource source)
73 { 85 {
74 if (m_scene == null)
75 m_scene = scene;
76
77 scene.RegisterModuleInterface<IJ2KDecoder>(this);
78
79 IConfig startupConfig = source.Configs["Startup"]; 86 IConfig startupConfig = source.Configs["Startup"];
80 if (startupConfig != null) 87 if (startupConfig != null)
81 { 88 {
@@ -83,16 +90,42 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
83 } 90 }
84 } 91 }
85 92
93 public void AddRegion(Scene scene)
94 {
95 if (m_scene == null)
96 {
97 m_scene = scene;
98 m_CreatorID = scene.RegionInfo.RegionID;
99 }
100
101 scene.RegisterModuleInterface<IJ2KDecoder>(this);
102
103 }
104
105 public void RemoveRegion(Scene scene)
106 {
107 if (m_scene == scene)
108 m_scene = null;
109 }
110
86 public void PostInitialise() 111 public void PostInitialise()
87 { 112 {
88 m_cache = m_scene.RequestModuleInterface<IImprovedAssetCache>();
89 } 113 }
90 114
91 public void Close() 115 public void Close()
92 { 116 {
93 } 117 }
94 118
95 #endregion IRegionModule 119 public void RegionLoaded(Scene scene)
120 {
121 }
122
123 public Type ReplaceableInterface
124 {
125 get { return null; }
126 }
127
128 #endregion Region Module interface
96 129
97 #region IJ2KDecoder 130 #region IJ2KDecoder
98 131
@@ -275,11 +308,11 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
275 { 308 {
276 m_decodedCache.AddOrUpdate(AssetId, Layers, TimeSpan.FromMinutes(10)); 309 m_decodedCache.AddOrUpdate(AssetId, Layers, TimeSpan.FromMinutes(10));
277 310
278 if (m_cache != null) 311 if (Cache != null)
279 { 312 {
280 string assetID = "j2kCache_" + AssetId.ToString(); 313 string assetID = "j2kCache_" + AssetId.ToString();
281 314
282 AssetBase layerDecodeAsset = new AssetBase(assetID, assetID, (sbyte)AssetType.Notecard, m_scene.RegionInfo.RegionID.ToString()); 315 AssetBase layerDecodeAsset = new AssetBase(assetID, assetID, (sbyte)AssetType.Notecard, m_CreatorID.ToString());
283 layerDecodeAsset.Local = true; 316 layerDecodeAsset.Local = true;
284 layerDecodeAsset.Temporary = true; 317 layerDecodeAsset.Temporary = true;
285 318
@@ -299,7 +332,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
299 332
300 #endregion Serialize Layer Data 333 #endregion Serialize Layer Data
301 334
302 m_cache.Cache(layerDecodeAsset); 335 Cache.Cache(layerDecodeAsset);
303 } 336 }
304 } 337 }
305 338
@@ -309,10 +342,10 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
309 { 342 {
310 return true; 343 return true;
311 } 344 }
312 else if (m_cache != null) 345 else if (Cache != null)
313 { 346 {
314 string assetName = "j2kCache_" + AssetId.ToString(); 347 string assetName = "j2kCache_" + AssetId.ToString();
315 AssetBase layerDecodeAsset = m_cache.Get(assetName); 348 AssetBase layerDecodeAsset = Cache.Get(assetName);
316 349
317 if (layerDecodeAsset != null) 350 if (layerDecodeAsset != null)
318 { 351 {
@@ -324,7 +357,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
324 if (lines.Length == 0) 357 if (lines.Length == 0)
325 { 358 {
326 m_log.Warn("[J2KDecodeCache]: Expiring corrupted layer data (empty) " + assetName); 359 m_log.Warn("[J2KDecodeCache]: Expiring corrupted layer data (empty) " + assetName);
327 m_cache.Expire(assetName); 360 Cache.Expire(assetName);
328 return false; 361 return false;
329 } 362 }
330 363
@@ -345,7 +378,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
345 catch (FormatException) 378 catch (FormatException)
346 { 379 {
347 m_log.Warn("[J2KDecodeCache]: Expiring corrupted layer data (format) " + assetName); 380 m_log.Warn("[J2KDecodeCache]: Expiring corrupted layer data (format) " + assetName);
348 m_cache.Expire(assetName); 381 Cache.Expire(assetName);
349 return false; 382 return false;
350 } 383 }
351 384
@@ -356,7 +389,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
356 else 389 else
357 { 390 {
358 m_log.Warn("[J2KDecodeCache]: Expiring corrupted layer data (layout) " + assetName); 391 m_log.Warn("[J2KDecodeCache]: Expiring corrupted layer data (layout) " + assetName);
359 m_cache.Expire(assetName); 392 Cache.Expire(assetName);
360 return false; 393 return false;
361 } 394 }
362 } 395 }
diff --git a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
index 78d597d..7113f4f 100644
--- a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs
@@ -35,9 +35,12 @@ using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
37 37
38using Mono.Addins;
39
38namespace OpenSim.Region.CoreModules.Agent.Xfer 40namespace OpenSim.Region.CoreModules.Agent.Xfer
39{ 41{
40 public class XferModule : IRegionModule, IXfer 42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XferModule")]
43 public class XferModule : INonSharedRegionModule, IXfer
41 { 44 {
42 private Scene m_scene; 45 private Scene m_scene;
43 private Dictionary<string, FileData> NewFiles = new Dictionary<string, FileData>(); 46 private Dictionary<string, FileData> NewFiles = new Dictionary<string, FileData>();
@@ -59,9 +62,13 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
59 public int Count; 62 public int Count;
60 } 63 }
61 64
62 #region IRegionModule Members 65 #region INonSharedRegionModule Members
66
67 public void Initialise(IConfigSource config)
68 {
69 }
63 70
64 public void Initialise(Scene scene, IConfigSource config) 71 public void AddRegion(Scene scene)
65 { 72 {
66 m_scene = scene; 73 m_scene = scene;
67 m_scene.EventManager.OnNewClient += NewClient; 74 m_scene.EventManager.OnNewClient += NewClient;
@@ -69,22 +76,30 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer
69 m_scene.RegisterModuleInterface<IXfer>(this); 76 m_scene.RegisterModuleInterface<IXfer>(this);
70 } 77 }
71 78
72 public void PostInitialise() 79 public void RemoveRegion(Scene scene)
73 { 80 {
81 m_scene.EventManager.OnNewClient -= NewClient;
82
83 m_scene.UnregisterModuleInterface<IXfer>(this);
84 m_scene = null;
74 } 85 }
75 86
76 public void Close() 87 public void RegionLoaded(Scene scene)
77 { 88 {
78 } 89 }
79 90
80 public string Name 91 public Type ReplaceableInterface
81 { 92 {
82 get { return "XferModule"; } 93 get { return null; }
83 } 94 }
84 95
85 public bool IsSharedModule 96 public void Close()
86 { 97 {
87 get { return false; } 98 }
99
100 public string Name
101 {
102 get { return "XferModule"; }
88 } 103 }
89 104
90 #endregion 105 #endregion
diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
index b1b7b27..e40caec 100644
--- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Reflection; 29using System.Reflection;
30using log4net; 30using log4net;
31using Mono.Addins;
31using Nini.Config; 32using Nini.Config;
32using OpenSim.Framework; 33using OpenSim.Framework;
33using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
@@ -89,6 +90,7 @@ namespace OpenSim.Region.CoreModules.Asset
89 /// ExpirationTime = 60 90 /// ExpirationTime = 60
90 /// </code> 91 /// </code>
91 /// </example> 92 /// </example>
93 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CenomeMemoryAssetCache")]
92 public class CenomeMemoryAssetCache : IImprovedAssetCache, ISharedRegionModule 94 public class CenomeMemoryAssetCache : IImprovedAssetCache, ISharedRegionModule
93 { 95 {
94 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 96 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
index 7da5e7a..9742a5c 100644
--- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
@@ -30,6 +30,7 @@ using System;
30using System.IO; 30using System.IO;
31using System.Collections.Generic; 31using System.Collections.Generic;
32using System.Reflection; 32using System.Reflection;
33using Mono.Addins;
33using Nini.Config; 34using Nini.Config;
34using OpenSim.Framework; 35using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
@@ -38,6 +39,7 @@ using OpenSim.Services.Interfaces;
38 39
39namespace OpenSim.Region.CoreModules.Asset 40namespace OpenSim.Region.CoreModules.Asset
40{ 41{
42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CoreAssetCache")]
41 public class CoreAssetCache : ISharedRegionModule, IImprovedAssetCache 43 public class CoreAssetCache : ISharedRegionModule, IImprovedAssetCache
42 { 44 {
43 private static readonly ILog m_log = 45 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 7d7176f..b1bb56b 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -49,12 +49,12 @@ using OpenSim.Region.Framework.Scenes;
49using OpenSim.Services.Interfaces; 49using OpenSim.Services.Interfaces;
50 50
51 51
52[assembly: Addin("FlotsamAssetCache", "1.1")] 52//[assembly: Addin("FlotsamAssetCache", "1.1")]
53[assembly: AddinDependency("OpenSim", "0.5")] 53//[assembly: AddinDependency("OpenSim", "0.5")]
54 54
55namespace Flotsam.RegionModules.AssetCache 55namespace OpenSim.Region.CoreModules.Asset
56{ 56{
57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "FlotsamAssetCache")]
58 public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService 58 public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService
59 { 59 {
60 private static readonly ILog m_log = 60 private static readonly ILog m_log =
@@ -107,8 +107,6 @@ namespace Flotsam.RegionModules.AssetCache
107 private IAssetService m_AssetService; 107 private IAssetService m_AssetService;
108 private List<Scene> m_Scenes = new List<Scene>(); 108 private List<Scene> m_Scenes = new List<Scene>();
109 109
110 private bool m_DeepScanBeforePurge;
111
112 public FlotsamAssetCache() 110 public FlotsamAssetCache()
113 { 111 {
114 m_InvalidChars.AddRange(Path.GetInvalidPathChars()); 112 m_InvalidChars.AddRange(Path.GetInvalidPathChars());
@@ -170,8 +168,6 @@ namespace Flotsam.RegionModules.AssetCache
170 m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen); 168 m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen);
171 169
172 m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt); 170 m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt);
173
174 m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge);
175 } 171 }
176 172
177 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); 173 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
@@ -226,10 +222,6 @@ namespace Flotsam.RegionModules.AssetCache
226 scene.RegisterModuleInterface<IImprovedAssetCache>(this); 222 scene.RegisterModuleInterface<IImprovedAssetCache>(this);
227 m_Scenes.Add(scene); 223 m_Scenes.Add(scene);
228 224
229 if (m_AssetService == null)
230 {
231 m_AssetService = scene.RequestModuleInterface<IAssetService>();
232 }
233 } 225 }
234 } 226 }
235 227
@@ -244,6 +236,8 @@ namespace Flotsam.RegionModules.AssetCache
244 236
245 public void RegionLoaded(Scene scene) 237 public void RegionLoaded(Scene scene)
246 { 238 {
239 if (m_Enabled && m_AssetService == null)
240 m_AssetService = scene.RequestModuleInterface<IAssetService>();
247 } 241 }
248 242
249 //////////////////////////////////////////////////////////// 243 ////////////////////////////////////////////////////////////
@@ -519,13 +513,10 @@ namespace Flotsam.RegionModules.AssetCache
519 // Purge all files last accessed prior to this point 513 // Purge all files last accessed prior to this point
520 DateTime purgeLine = DateTime.Now - m_FileExpiration; 514 DateTime purgeLine = DateTime.Now - m_FileExpiration;
521 515
522 // An optional deep scan at this point will ensure assets present in scenes, 516 // An asset cache may contain local non-temporary assets that are not in the asset service. Therefore,
523 // or referenced by objects in the scene, but not recently accessed 517 // before cleaning up expired files we must scan the objects in the scene to make sure that we retain
524 // are not purged. 518 // such local assets if they have not been recently accessed.
525 if (m_DeepScanBeforePurge) 519 TouchAllSceneAssets(false);
526 {
527 CacheScenes();
528 }
529 520
530 foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) 521 foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
531 { 522 {
@@ -718,11 +709,14 @@ namespace Flotsam.RegionModules.AssetCache
718 709
719 /// <summary> 710 /// <summary>
720 /// Iterates through all Scenes, doing a deep scan through assets 711 /// Iterates through all Scenes, doing a deep scan through assets
721 /// to cache all assets present in the scene or referenced by assets 712 /// to update the access time of all assets present in the scene or referenced by assets
722 /// in the scene 713 /// in the scene.
723 /// </summary> 714 /// </summary>
724 /// <returns></returns> 715 /// <param name="storeUncached">
725 private int CacheScenes() 716 /// If true, then assets scanned which are not found in cache are added to the cache.
717 /// </param>
718 /// <returns>Number of distinct asset references found in the scene.</returns>
719 private int TouchAllSceneAssets(bool storeUncached)
726 { 720 {
727 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 721 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
728 722
@@ -745,7 +739,7 @@ namespace Flotsam.RegionModules.AssetCache
745 { 739 {
746 File.SetLastAccessTime(filename, DateTime.Now); 740 File.SetLastAccessTime(filename, DateTime.Now);
747 } 741 }
748 else 742 else if (storeUncached)
749 { 743 {
750 m_AssetService.Get(assetID.ToString()); 744 m_AssetService.Get(assetID.ToString());
751 } 745 }
@@ -873,13 +867,14 @@ namespace Flotsam.RegionModules.AssetCache
873 867
874 break; 868 break;
875 869
876
877 case "assets": 870 case "assets":
878 m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes."); 871 m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes.");
879 872
880 Util.FireAndForget(delegate { 873 Util.FireAndForget(delegate {
881 int assetsCached = CacheScenes(); 874 int assetReferenceTotal = TouchAllSceneAssets(true);
882 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached); 875 m_log.InfoFormat(
876 "[FLOTSAM ASSET CACHE]: Completed check with {0} assets.",
877 assetReferenceTotal);
883 }); 878 });
884 879
885 break; 880 break;
diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
index 1365e69..9592ca0 100644
--- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
@@ -31,6 +31,7 @@ using System.IO;
31using System.Collections.Generic; 31using System.Collections.Generic;
32using System.Reflection; 32using System.Reflection;
33using GlynnTucker.Cache; 33using GlynnTucker.Cache;
34using Mono.Addins;
34using Nini.Config; 35using Nini.Config;
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
@@ -39,6 +40,7 @@ using OpenSim.Services.Interfaces;
39 40
40namespace OpenSim.Region.CoreModules.Asset 41namespace OpenSim.Region.CoreModules.Asset
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GlynnTuckerAssetCache")]
42 public class GlynnTuckerAssetCache : ISharedRegionModule, IImprovedAssetCache 44 public class GlynnTuckerAssetCache : ISharedRegionModule, IImprovedAssetCache
43 { 45 {
44 private static readonly ILog m_log = 46 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
index c91b25f..1c2bfd0 100644
--- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -35,7 +35,6 @@ using Nini.Config;
35using NUnit.Framework; 35using NUnit.Framework;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenMetaverse.Assets; 37using OpenMetaverse.Assets;
38using Flotsam.RegionModules.AssetCache;
39using OpenSim.Framework; 38using OpenSim.Framework;
40using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
41using OpenSim.Region.Framework.Scenes.Serialization; 40using OpenSim.Region.Framework.Scenes.Serialization;
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 951afd7..acd156e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -286,6 +286,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
286 286
287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) 287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp)
288 { 288 {
289 if (!Enabled)
290 return false;
291
292 if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp))
293 {
294 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
295 return true;
296 }
297
298 return false;
299 }
300
301 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp)
302 {
289 lock (sp.AttachmentsSyncLock) 303 lock (sp.AttachmentsSyncLock)
290 { 304 {
291// m_log.DebugFormat( 305// m_log.DebugFormat(
@@ -461,6 +475,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
461 475
462 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) 476 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId)
463 { 477 {
478 DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity);
479 }
480
481 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot)
482 {
464 if (!Enabled) 483 if (!Enabled)
465 return; 484 return;
466 485
@@ -502,7 +521,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
502 so.FromItemID = UUID.Zero; 521 so.FromItemID = UUID.Zero;
503 522
504 SceneObjectPart rootPart = so.RootPart; 523 SceneObjectPart rootPart = so.RootPart;
505 so.AbsolutePosition = sp.AbsolutePosition; 524 so.AbsolutePosition = absolutePos;
525 if (absoluteRot != Quaternion.Identity)
526 {
527 so.UpdateGroupRotationR(absoluteRot);
528 }
506 so.AttachedAvatar = UUID.Zero; 529 so.AttachedAvatar = UUID.Zero;
507 rootPart.SetParentLocalId(0); 530 rootPart.SetParentLocalId(0);
508 so.ClearPartAttachmentData(); 531 so.ClearPartAttachmentData();
@@ -616,9 +639,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
616 639
617 if (grp.HasGroupChanged) 640 if (grp.HasGroupChanged)
618 { 641 {
619// m_log.DebugFormat( 642 m_log.DebugFormat(
620// "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", 643 "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
621// grp.UUID, grp.AttachmentPoint); 644 grp.UUID, grp.AttachmentPoint);
622 645
623 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); 646 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState);
624 647
@@ -862,7 +885,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
862 // This will throw if the attachment fails 885 // This will throw if the attachment fails
863 try 886 try
864 { 887 {
865 AttachObject(sp, objatt, attachmentPt, false, false, false); 888 AttachObjectInternal(sp, objatt, attachmentPt, false, false, false);
866 } 889 }
867 catch (Exception e) 890 catch (Exception e)
868 { 891 {
@@ -933,6 +956,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
933 956
934 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); 957 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID);
935 item = m_scene.InventoryService.GetItem(item); 958 item = m_scene.InventoryService.GetItem(item);
959 if (item == null)
960 return;
961
936 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); 962 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
937 if (changed && m_scene.AvatarFactory != null) 963 if (changed && m_scene.AvatarFactory != null)
938 { 964 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index d9a619d..4e9d3f9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -62,7 +62,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
62 public class AttachmentsModuleTests : OpenSimTestCase 62 public class AttachmentsModuleTests : OpenSimTestCase
63 { 63 {
64 private AutoResetEvent m_chatEvent = new AutoResetEvent(false); 64 private AutoResetEvent m_chatEvent = new AutoResetEvent(false);
65 private OSChatMessage m_osChatMessageReceived; 65// private OSChatMessage m_osChatMessageReceived;
66
67 // Used to test whether the operations have fired the attach event. Must be reset after each test.
68 private int m_numberOfAttachEventsFired;
66 69
67 [TestFixtureSetUp] 70 [TestFixtureSetUp]
68 public void FixtureInit() 71 public void FixtureInit()
@@ -83,7 +86,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
83 { 86 {
84// Console.WriteLine("Got chat [{0}]", oscm.Message); 87// Console.WriteLine("Got chat [{0}]", oscm.Message);
85 88
86 m_osChatMessageReceived = oscm; 89// m_osChatMessageReceived = oscm;
87 m_chatEvent.Set(); 90 m_chatEvent.Set();
88 } 91 }
89 92
@@ -99,6 +102,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
99 "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); 102 "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config);
100 SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); 103 SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
101 104
105 scene.EventManager.OnAttach += (localID, itemID, avatarID) => m_numberOfAttachEventsFired++;
106
102 return scene; 107 return scene;
103 } 108 }
104 109
@@ -181,6 +186,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
181 TestHelpers.InMethod(); 186 TestHelpers.InMethod();
182// TestHelpers.EnableLogging(); 187// TestHelpers.EnableLogging();
183 188
189 m_numberOfAttachEventsFired = 0;
190
184 Scene scene = CreateTestScene(); 191 Scene scene = CreateTestScene();
185 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); 192 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
186 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); 193 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
@@ -189,6 +196,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
189 196
190 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); 197 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
191 198
199 m_numberOfAttachEventsFired = 0;
192 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false); 200 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
193 201
194 // Check status on scene presence 202 // Check status on scene presence
@@ -216,7 +224,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
216 224
217 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 225 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
218 226
219// TestHelpers.DisableLogging(); 227 // Check events
228 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
220 } 229 }
221 230
222 /// <summary> 231 /// <summary>
@@ -228,6 +237,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
228 TestHelpers.InMethod(); 237 TestHelpers.InMethod();
229// TestHelpers.EnableLogging(); 238// TestHelpers.EnableLogging();
230 239
240 m_numberOfAttachEventsFired = 0;
241
231 Scene scene = CreateTestScene(); 242 Scene scene = CreateTestScene();
232 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); 243 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
233 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); 244 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
@@ -247,6 +258,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
247 258
248 Assert.That(sp.HasAttachments(), Is.False); 259 Assert.That(sp.HasAttachments(), Is.False);
249 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 260 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
261
262 // Check events
263 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
250 } 264 }
251 265
252 [Test] 266 [Test]
@@ -261,6 +275,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
261 275
262 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); 276 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
263 277
278 m_numberOfAttachEventsFired = 0;
264 scene.AttachmentsModule.RezSingleAttachmentFromInventory( 279 scene.AttachmentsModule.RezSingleAttachmentFromInventory(
265 sp, attItem.ID, (uint)AttachmentPoint.Chest); 280 sp, attItem.ID, (uint)AttachmentPoint.Chest);
266 281
@@ -280,6 +295,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
280 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 295 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
281 296
282 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 297 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
298
299 // Check events
300 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
283 } 301 }
284 302
285 /// <summary> 303 /// <summary>
@@ -338,6 +356,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
338 ISceneEntity so 356 ISceneEntity so
339 = scene.AttachmentsModule.RezSingleAttachmentFromInventory( 357 = scene.AttachmentsModule.RezSingleAttachmentFromInventory(
340 sp, attItem.ID, (uint)AttachmentPoint.Chest); 358 sp, attItem.ID, (uint)AttachmentPoint.Chest);
359
360 m_numberOfAttachEventsFired = 0;
341 scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId); 361 scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId);
342 362
343 // Check scene presence status 363 // Check scene presence status
@@ -353,6 +373,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
353 373
354 // Check object in scene 374 // Check object in scene
355 Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null); 375 Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null);
376
377 // Check events
378 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
356 } 379 }
357 380
358 [Test] 381 [Test]
@@ -369,6 +392,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
369 SceneObjectGroup so 392 SceneObjectGroup so
370 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory( 393 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(
371 sp, attItem.ID, (uint)AttachmentPoint.Chest); 394 sp, attItem.ID, (uint)AttachmentPoint.Chest);
395
396 m_numberOfAttachEventsFired = 0;
372 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so); 397 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so);
373 398
374 // Check status on scene presence 399 // Check status on scene presence
@@ -380,6 +405,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
380 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); 405 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0));
381 406
382 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); 407 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0));
408
409 // Check events
410 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
383 } 411 }
384 412
385 /// <summary> 413 /// <summary>
@@ -461,10 +489,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
461 489
462 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; 490 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
463 491
464 scene.IncomingCloseAgent(presence.UUID); 492 m_numberOfAttachEventsFired = 0;
493 scene.IncomingCloseAgent(presence.UUID, false);
465 494
466 // Check that we can't retrieve this attachment from the scene. 495 // Check that we can't retrieve this attachment from the scene.
467 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); 496 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);
497
498 // Check events
499 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
468 } 500 }
469 501
470 [Test] 502 [Test]
@@ -480,6 +512,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
480 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); 512 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
481 acd.Appearance = new AvatarAppearance(); 513 acd.Appearance = new AvatarAppearance();
482 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); 514 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
515
516 m_numberOfAttachEventsFired = 0;
483 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); 517 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
484 518
485 Assert.That(presence.HasAttachments(), Is.True); 519 Assert.That(presence.HasAttachments(), Is.True);
@@ -502,6 +536,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
502 Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 536 Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
503 537
504 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 538 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
539
540 // Check events. We expect OnAttach to fire on login.
541 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
505 } 542 }
506 543
507 [Test] 544 [Test]
@@ -522,10 +559,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
522 559
523 Vector3 newPosition = new Vector3(1, 2, 4); 560 Vector3 newPosition = new Vector3(1, 2, 4);
524 561
562 m_numberOfAttachEventsFired = 0;
525 scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient); 563 scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient);
526 564
527 Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition)); 565 Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition));
528 Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition)); 566 Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition));
567
568 // Check events
569 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
529 } 570 }
530 571
531 [Test] 572 [Test]
@@ -574,6 +615,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
574 Vector3 teleportPosition = new Vector3(10, 11, 12); 615 Vector3 teleportPosition = new Vector3(10, 11, 12);
575 Vector3 teleportLookAt = new Vector3(20, 21, 22); 616 Vector3 teleportLookAt = new Vector3(20, 21, 22);
576 617
618 m_numberOfAttachEventsFired = 0;
577 sceneA.RequestTeleportLocation( 619 sceneA.RequestTeleportLocation(
578 beforeTeleportSp.ControllingClient, 620 beforeTeleportSp.ControllingClient,
579 sceneB.RegionInfo.RegionHandle, 621 sceneB.RegionInfo.RegionHandle,
@@ -616,29 +658,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
616 Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); 658 Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0));
617 659
618 Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); 660 Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0));
619 }
620 661
621 // I'm commenting this test because scene setup NEEDS InventoryService to 662 // Check events
622 // be non-null 663 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
623 //[Test] 664 }
624// public void T032_CrossAttachments()
625// {
626// TestHelpers.InMethod();
627//
628// ScenePresence presence = scene.GetScenePresence(agent1);
629// ScenePresence presence2 = scene2.GetScenePresence(agent1);
630// presence2.AddAttachment(sog1);
631// presence2.AddAttachment(sog2);
632//
633// ISharedRegionModule serialiser = new SerialiserModule();
634// SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), serialiser);
635// SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), serialiser);
636//
637// Assert.That(presence.HasAttachments(), Is.False, "Presence has attachments before cross");
638//
639// //Assert.That(presence2.CrossAttachmentsIntoNewRegion(region1, true), Is.True, "Cross was not successful");
640// Assert.That(presence2.HasAttachments(), Is.False, "Presence2 objects were not deleted");
641// Assert.That(presence.HasAttachments(), Is.True, "Presence has not received new objects");
642// }
643 } 665 }
644} 666}
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 4cb4370..8496005 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -39,9 +39,12 @@ using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
41 41
42using Mono.Addins;
43
42namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory 44namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
43{ 45{
44 public class AvatarFactoryModule : IAvatarFactoryModule, IRegionModule 46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AvatarFactoryModule")]
47 public class AvatarFactoryModule : IAvatarFactoryModule, INonSharedRegionModule
45 { 48 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 50
@@ -59,12 +62,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
59 62
60 private object m_setAppearanceLock = new object(); 63 private object m_setAppearanceLock = new object();
61 64
62 #region IRegionModule 65 #region Region Module interface
63 66
64 public void Initialise(Scene scene, IConfigSource config) 67 public void Initialise(IConfigSource config)
65 { 68 {
66 scene.RegisterModuleInterface<IAvatarFactoryModule>(this);
67 scene.EventManager.OnNewClient += SubscribeToClientEvents;
68 69
69 IConfig appearanceConfig = config.Configs["Appearance"]; 70 IConfig appearanceConfig = config.Configs["Appearance"];
70 if (appearanceConfig != null) 71 if (appearanceConfig != null)
@@ -74,11 +75,29 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
74 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime); 75 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
75 } 76 }
76 77
78 }
79
80 public void AddRegion(Scene scene)
81 {
77 if (m_scene == null) 82 if (m_scene == null)
78 m_scene = scene; 83 m_scene = scene;
84
85 scene.RegisterModuleInterface<IAvatarFactoryModule>(this);
86 scene.EventManager.OnNewClient += SubscribeToClientEvents;
87 }
88
89 public void RemoveRegion(Scene scene)
90 {
91 if (scene == m_scene)
92 {
93 scene.UnregisterModuleInterface<IAvatarFactoryModule>(this);
94 scene.EventManager.OnNewClient -= SubscribeToClientEvents;
95 }
96
97 m_scene = null;
79 } 98 }
80 99
81 public void PostInitialise() 100 public void RegionLoaded(Scene scene)
82 { 101 {
83 m_updateTimer.Enabled = false; 102 m_updateTimer.Enabled = false;
84 m_updateTimer.AutoReset = true; 103 m_updateTimer.AutoReset = true;
@@ -100,6 +119,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
100 get { return false; } 119 get { return false; }
101 } 120 }
102 121
122 public Type ReplaceableInterface
123 {
124 get { return null; }
125 }
126
127
103 private void SubscribeToClientEvents(IClientAPI client) 128 private void SubscribeToClientEvents(IClientAPI client)
104 { 129 {
105 client.OnRequestWearables += Client_OnRequestWearables; 130 client.OnRequestWearables += Client_OnRequestWearables;
@@ -533,6 +558,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
533 // Ignore ruth's assets 558 // Ignore ruth's assets
534 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) 559 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
535 continue; 560 continue;
561
536 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); 562 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
537 baseItem = invService.GetItem(baseItem); 563 baseItem = invService.GetItem(baseItem);
538 564
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index dbbb0ae..4c3f1cc 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using Mono.Addins;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
@@ -37,6 +38,7 @@ using OpenSim.Region.Framework.Scenes;
37 38
38namespace OpenSim.Region.CoreModules.Avatar.Chat 39namespace OpenSim.Region.CoreModules.Avatar.Chat
39{ 40{
41 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ChatModule")]
40 public class ChatModule : ISharedRegionModule 42 public class ChatModule : ISharedRegionModule
41 { 43 {
42 private static readonly ILog m_log = 44 private static readonly ILog m_log =
@@ -197,6 +199,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
197 string fromName = c.From; 199 string fromName = c.From;
198 string fromNamePrefix = ""; 200 string fromNamePrefix = "";
199 UUID fromID = UUID.Zero; 201 UUID fromID = UUID.Zero;
202 UUID ownerID = UUID.Zero;
200 string message = c.Message; 203 string message = c.Message;
201 IScene scene = c.Scene; 204 IScene scene = c.Scene;
202 UUID destination = c.Destination; 205 UUID destination = c.Destination;
@@ -224,11 +227,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
224 fromNamePrefix = m_adminPrefix; 227 fromNamePrefix = m_adminPrefix;
225 } 228 }
226 destination = UUID.Zero; // Avatars cant "SayTo" 229 destination = UUID.Zero; // Avatars cant "SayTo"
230 ownerID = c.Sender.AgentId;
231
227 break; 232 break;
228 233
229 case ChatSourceType.Object: 234 case ChatSourceType.Object:
230 fromID = c.SenderUUID; 235 fromID = c.SenderUUID;
231 236
237 if (c.SenderObject != null && c.SenderObject is SceneObjectPart)
238 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
239
232 break; 240 break;
233 } 241 }
234 242
@@ -262,8 +270,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
262 // objects on a parcel with access restrictions 270 // objects on a parcel with access restrictions
263 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) 271 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
264 { 272 {
265 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix + fromName, c.Type, message, sourceType)) 273 if (destination != UUID.Zero)
266 receiverIDs.Add(presence.UUID); 274 {
275 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true))
276 receiverIDs.Add(presence.UUID);
277 }
278 else
279 {
280 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false))
281 receiverIDs.Add(presence.UUID);
282 }
267 } 283 }
268 } 284 }
269 } 285 }
@@ -324,7 +340,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
324 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 340 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
325 return; 341 return;
326 342
327 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, 343 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID,
328 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 344 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
329 receiverIDs.Add(client.AgentId); 345 receiverIDs.Add(client.AgentId);
330 } 346 }
@@ -341,15 +357,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
341 /// <param name="fromPos"></param> 357 /// <param name="fromPos"></param>
342 /// <param name="regionPos">/param> 358 /// <param name="regionPos">/param>
343 /// <param name="fromAgentID"></param> 359 /// <param name="fromAgentID"></param>
360 /// <param name='ownerID'>
361 /// Owner of the message. For at least some messages from objects, this has to be correctly filled with the owner's UUID.
362 /// This is the case for script error messages in viewer 3 since LLViewer change EXT-7762
363 /// </param>
344 /// <param name="fromName"></param> 364 /// <param name="fromName"></param>
345 /// <param name="type"></param> 365 /// <param name="type"></param>
346 /// <param name="message"></param> 366 /// <param name="message"></param>
347 /// <param name="src"></param> 367 /// <param name="src"></param>
348 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a 368 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a
349 /// precondition</returns> 369 /// precondition</returns>
350 protected virtual bool TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, 370 protected virtual bool TrySendChatMessage(
351 UUID fromAgentID, string fromName, ChatTypeEnum type, 371 ScenePresence presence, Vector3 fromPos, Vector3 regionPos,
352 string message, ChatSourceType src) 372 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type,
373 string message, ChatSourceType src, bool ignoreDistance)
353 { 374 {
354 // don't send chat to child agents 375 // don't send chat to child agents
355 if (presence.IsChildAgent) return false; 376 if (presence.IsChildAgent) return false;
@@ -369,8 +390,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
369 } 390 }
370 391
371 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView 392 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
372 presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, 393 presence.ControllingClient.SendChatMessage(
373 fromAgentID, (byte)src, (byte)ChatAudibleLevel.Fully); 394 message, (byte) type, fromPos, fromName,
395 fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully);
374 396
375 return true; 397 return true;
376 } 398 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
index 3a91465..343cdb5 100644
--- a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs
@@ -33,9 +33,12 @@ using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Region.Framework.Scenes; 33using OpenSim.Region.Framework.Scenes;
34using OpenMetaverse; 34using OpenMetaverse;
35 35
36using Mono.Addins;
37
36namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule 38namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
37{ 39{
38 public class CombatModule : IRegionModule 40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CombatModule")]
41 public class CombatModule : ISharedRegionModule
39 { 42 {
40 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 43 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41 44
@@ -54,7 +57,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
54 /// </summary> 57 /// </summary>
55 /// <param name="scene"></param> 58 /// <param name="scene"></param>
56 /// <param name="config"></param> 59 /// <param name="config"></param>
57 public void Initialise(Scene scene, IConfigSource config) 60 public void Initialise(IConfigSource config)
61 {
62 }
63
64 public void AddRegion(Scene scene)
58 { 65 {
59 lock (m_scenel) 66 lock (m_scenel)
60 { 67 {
@@ -72,6 +79,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
72 scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; 79 scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
73 } 80 }
74 81
82 public void RemoveRegion(Scene scene)
83 {
84 if (m_scenel.ContainsKey(scene.RegionInfo.RegionHandle))
85 m_scenel.Remove(scene.RegionInfo.RegionHandle);
86
87 scene.EventManager.OnAvatarKilled -= KillAvatar;
88 scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel;
89 }
90
91 public void RegionLoaded(Scene scene)
92 {
93 }
94
75 public void PostInitialise() 95 public void PostInitialise()
76 { 96 {
77 } 97 }
@@ -85,11 +105,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule
85 get { return "CombatModule"; } 105 get { return "CombatModule"; }
86 } 106 }
87 107
88 public bool IsSharedModule 108 public Type ReplaceableInterface
89 { 109 {
90 get { return true; } 110 get { return null; }
91 } 111 }
92 112
113
93 private void KillAvatar(uint killerObjectLocalID, ScenePresence deadAvatar) 114 private void KillAvatar(uint killerObjectLocalID, ScenePresence deadAvatar)
94 { 115 {
95 string deadAvatarMessage; 116 string deadAvatarMessage;
diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
index 3c294bb..0e7ab7e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs
@@ -32,6 +32,7 @@ using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using Mono.Addins;
35 36
36using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
@@ -39,16 +40,27 @@ using OpenSim.Services.Interfaces;
39 40
40namespace OpenSim.Region.CoreModules.Avatar.Dialog 41namespace OpenSim.Region.CoreModules.Avatar.Dialog
41{ 42{
42 public class DialogModule : IRegionModule, IDialogModule 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DialogModule")]
43 { 44 public class DialogModule : IDialogModule, INonSharedRegionModule
45 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 47
46 protected Scene m_scene; 48 protected Scene m_scene;
47 49
48 public void Initialise(Scene scene, IConfigSource source) 50 public void Initialise(IConfigSource source) { }
51
52 public Type ReplaceableInterface { get { return null; } }
53
54 public void AddRegion(Scene scene)
49 { 55 {
50 m_scene = scene; 56 m_scene = scene;
51 m_scene.RegisterModuleInterface<IDialogModule>(this); 57 m_scene.RegisterModuleInterface<IDialogModule>(this);
58 }
59
60 public void RegionLoaded(Scene scene)
61 {
62 if (scene != m_scene)
63 return;
52 64
53 m_scene.AddCommand( 65 m_scene.AddCommand(
54 "Users", this, "alert", "alert <message>", 66 "Users", this, "alert", "alert <message>",
@@ -56,46 +68,59 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
56 HandleAlertConsoleCommand); 68 HandleAlertConsoleCommand);
57 69
58 m_scene.AddCommand( 70 m_scene.AddCommand(
59 "Users", this, "alert-user", "alert-user <first> <last> <message>", 71 "Users", this, "alert-user",
72 "alert-user <first> <last> <message>",
60 "Send an alert to a user", 73 "Send an alert to a user",
61 HandleAlertConsoleCommand); 74 HandleAlertConsoleCommand);
62 } 75 }
63 76
64 public void PostInitialise() {} 77 public void RemoveRegion(Scene scene)
65 public void Close() {} 78 {
79 if (scene != m_scene)
80 return;
81
82 m_scene.UnregisterModuleInterface<IDialogModule>(this);
83 }
84
85 public void Close() { }
66 public string Name { get { return "Dialog Module"; } } 86 public string Name { get { return "Dialog Module"; } }
67 public bool IsSharedModule { get { return false; } } 87
68
69 public void SendAlertToUser(IClientAPI client, string message) 88 public void SendAlertToUser(IClientAPI client, string message)
70 { 89 {
71 SendAlertToUser(client, message, false); 90 SendAlertToUser(client, message, false);
72 } 91 }
73 92
74 public void SendAlertToUser(IClientAPI client, string message, bool modal) 93 public void SendAlertToUser(IClientAPI client, string message,
94 bool modal)
75 { 95 {
76 client.SendAgentAlertMessage(message, modal); 96 client.SendAgentAlertMessage(message, modal);
77 } 97 }
78 98
79 public void SendAlertToUser(UUID agentID, string message) 99 public void SendAlertToUser(UUID agentID, string message)
80 { 100 {
81 SendAlertToUser(agentID, message, false); 101 SendAlertToUser(agentID, message, false);
82 } 102 }
83 103
84 public void SendAlertToUser(UUID agentID, string message, bool modal) 104 public void SendAlertToUser(UUID agentID, string message, bool modal)
85 { 105 {
86 ScenePresence sp = m_scene.GetScenePresence(agentID); 106 ScenePresence sp = m_scene.GetScenePresence(agentID);
87 107
88 if (sp != null) 108 if (sp != null)
89 sp.ControllingClient.SendAgentAlertMessage(message, modal); 109 sp.ControllingClient.SendAgentAlertMessage(message, modal);
90 } 110 }
91 111
92 public void SendAlertToUser(string firstName, string lastName, string message, bool modal) 112 public void SendAlertToUser(string firstName, string lastName,
113 string message, bool modal)
93 { 114 {
94 ScenePresence presence = m_scene.GetScenePresence(firstName, lastName); 115 ScenePresence presence = m_scene.GetScenePresence(firstName,
116 lastName);
95 if (presence != null) 117 if (presence != null)
96 presence.ControllingClient.SendAgentAlertMessage(message, modal); 118 {
119 presence.ControllingClient.SendAgentAlertMessage(message,
120 modal);
121 }
97 } 122 }
98 123
99 public void SendGeneralAlert(string message) 124 public void SendGeneralAlert(string message)
100 { 125 {
101 m_scene.ForEachRootClient(delegate(IClientAPI client) 126 m_scene.ForEachRootClient(delegate(IClientAPI client)
@@ -104,11 +129,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
104 }); 129 });
105 } 130 }
106 131
107 public void SendDialogToUser( 132 public void SendDialogToUser(UUID avatarID, string objectName,
108 UUID avatarID, string objectName, UUID objectID, UUID ownerID, 133 UUID objectID, UUID ownerID, string message, UUID textureID,
109 string message, UUID textureID, int ch, string[] buttonlabels) 134 int ch, string[] buttonlabels)
110 { 135 {
111 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, ownerID); 136 UserAccount account = m_scene.UserAccountService.GetUserAccount(
137 m_scene.RegionInfo.ScopeID, ownerID);
112 string ownerFirstName, ownerLastName; 138 string ownerFirstName, ownerLastName;
113 if (account != null) 139 if (account != null)
114 { 140 {
@@ -123,29 +149,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
123 149
124 ScenePresence sp = m_scene.GetScenePresence(avatarID); 150 ScenePresence sp = m_scene.GetScenePresence(avatarID);
125 if (sp != null) 151 if (sp != null)
126 sp.ControllingClient.SendDialog( 152 {
127 objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); 153 sp.ControllingClient.SendDialog(objectName, objectID, ownerID,
154 ownerFirstName, ownerLastName, message, textureID, ch,
155 buttonlabels);
156 }
128 } 157 }
129 158
130 public void SendUrlToUser( 159 public void SendUrlToUser(UUID avatarID, string objectName,
131 UUID avatarID, string objectName, UUID objectID, UUID ownerID, bool groupOwned, string message, string url) 160 UUID objectID, UUID ownerID, bool groupOwned, string message,
161 string url)
132 { 162 {
133 ScenePresence sp = m_scene.GetScenePresence(avatarID); 163 ScenePresence sp = m_scene.GetScenePresence(avatarID);
134 164
135 if (sp != null) 165 if (sp != null)
136 sp.ControllingClient.SendLoadURL(objectName, objectID, ownerID, groupOwned, message, url); 166 {
167 sp.ControllingClient.SendLoadURL(objectName, objectID,
168 ownerID, groupOwned, message, url);
169 }
137 } 170 }
138 171
139 public void SendTextBoxToUser(UUID avatarid, string message, int chatChannel, string name, UUID objectid, UUID ownerid) 172 public void SendTextBoxToUser(UUID avatarid, string message,
173 int chatChannel, string name, UUID objectid, UUID ownerid)
140 { 174 {
141 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, ownerid); 175 UserAccount account = m_scene.UserAccountService.GetUserAccount(
176 m_scene.RegionInfo.ScopeID, ownerid);
142 string ownerFirstName, ownerLastName; 177 string ownerFirstName, ownerLastName;
143 UUID ownerID = UUID.Zero; 178 UUID ownerID = UUID.Zero;
144 if (account != null) 179 if (account != null)
145 { 180 {
146 ownerFirstName = account.FirstName; 181 ownerFirstName = account.FirstName;
147 ownerLastName = account.LastName; 182 ownerLastName = account.LastName;
148 ownerID = account.PrincipalID; 183 ownerID = account.PrincipalID;
149 } 184 }
150 else 185 else
151 { 186 {
@@ -154,29 +189,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
154 } 189 }
155 190
156 ScenePresence sp = m_scene.GetScenePresence(avatarid); 191 ScenePresence sp = m_scene.GetScenePresence(avatarid);
157 192
158 if (sp != null) 193 if (sp != null)
159 sp.ControllingClient.SendTextBoxRequest(message, chatChannel, name, ownerID, ownerFirstName, ownerLastName, objectid); 194 {
195 sp.ControllingClient.SendTextBoxRequest(message, chatChannel,
196 name, ownerID, ownerFirstName, ownerLastName,
197 objectid);
198 }
160 } 199 }
161 200
162 public void SendNotificationToUsersInRegion( 201 public void SendNotificationToUsersInRegion(UUID fromAvatarID,
163 UUID fromAvatarID, string fromAvatarName, string message) 202 string fromAvatarName, string message)
164 { 203 {
165 m_scene.ForEachRootClient(delegate(IClientAPI client) 204 m_scene.ForEachRootClient(delegate(IClientAPI client)
166 { 205 {
167 client.SendBlueBoxMessage(fromAvatarID, fromAvatarName, message); 206 client.SendBlueBoxMessage(fromAvatarID, fromAvatarName,
207 message);
168 }); 208 });
169 } 209 }
170 210
171 /// <summary> 211 /// <summary>
172 /// Handle an alert command from the console. 212 /// Handle an alert command from the console.
173 /// </summary> 213 /// </summary>
174 /// <param name="module"></param> 214 /// <param name="module"></param>
175 /// <param name="cmdparams"></param> 215 /// <param name="cmdparams"></param>
176 public void HandleAlertConsoleCommand(string module, string[] cmdparams) 216 public void HandleAlertConsoleCommand(string module,
217 string[] cmdparams)
177 { 218 {
178 if (m_scene.ConsoleScene() != null && m_scene.ConsoleScene() != m_scene) 219 if (m_scene.ConsoleScene() != null &&
220 m_scene.ConsoleScene() != m_scene)
221 {
179 return; 222 return;
223 }
180 224
181 string message = string.Empty; 225 string message = string.Empty;
182 226
@@ -184,7 +228,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
184 { 228 {
185 message = CombineParams(cmdparams, 1); 229 message = CombineParams(cmdparams, 1);
186 m_log.InfoFormat("[DIALOG]: Sending general alert in region {0} with message {1}", 230 m_log.InfoFormat("[DIALOG]: Sending general alert in region {0} with message {1}",
187 m_scene.RegionInfo.RegionName, message); 231 m_scene.RegionInfo.RegionName, message);
188 SendGeneralAlert(message); 232 SendGeneralAlert(message);
189 } 233 }
190 else if (cmdparams.Length > 3) 234 else if (cmdparams.Length > 3)
@@ -192,9 +236,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
192 string firstName = cmdparams[1]; 236 string firstName = cmdparams[1];
193 string lastName = cmdparams[2]; 237 string lastName = cmdparams[2];
194 message = CombineParams(cmdparams, 3); 238 message = CombineParams(cmdparams, 3);
195 m_log.InfoFormat( 239 m_log.InfoFormat("[DIALOG]: Sending alert in region {0} to {1} {2} with message {3}",
196 "[DIALOG]: Sending alert in region {0} to {1} {2} with message {3}", 240 m_scene.RegionInfo.RegionName, firstName, lastName,
197 m_scene.RegionInfo.RegionName, firstName, lastName, message); 241 message);
198 SendAlertToUser(firstName, lastName, message, false); 242 SendAlertToUser(firstName, lastName, message, false);
199 } 243 }
200 else 244 else
@@ -212,7 +256,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog
212 { 256 {
213 result += commandParams[i] + " "; 257 result += commandParams[i] + " ";
214 } 258 }
215 259
216 return result; 260 return result;
217 } 261 }
218 } 262 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
index d942e87..5ec0ea9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
@@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
141 client.FirstName+" "+client.LastName, 141 client.FirstName+" "+client.LastName,
142 destID, (byte)211, false, 142 destID, (byte)211, false,
143 String.Empty, 143 String.Empty,
144 transactionID, false, new Vector3(), new byte[0]), 144 transactionID, false, new Vector3(), new byte[0], true),
145 delegate(bool success) {} ); 145 delegate(bool success) {} );
146 } 146 }
147 } 147 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 24ec435..8056030 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -28,12 +28,14 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Linq;
31using System.Reflection; 32using System.Reflection;
32using System.Threading; 33using System.Threading;
33using log4net; 34using log4net;
34using Nini.Config; 35using Nini.Config;
35using Nwc.XmlRpc; 36using Nwc.XmlRpc;
36using OpenMetaverse; 37using OpenMetaverse;
38using Mono.Addins;
37using OpenSim.Framework; 39using OpenSim.Framework;
38using OpenSim.Framework.Servers.HttpServer; 40using OpenSim.Framework.Servers.HttpServer;
39using OpenSim.Framework.Communications; 41using OpenSim.Framework.Communications;
@@ -49,6 +51,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
49 51
50namespace OpenSim.Region.CoreModules.Avatar.Friends 52namespace OpenSim.Region.CoreModules.Avatar.Friends
51{ 53{
54 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "FriendsModule")]
52 public class FriendsModule : ISharedRegionModule, IFriendsModule 55 public class FriendsModule : ISharedRegionModule, IFriendsModule
53 { 56 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 57 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -482,9 +485,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
482 Util.FireAndForget( 485 Util.FireAndForget(
483 delegate 486 delegate
484 { 487 {
485 m_log.DebugFormat( 488// m_log.DebugFormat(
486 "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", 489// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}",
487 friendList.Count, agentID, online); 490// friendList.Count, agentID, online);
488 491
489 // Notify about this user status 492 // Notify about this user status
490 StatusNotify(friendList, agentID, online); 493 StatusNotify(friendList, agentID, online);
@@ -495,42 +498,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
495 498
496 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online) 499 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
497 { 500 {
498 foreach (FriendInfo friend in friendList) 501 List<string> friendStringIds = friendList.ConvertAll<string>(friend => friend.Friend);
502 List<string> remoteFriendStringIds = new List<string>();
503 foreach (string friendStringId in friendStringIds)
499 { 504 {
500 UUID friendID; 505 UUID friendUuid;
501 if (UUID.TryParse(friend.Friend, out friendID)) 506 if (UUID.TryParse(friendStringId, out friendUuid))
502 { 507 {
503 // Try local 508 if (LocalStatusNotification(userID, friendUuid, online))
504 if (LocalStatusNotification(userID, friendID, online))
505 continue; 509 continue;
506 510
507 // The friend is not here [as root]. Let's forward. 511 remoteFriendStringIds.Add(friendStringId);
508 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
509 if (friendSessions != null && friendSessions.Length > 0)
510 {
511 PresenceInfo friendSession = null;
512 foreach (PresenceInfo pinfo in friendSessions)
513 {
514 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
515 {
516 friendSession = pinfo;
517 break;
518 }
519 }
520
521 if (friendSession != null)
522 {
523 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
524 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
525 m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
526 }
527 }
528
529 // Friend is not online. Ignore.
530 } 512 }
531 else 513 else
532 { 514 {
533 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); 515 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friendStringId);
516 }
517 }
518
519 // We do this regrouping so that we can efficiently send a single request rather than one for each
520 // friend in what may be a very large friends list.
521 PresenceInfo[] friendSessions = PresenceService.GetAgents(remoteFriendStringIds.ToArray());
522
523 foreach (PresenceInfo friendSession in friendSessions)
524 {
525 // let's guard against sessions-gone-bad
526 if (friendSession.RegionID != UUID.Zero)
527 {
528 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
529 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
530 m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online);
534 } 531 }
535 } 532 }
536 } 533 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index 06f27e2..bf5c0bb 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -46,6 +46,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
46 46
47namespace OpenSim.Region.CoreModules.Avatar.Friends 47namespace OpenSim.Region.CoreModules.Avatar.Friends
48{ 48{
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGFriendsModule")]
49 public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule, IFriendsSimConnector 50 public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule, IFriendsSimConnector
50 { 51 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs b/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs
index 7df2beb..095c57b 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs
@@ -25,6 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
28using System.Reflection; 29using System.Reflection;
29using log4net; 30using log4net;
30using Nini.Config; 31using Nini.Config;
@@ -35,26 +36,46 @@ using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
36using OpenSim.Services.Interfaces; 37using OpenSim.Services.Interfaces;
37 38
39using Mono.Addins;
40
38namespace OpenSim.Region.CoreModules.Avatar.Gestures 41namespace OpenSim.Region.CoreModules.Avatar.Gestures
39{ 42{
40 public class GesturesModule : IRegionModule 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GesturesModule")]
44 public class GesturesModule : INonSharedRegionModule
41 { 45 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 47
44 protected Scene m_scene; 48 protected Scene m_scene;
45 49
46 public void Initialise(Scene scene, IConfigSource source) 50 public void Initialise(IConfigSource source)
51 {
52 }
53
54 public void AddRegion(Scene scene)
47 { 55 {
48 m_scene = scene; 56 m_scene = scene;
49 57
50 m_scene.EventManager.OnNewClient += OnNewClient; 58 m_scene.EventManager.OnNewClient += OnNewClient;
51 } 59 }
60
61 public void RegionLoaded(Scene scene)
62 {
63 }
64
65 public void RemoveRegion(Scene scene)
66 {
67 m_scene.EventManager.OnNewClient -= OnNewClient;
68 m_scene = null;
69 }
52 70
53 public void PostInitialise() {}
54 public void Close() {} 71 public void Close() {}
55 public string Name { get { return "Gestures Module"; } } 72 public string Name { get { return "Gestures Module"; } }
56 public bool IsSharedModule { get { return false; } } 73
57 74 public Type ReplaceableInterface
75 {
76 get { return null; }
77 }
78
58 private void OnNewClient(IClientAPI client) 79 private void OnNewClient(IClientAPI client)
59 { 80 {
60 client.OnActivateGesture += ActivateGesture; 81 client.OnActivateGesture += ActivateGesture;
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 716cc69..9fa9be1 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -25,6 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
28using System.Collections.Generic; 29using System.Collections.Generic;
29using Nini.Config; 30using Nini.Config;
30using OpenMetaverse; 31using OpenMetaverse;
@@ -50,9 +51,12 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
50using OSDArray = OpenMetaverse.StructuredData.OSDArray; 51using OSDArray = OpenMetaverse.StructuredData.OSDArray;
51using OSDMap = OpenMetaverse.StructuredData.OSDMap; 52using OSDMap = OpenMetaverse.StructuredData.OSDMap;
52 53
54using Mono.Addins;
55
53namespace OpenSim.Region.CoreModules.Avatar.Gods 56namespace OpenSim.Region.CoreModules.Avatar.Gods
54{ 57{
55 public class GodsModule : IRegionModule, IGodsModule 58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GodsModule")]
59 public class GodsModule : INonSharedRegionModule, IGodsModule
56 { 60 {
57 private static readonly ILog m_log = 61 private static readonly ILog m_log =
58 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 62 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -66,10 +70,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
66 protected Dictionary<UUID, string> m_capsDict = 70 protected Dictionary<UUID, string> m_capsDict =
67 new Dictionary<UUID, string>(); 71 new Dictionary<UUID, string>();
68 72
69 public void Initialise(Scene scene, IConfigSource source) 73 protected IDialogModule DialogModule
74 {
75 get
76 {
77 if (m_dialogModule == null)
78 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
79
80 return m_dialogModule;
81 }
82 }
83
84 public void Initialise(IConfigSource source)
85 {
86 }
87
88 public void AddRegion(Scene scene)
70 { 89 {
71 m_scene = scene; 90 m_scene = scene;
72 m_dialogModule = m_scene.RequestModuleInterface<IDialogModule>();
73 m_scene.RegisterModuleInterface<IGodsModule>(this); 91 m_scene.RegisterModuleInterface<IGodsModule>(this);
74 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 92 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
75 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps; 93 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
@@ -77,12 +95,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
77 scene.EventManager.OnIncomingInstantMessage += 95 scene.EventManager.OnIncomingInstantMessage +=
78 OnIncomingInstantMessage; 96 OnIncomingInstantMessage;
79 } 97 }
80 98
81 public void PostInitialise() {} 99 public void RemoveRegion(Scene scene)
100 {
101 m_scene.UnregisterModuleInterface<IGodsModule>(this);
102 m_scene.EventManager.OnNewClient -= SubscribeToClientEvents;
103 m_scene = null;
104 }
105
106 public void RegionLoaded(Scene scene)
107 {
108 }
109
82 public void Close() {} 110 public void Close() {}
83 public string Name { get { return "Gods Module"; } } 111 public string Name { get { return "Gods Module"; } }
84 public bool IsSharedModule { get { return false; } } 112
85 113 public Type ReplaceableInterface
114 {
115 get { return null; }
116 }
117
86 public void SubscribeToClientEvents(IClientAPI client) 118 public void SubscribeToClientEvents(IClientAPI client)
87 { 119 {
88 client.OnGodKickUser += KickUser; 120 client.OnGodKickUser += KickUser;
@@ -172,8 +204,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
172 } 204 }
173 else 205 else
174 { 206 {
175 if (m_dialogModule != null) 207 if (DialogModule != null)
176 m_dialogModule.SendAlertToUser(agentID, "Request for god powers denied"); 208 DialogModule.SendAlertToUser(agentID, "Request for god powers denied");
177 } 209 }
178 } 210 }
179 } 211 }
@@ -206,7 +238,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
206 transferModule.SendInstantMessage(new GridInstantMessage( 238 transferModule.SendInstantMessage(new GridInstantMessage(
207 m_scene, godID, "God", agentID, (byte)250, false, 239 m_scene, godID, "God", agentID, (byte)250, false,
208 Utils.BytesToString(reason), UUID.Zero, true, 240 Utils.BytesToString(reason), UUID.Zero, true,
209 new Vector3(), new byte[] {(byte)kickflags}), 241 new Vector3(), new byte[] {(byte)kickflags}, true),
210 delegate(bool success) {} ); 242 delegate(bool success) {} );
211 } 243 }
212 return; 244 return;
diff --git a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
index b258e13..af54c1a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
@@ -25,6 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
28using System.Collections.Generic; 29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
30using log4net; 31using log4net;
@@ -34,9 +35,12 @@ using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
36 37
38using Mono.Addins;
39
37namespace OpenSim.Region.CoreModules.Avatar.Groups 40namespace OpenSim.Region.CoreModules.Avatar.Groups
38{ 41{
39 public class GroupsModule : IRegionModule 42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsModule")]
43 public class GroupsModule : ISharedRegionModule
40 { 44 {
41 private static readonly ILog m_log = 45 private static readonly ILog m_log =
42 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -55,9 +59,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
55 private static GroupMembershipData osGroup = 59 private static GroupMembershipData osGroup =
56 new GroupMembershipData(); 60 new GroupMembershipData();
57 61
58 #region IRegionModule Members 62 private bool m_Enabled = false;
63
64 #region ISharedRegionModule Members
59 65
60 public void Initialise(Scene scene, IConfigSource config) 66 public void Initialise(IConfigSource config)
61 { 67 {
62 IConfig groupsConfig = config.Configs["Groups"]; 68 IConfig groupsConfig = config.Configs["Groups"];
63 69
@@ -67,7 +73,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
67 } 73 }
68 else 74 else
69 { 75 {
70 if (!groupsConfig.GetBoolean("Enabled", false)) 76 m_Enabled = groupsConfig.GetBoolean("Enabled", false);
77 if (!m_Enabled)
71 { 78 {
72 m_log.Info("[GROUPS]: Groups disabled in configuration"); 79 m_log.Info("[GROUPS]: Groups disabled in configuration");
73 return; 80 return;
@@ -77,6 +84,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
77 return; 84 return;
78 } 85 }
79 86
87 }
88
89 public void AddRegion(Scene scene)
90 {
91 if (!m_Enabled)
92 return;
93
80 lock (m_SceneList) 94 lock (m_SceneList)
81 { 95 {
82 if (!m_SceneList.Contains(scene)) 96 if (!m_SceneList.Contains(scene))
@@ -96,7 +110,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
96 110
97 scene.EventManager.OnNewClient += OnNewClient; 111 scene.EventManager.OnNewClient += OnNewClient;
98 scene.EventManager.OnClientClosed += OnClientClosed; 112 scene.EventManager.OnClientClosed += OnClientClosed;
99// scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; 113 // scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
114 }
115
116 public void RemoveRegion(Scene scene)
117 {
118 if (!m_Enabled)
119 return;
120
121 lock (m_SceneList)
122 {
123 if (m_SceneList.Contains(scene))
124 m_SceneList.Remove(scene);
125 }
126
127 scene.EventManager.OnNewClient -= OnNewClient;
128 scene.EventManager.OnClientClosed -= OnClientClosed;
129 }
130
131 public void RegionLoaded(Scene scene)
132 {
100 } 133 }
101 134
102 public void PostInitialise() 135 public void PostInitialise()
@@ -105,6 +138,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
105 138
106 public void Close() 139 public void Close()
107 { 140 {
141 if (!m_Enabled)
142 return;
143
108// m_log.Debug("[GROUPS]: Shutting down group module."); 144// m_log.Debug("[GROUPS]: Shutting down group module.");
109 145
110 lock (m_ClientMap) 146 lock (m_ClientMap)
@@ -123,9 +159,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
123 get { return "GroupsModule"; } 159 get { return "GroupsModule"; }
124 } 160 }
125 161
126 public bool IsSharedModule 162 public Type ReplaceableInterface
127 { 163 {
128 get { return true; } 164 get { return null; }
129 } 165 }
130 166
131 #endregion 167 #endregion
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
index bf1d787..7bf19c2 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
@@ -48,7 +48,7 @@ using OpenSim.Server.Handlers.Hypergrid;
48 48
49namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 49namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
50{ 50{
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGMessageTransferModule")]
52 public class HGMessageTransferModule : ISharedRegionModule, IMessageTransferModule, IInstantMessageSimConnector 52 public class HGMessageTransferModule : ISharedRegionModule, IMessageTransferModule, IInstantMessageSimConnector
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);
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
index 727f1c9..55e30a0 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
@@ -29,6 +29,7 @@ using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using System.Timers; 30using System.Timers;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
@@ -38,6 +39,7 @@ using OpenSim.Region.Framework.Scenes;
38 39
39namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 40namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
40{ 41{
42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "InstantMessageModule")]
41 public class InstantMessageModule : ISharedRegionModule 43 public class InstantMessageModule : ISharedRegionModule
42 { 44 {
43 private static readonly ILog m_log = LogManager.GetLogger( 45 private static readonly ILog m_log = LogManager.GetLogger(
@@ -54,7 +56,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
54 56
55 private readonly List<Scene> m_scenes = new List<Scene>(); 57 private readonly List<Scene> m_scenes = new List<Scene>();
56 58
57 #region IRegionModule Members 59 #region Region Module interface
58 60
59 private IMessageTransferModule m_TransferModule = null; 61 private IMessageTransferModule m_TransferModule = null;
60 62
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index edd9707..cc266df 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.Net; 30using System.Net;
31using System.Reflection; 31using System.Reflection;
32using log4net; 32using log4net;
33using Mono.Addins;
33using Nini.Config; 34using Nini.Config;
34using Nwc.XmlRpc; 35using Nwc.XmlRpc;
35using OpenMetaverse; 36using OpenMetaverse;
@@ -43,6 +44,7 @@ using OpenSim.Services.Interfaces;
43 44
44namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 45namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
45{ 46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MessageTransferModule")]
46 public class MessageTransferModule : ISharedRegionModule, IMessageTransferModule 48 public class MessageTransferModule : ISharedRegionModule, IMessageTransferModule
47 { 49 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
index 24cbaeb..7ce2813 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
@@ -29,6 +29,7 @@ using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using log4net; 30using log4net;
31using Nini.Config; 31using Nini.Config;
32using Mono.Addins;
32using OpenMetaverse; 33using OpenMetaverse;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Communications; 35using OpenSim.Framework.Communications;
@@ -39,6 +40,7 @@ using OpenSim.Region.Framework.Scenes;
39 40
40namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 41namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MuteListModule")]
42 public class MuteListModule : ISharedRegionModule 44 public class MuteListModule : ISharedRegionModule
43 { 45 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index b27b07d..3a44cc5 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -28,6 +28,7 @@ using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using log4net; 30using log4net;
31using Mono.Addins;
31using Nini.Config; 32using Nini.Config;
32using OpenMetaverse; 33using OpenMetaverse;
33using OpenSim.Framework; 34using OpenSim.Framework;
@@ -39,6 +40,7 @@ using OpenSim.Region.Framework.Scenes;
39 40
40namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 41namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineMessageModule")]
42 public class OfflineMessageModule : ISharedRegionModule 44 public class OfflineMessageModule : ISharedRegionModule
43 { 45 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs
index dd17f3c..4c678c2 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs
@@ -33,6 +33,7 @@ using log4net;
33using Nini.Config; 33using Nini.Config;
34using Nwc.XmlRpc; 34using Nwc.XmlRpc;
35using OpenMetaverse; 35using OpenMetaverse;
36using Mono.Addins;
36using OpenSim.Framework; 37using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
@@ -42,6 +43,7 @@ using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
42 43
43namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 44namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
44{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PresenceModule")]
45 public class PresenceModule : ISharedRegionModule, IPresenceModule 47 public class PresenceModule : ISharedRegionModule, IPresenceModule
46 { 48 {
47 private static readonly ILog m_log = LogManager.GetLogger( 49 private static readonly ILog m_log = LogManager.GetLogger(
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 0833154..dc2b0e0 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -411,18 +411,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
411 { 411 {
412// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId); 412// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId);
413 413
414 item.CreatorIdAsUuid = ospResolvedId; 414// item.CreatorIdAsUuid = ospResolvedId;
415 415
416 // Don't preserve the OSPA in the creator id (which actually gets persisted to the 416 // Don't preserve the OSPA in the creator id (which actually gets persisted to the
417 // database). Instead, replace with the UUID that we found. 417 // database). Instead, replace with the UUID that we found.
418 item.CreatorId = ospResolvedId.ToString(); 418 item.CreatorId = ospResolvedId.ToString();
419
420 item.CreatorData = string.Empty; 419 item.CreatorData = string.Empty;
421 } 420 }
422 else if (item.CreatorData == null || item.CreatorData == String.Empty) 421 else if (item.CreatorData == null || item.CreatorData == String.Empty)
423 { 422 {
424 item.CreatorId = m_userInfo.PrincipalID.ToString(); 423 item.CreatorId = m_userInfo.PrincipalID.ToString();
425 item.CreatorIdAsUuid = new UUID(item.CreatorId); 424// item.CreatorIdAsUuid = new UUID(item.CreatorId);
426 } 425 }
427 426
428 item.Owner = m_userInfo.PrincipalID; 427 item.Owner = m_userInfo.PrincipalID;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 6587ead..d0e88f6 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
166 166
167 if (options.ContainsKey("verbose")) 167 if (options.ContainsKey("verbose"))
168 m_log.InfoFormat( 168 m_log.InfoFormat(
169 "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", 169 "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {2})",
170 inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); 170 inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID);
171 171
172 string filename = path + CreateArchiveItemName(inventoryItem); 172 string filename = path + CreateArchiveItemName(inventoryItem);
@@ -337,11 +337,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
337 { 337 {
338 m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); 338 m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count);
339 339
340 new AssetsRequest( 340 AssetsRequest ar
341 new AssetsArchiver(m_archiveWriter), 341 = new AssetsRequest(
342 m_assetUuids, m_scene.AssetService, 342 new AssetsArchiver(m_archiveWriter),
343 m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, 343 m_assetUuids, m_scene.AssetService,
344 options, ReceivedAllAssets).Execute(); 344 m_scene.UserAccountService, m_scene.RegionInfo.ScopeID,
345 options, ReceivedAllAssets);
346
347 Util.FireAndForget(o => ar.Execute());
345 } 348 }
346 else 349 else
347 { 350 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index 7d1fe68..f4f9e2d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -35,23 +35,22 @@ using Nini.Config;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Framework.Communications; 37using OpenSim.Framework.Communications;
38using OpenSim.Framework.Console;
38using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
42using Mono.Addins;
41 43
42namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver 44namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
43{ 45{
44 /// <summary> 46 /// <summary>
45 /// This module loads and saves OpenSimulator inventory archives 47 /// This module loads and saves OpenSimulator inventory archives
46 /// </summary> 48 /// </summary>
47 public class InventoryArchiverModule : IRegionModule, IInventoryArchiverModule 49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "InventoryArchiverModule")]
50 public class InventoryArchiverModule : ISharedRegionModule, IInventoryArchiverModule
48 { 51 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 53
51 public string Name { get { return "Inventory Archiver Module"; } }
52
53 public bool IsSharedModule { get { return true; } }
54
55 /// <value> 54 /// <value>
56 /// Enable or disable checking whether the iar user is actually logged in 55 /// Enable or disable checking whether the iar user is actually logged in
57 /// </value> 56 /// </value>
@@ -98,9 +97,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
98// public InventoryArchiverModule(bool disablePresenceChecks) 97// public InventoryArchiverModule(bool disablePresenceChecks)
99// { 98// {
100// DisablePresenceChecks = disablePresenceChecks; 99// DisablePresenceChecks = disablePresenceChecks;
101// } 100 // }
101
102 #region ISharedRegionModule
103
104 public void Initialise(IConfigSource source)
105 {
106 }
102 107
103 public void Initialise(Scene scene, IConfigSource source) 108 public void AddRegion(Scene scene)
104 { 109 {
105 if (m_scenes.Count == 0) 110 if (m_scenes.Count == 0)
106 { 111 {
@@ -143,10 +148,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
143 m_scenes[scene.RegionInfo.RegionID] = scene; 148 m_scenes[scene.RegionInfo.RegionID] = scene;
144 } 149 }
145 150
146 public void PostInitialise() {} 151 public void RemoveRegion(Scene scene)
152 {
153 }
147 154
148 public void Close() {} 155 public void Close() {}
149 156
157 public void RegionLoaded(Scene scene)
158 {
159 }
160
161 public void PostInitialise()
162 {
163 }
164
165 public Type ReplaceableInterface
166 {
167 get { return null; }
168 }
169
170 public string Name { get { return "Inventory Archiver Module"; } }
171
172 #endregion
173
150 /// <summary> 174 /// <summary>
151 /// Trigger the inventory archive saved event. 175 /// Trigger the inventory archive saved event.
152 /// </summary> 176 /// </summary>
@@ -209,6 +233,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
209 Guid id, string firstName, string lastName, string invPath, string pass, string savePath, 233 Guid id, string firstName, string lastName, string invPath, string pass, string savePath,
210 Dictionary<string, object> options) 234 Dictionary<string, object> options)
211 { 235 {
236// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath))
237// return false;
238
212 if (m_scenes.Count > 0) 239 if (m_scenes.Count > 0)
213 { 240 {
214 UserAccount userInfo = GetUserInfo(firstName, lastName, pass); 241 UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
index 1056865..db78da9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
@@ -82,7 +82,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
82 82
83 protected string m_item1Name = "Ray Gun Item"; 83 protected string m_item1Name = "Ray Gun Item";
84 protected string m_coaItemName = "Coalesced Item"; 84 protected string m_coaItemName = "Coalesced Item";
85 85
86 [TestFixtureSetUp]
87 public void FixtureSetup()
88 {
89 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
90 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
91
92 ConstructDefaultIarBytesForTestLoad();
93 }
94
95 [TestFixtureTearDown]
96 public void TearDown()
97 {
98 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
99 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
100 // tests really shouldn't).
101 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
102 }
103
86 [SetUp] 104 [SetUp]
87 public override void SetUp() 105 public override void SetUp()
88 { 106 {
@@ -90,12 +108,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
90 m_iarStream = new MemoryStream(m_iarStreamBytes); 108 m_iarStream = new MemoryStream(m_iarStreamBytes);
91 } 109 }
92 110
93 [TestFixtureSetUp]
94 public void FixtureSetup()
95 {
96 ConstructDefaultIarBytesForTestLoad();
97 }
98
99 protected void ConstructDefaultIarBytesForTestLoad() 111 protected void ConstructDefaultIarBytesForTestLoad()
100 { 112 {
101// log4net.Config.XmlConfigurator.Configure(); 113// log4net.Config.XmlConfigurator.Configure();
@@ -122,7 +134,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
122 item1.ID = UUID.Parse("00000000-0000-0000-0000-000000000020"); 134 item1.ID = UUID.Parse("00000000-0000-0000-0000-000000000020");
123 item1.AssetID = asset1.FullID; 135 item1.AssetID = asset1.FullID;
124 item1.GroupID = UUID.Random(); 136 item1.GroupID = UUID.Random();
125 item1.CreatorIdAsUuid = m_uaLL1.PrincipalID; 137 item1.CreatorId = m_uaLL1.PrincipalID.ToString();
126 item1.Owner = m_uaLL1.PrincipalID; 138 item1.Owner = m_uaLL1.PrincipalID;
127 item1.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID; 139 item1.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID;
128 scene.AddInventoryItem(item1); 140 scene.AddInventoryItem(item1);
@@ -145,7 +157,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
145 coaItem.ID = UUID.Parse("00000000-0000-0000-0000-000000000180"); 157 coaItem.ID = UUID.Parse("00000000-0000-0000-0000-000000000180");
146 coaItem.AssetID = coaAsset.FullID; 158 coaItem.AssetID = coaAsset.FullID;
147 coaItem.GroupID = UUID.Random(); 159 coaItem.GroupID = UUID.Random();
148 coaItem.CreatorIdAsUuid = m_uaLL1.PrincipalID; 160 coaItem.CreatorId = m_uaLL1.PrincipalID.ToString();
149 coaItem.Owner = m_uaLL1.PrincipalID; 161 coaItem.Owner = m_uaLL1.PrincipalID;
150 coaItem.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID; 162 coaItem.Folder = scene.InventoryService.GetRootFolder(m_uaLL1.PrincipalID).ID;
151 scene.AddInventoryItem(coaItem); 163 scene.AddInventoryItem(coaItem);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index b112b6d..06f6e49 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
49{ 49{
50 [TestFixture] 50 [TestFixture]
51 public class InventoryArchiverTests : InventoryArchiveTestCase 51 public class InventoryArchiverTests : InventoryArchiveTestCase
52 { 52 {
53 protected TestScene m_scene; 53 protected TestScene m_scene;
54 protected InventoryArchiverModule m_archiverModule; 54 protected InventoryArchiverModule m_archiverModule;
55 55
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
69 public void TestLoadCoalesecedItem() 69 public void TestLoadCoalesecedItem()
70 { 70 {
71 TestHelpers.InMethod(); 71 TestHelpers.InMethod();
72// log4net.Config.XmlConfigurator.Configure(); 72// TestHelpers.EnableLogging();
73 73
74 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); 74 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password");
75 m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); 75 m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream);
@@ -350,38 +350,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
350 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); 350 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID));
351 } 351 }
352 352
353 /// <summary> 353// /// <summary>
354 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where 354// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
355 /// an account exists with the same name as the creator, though not the same id. 355// /// an account exists with the same name as the creator, though not the same id.
356 /// </summary> 356// /// </summary>
357 [Test] 357// [Test]
358 public void TestLoadIarV0_1SameNameCreator() 358// public void TestLoadIarV0_1SameNameCreator()
359 { 359// {
360 TestHelpers.InMethod(); 360// TestHelpers.InMethod();
361// log4net.Config.XmlConfigurator.Configure(); 361// TestHelpers.EnableLogging();
362 362//
363 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); 363// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
364 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); 364// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
365 365//
366 m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); 366// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
367 InventoryItemBase foundItem1 367// InventoryItemBase foundItem1
368 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); 368// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
369 369//
370 Assert.That( 370// Assert.That(
371 foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), 371// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
372 "Loaded item non-uuid creator doesn't match original"); 372// "Loaded item non-uuid creator doesn't match original");
373 Assert.That( 373// Assert.That(
374 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), 374// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
375 "Loaded item uuid creator doesn't match original"); 375// "Loaded item uuid creator doesn't match original");
376 Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), 376// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
377 "Loaded item owner doesn't match inventory reciever"); 377// "Loaded item owner doesn't match inventory reciever");
378 378//
379 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); 379// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
380 string xmlData = Utils.BytesToString(asset1.Data); 380// string xmlData = Utils.BytesToString(asset1.Data);
381 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 381// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
382 382//
383 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); 383// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
384 } 384// }
385 385
386 /// <summary> 386 /// <summary>
387 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where 387 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index c14cb17..4cfa33d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
@@ -38,20 +39,21 @@ using OpenSim.Services.Interfaces;
38 39
39namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer 40namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
40{ 41{
41 public class InventoryTransferModule : IInventoryTransferModule, ISharedRegionModule 42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "InventoryTransferModule")]
43 public class InventoryTransferModule : ISharedRegionModule
42 { 44 {
43 private static readonly ILog m_log 45 private static readonly ILog m_log
44 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 47
46 /// <summary> 48 /// <summary>
47 private List<Scene> m_Scenelist = new List<Scene>(); 49 private List<Scene> m_Scenelist = new List<Scene>();
48 private Dictionary<UUID, Scene> m_AgentRegions = 50// private Dictionary<UUID, Scene> m_AgentRegions =
49 new Dictionary<UUID, Scene>(); 51// new Dictionary<UUID, Scene>();
50 52
51 private IMessageTransferModule m_TransferModule = null; 53 private IMessageTransferModule m_TransferModule = null;
52 private bool m_Enabled = true; 54 private bool m_Enabled = true;
53 55
54 #region IRegionModule Members 56 #region Region Module interface
55 57
56 public void Initialise(IConfigSource config) 58 public void Initialise(IConfigSource config)
57 { 59 {
@@ -76,12 +78,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
76 78
77 m_Scenelist.Add(scene); 79 m_Scenelist.Add(scene);
78 80
79 scene.RegisterModuleInterface<IInventoryTransferModule>(this); 81// scene.RegisterModuleInterface<IInventoryTransferModule>(this);
80 82
81 scene.EventManager.OnNewClient += OnNewClient; 83 scene.EventManager.OnNewClient += OnNewClient;
82 scene.EventManager.OnClientClosed += ClientLoggedOut; 84// scene.EventManager.OnClientClosed += ClientLoggedOut;
83 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; 85 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
84 scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; 86// scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
85 } 87 }
86 88
87 public void RegionLoaded(Scene scene) 89 public void RegionLoaded(Scene scene)
@@ -96,9 +98,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
96 98
97 m_Scenelist.Clear(); 99 m_Scenelist.Clear();
98 scene.EventManager.OnNewClient -= OnNewClient; 100 scene.EventManager.OnNewClient -= OnNewClient;
99 scene.EventManager.OnClientClosed -= ClientLoggedOut; 101// scene.EventManager.OnClientClosed -= ClientLoggedOut;
100 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 102 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
101 scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; 103// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
102 } 104 }
103 } 105 }
104 } 106 }
@@ -106,9 +108,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
106 public void RemoveRegion(Scene scene) 108 public void RemoveRegion(Scene scene)
107 { 109 {
108 scene.EventManager.OnNewClient -= OnNewClient; 110 scene.EventManager.OnNewClient -= OnNewClient;
109 scene.EventManager.OnClientClosed -= ClientLoggedOut; 111// scene.EventManager.OnClientClosed -= ClientLoggedOut;
110 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 112 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
111 scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; 113// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
112 m_Scenelist.Remove(scene); 114 m_Scenelist.Remove(scene);
113 } 115 }
114 116
@@ -138,10 +140,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
138 client.OnInstantMessage += OnInstantMessage; 140 client.OnInstantMessage += OnInstantMessage;
139 } 141 }
140 142
141 protected void OnSetRootAgentScene(UUID id, Scene scene) 143// protected void OnSetRootAgentScene(UUID id, Scene scene)
142 { 144// {
143 m_AgentRegions[id] = scene; 145// m_AgentRegions[id] = scene;
144 } 146// }
145 147
146 private Scene FindClientScene(UUID agentId) 148 private Scene FindClientScene(UUID agentId)
147 { 149 {
@@ -313,45 +315,77 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
313 m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); 315 m_TransferModule.SendInstantMessage(im, delegate(bool success) {});
314 } 316 }
315 } 317 }
316 else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
317 {
318 UUID destinationFolderID = UUID.Zero;
319
320 if (im.binaryBucket != null && im.binaryBucket.Length >= 16)
321 {
322 destinationFolderID = new UUID(im.binaryBucket, 0);
323 }
324
325 if (destinationFolderID != UUID.Zero)
326 {
327 IInventoryService invService = scene.InventoryService;
328
329 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
330 318
331 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 319 // Disabled for now as it looks like http://opensimulator.org/mantis/view.php?id=6311 was fixed by fixes
332 item = invService.GetItem(item); 320 // to inventory folder versioning allowing the viewer to move the received folder itself as happens on the
333 InventoryFolderBase folder = null; 321 // LL grid. Doing it again server-side then wrongly does a second create and move
334 322// // XXX: This code was placed here to try and accomdate RLV which moves given folders named #RLV/~<name>
335 if (item != null) // It's an item 323// // to a folder called name in #RLV. However, this approach may not be ultimately correct - from analysis
336 { 324// // of Firestorm 4.2.2 on sending an InventoryOffered instead of TaskInventoryOffered (as was previously
337 item.Folder = destinationFolderID; 325// // done), the viewer itself would appear to move and rename the folder, rather than the simulator doing it here.
338 326// else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
339 invService.DeleteItems(item.Owner, new List<UUID>() { item.ID }); 327// {
340 scene.AddInventoryItem(client, item); 328// UUID destinationFolderID = UUID.Zero;
341 } 329//
342 else 330// if (im.binaryBucket != null && im.binaryBucket.Length >= 16)
343 { 331// {
344 folder = new InventoryFolderBase(inventoryID, client.AgentId); 332// destinationFolderID = new UUID(im.binaryBucket, 0);
345 folder = invService.GetFolder(folder); 333// }
346 334//
347 if (folder != null) // It's a folder 335// if (destinationFolderID != UUID.Zero)
348 { 336// {
349 folder.ParentID = destinationFolderID; 337// InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId);
350 invService.MoveFolder(folder); 338// if (destinationFolder == null)
351 } 339// {
352 } 340// m_log.WarnFormat(
353 } 341// "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist",
354 } 342// client.Name, scene.Name, destinationFolderID);
343//
344// return;
345// }
346//
347// IInventoryService invService = scene.InventoryService;
348//
349// UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
350//
351// InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId);
352// item = invService.GetItem(item);
353// InventoryFolderBase folder = null;
354// UUID? previousParentFolderID = null;
355//
356// if (item != null) // It's an item
357// {
358// previousParentFolderID = item.Folder;
359// item.Folder = destinationFolderID;
360//
361// invService.DeleteItems(item.Owner, new List<UUID>() { item.ID });
362// scene.AddInventoryItem(client, item);
363// }
364// else
365// {
366// folder = new InventoryFolderBase(inventoryID, client.AgentId);
367// folder = invService.GetFolder(folder);
368//
369// if (folder != null) // It's a folder
370// {
371// previousParentFolderID = folder.ParentID;
372// folder.ParentID = destinationFolderID;
373// invService.MoveFolder(folder);
374// }
375// }
376//
377// // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
378// if (previousParentFolderID != null)
379// {
380// InventoryFolderBase previousParentFolder
381// = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
382// previousParentFolder = invService.GetFolder(previousParentFolder);
383// scene.SendInventoryUpdate(client, previousParentFolder, true, true);
384//
385// scene.SendInventoryUpdate(client, destinationFolder, true, true);
386// }
387// }
388// }
355 else if ( 389 else if (
356 im.dialog == (byte)InstantMessageDialog.InventoryDeclined 390 im.dialog == (byte)InstantMessageDialog.InventoryDeclined
357 || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined) 391 || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined)
@@ -370,9 +404,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
370 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 404 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId);
371 item = invService.GetItem(item); 405 item = invService.GetItem(item);
372 InventoryFolderBase folder = null; 406 InventoryFolderBase folder = null;
407 UUID? previousParentFolderID = null;
373 408
374 if (item != null && trashFolder != null) 409 if (item != null && trashFolder != null)
375 { 410 {
411 previousParentFolderID = item.Folder;
376 item.Folder = trashFolder.ID; 412 item.Folder = trashFolder.ID;
377 413
378 // Diva comment: can't we just update this item??? 414 // Diva comment: can't we just update this item???
@@ -388,6 +424,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
388 424
389 if (folder != null & trashFolder != null) 425 if (folder != null & trashFolder != null)
390 { 426 {
427 previousParentFolderID = folder.ParentID;
391 folder.ParentID = trashFolder.ID; 428 folder.ParentID = trashFolder.ID;
392 invService.MoveFolder(folder); 429 invService.MoveFolder(folder);
393 client.SendBulkUpdateInventory(folder); 430 client.SendBulkUpdateInventory(folder);
@@ -408,84 +445,97 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
408 client.SendAgentAlertMessage("Unable to delete "+ 445 client.SendAgentAlertMessage("Unable to delete "+
409 "received inventory" + reason, false); 446 "received inventory" + reason, false);
410 } 447 }
411 448 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
412 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 449 else if (previousParentFolderID != null)
413
414 if (user != null) // Local
415 { 450 {
416 user.ControllingClient.SendInstantMessage(im); 451 InventoryFolderBase previousParentFolder
417 } 452 = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
418 else 453 previousParentFolder = invService.GetFolder(previousParentFolder);
419 { 454 scene.SendInventoryUpdate(client, previousParentFolder, true, true);
420 if (m_TransferModule != null)
421 m_TransferModule.SendInstantMessage(im, delegate(bool success) {});
422 }
423 }
424 }
425 455
426 public bool NeedSceneCacheClear(UUID agentID, Scene scene) 456 scene.SendInventoryUpdate(client, trashFolder, true, true);
427 { 457 }
428 if (!m_AgentRegions.ContainsKey(agentID))
429 {
430 // Since we can get here two ways, we need to scan
431 // the scenes here. This is somewhat more expensive
432 // but helps avoid a nasty bug
433 //
434 458
435 foreach (Scene s in m_Scenelist) 459 if (im.dialog == (byte)InstantMessageDialog.InventoryDeclined)
436 { 460 {
437 ScenePresence presence; 461 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
438 462
439 if (s.TryGetScenePresence(agentID, out presence)) 463 if (user != null) // Local
440 { 464 {
441 // If the agent is in this scene, then we 465 user.ControllingClient.SendInstantMessage(im);
442 // are being called twice in a single 466 }
443 // teleport. This is wasteful of cycles 467 else
444 // but harmless due to this 2nd level check 468 {
445 // 469 if (m_TransferModule != null)
446 // If the agent is found in another scene 470 m_TransferModule.SendInstantMessage(im, delegate(bool success) { });
447 // then the list wasn't current
448 //
449 // If the agent is totally unknown, then what
450 // are we even doing here??
451 //
452 if (s == scene)
453 {
454 //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName);
455 return true;
456 }
457 else
458 {
459 //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName);
460 return false;
461 }
462 } 471 }
463 } 472 }
464 //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName);
465 return true;
466 } 473 }
467
468 // The agent is left in current Scene, so we must be
469 // going to another instance
470 //
471 if (m_AgentRegions[agentID] == scene)
472 {
473 //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName);
474 m_AgentRegions.Remove(agentID);
475 return true;
476 }
477
478 // Another region has claimed the agent
479 //
480 //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName);
481 return false;
482 } 474 }
483 475
484 public void ClientLoggedOut(UUID agentID, Scene scene) 476// public bool NeedSceneCacheClear(UUID agentID, Scene scene)
485 { 477// {
486 if (m_AgentRegions.ContainsKey(agentID)) 478// if (!m_AgentRegions.ContainsKey(agentID))
487 m_AgentRegions.Remove(agentID); 479// {
488 } 480// // Since we can get here two ways, we need to scan
481// // the scenes here. This is somewhat more expensive
482// // but helps avoid a nasty bug
483// //
484//
485// foreach (Scene s in m_Scenelist)
486// {
487// ScenePresence presence;
488//
489// if (s.TryGetScenePresence(agentID, out presence))
490// {
491// // If the agent is in this scene, then we
492// // are being called twice in a single
493// // teleport. This is wasteful of cycles
494// // but harmless due to this 2nd level check
495// //
496// // If the agent is found in another scene
497// // then the list wasn't current
498// //
499// // If the agent is totally unknown, then what
500// // are we even doing here??
501// //
502// if (s == scene)
503// {
504// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName);
505// return true;
506// }
507// else
508// {
509// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName);
510// return false;
511// }
512// }
513// }
514// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName);
515// return true;
516// }
517//
518// // The agent is left in current Scene, so we must be
519// // going to another instance
520// //
521// if (m_AgentRegions[agentID] == scene)
522// {
523// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName);
524// m_AgentRegions.Remove(agentID);
525// return true;
526// }
527//
528// // Another region has claimed the agent
529// //
530// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName);
531// return false;
532// }
533//
534// public void ClientLoggedOut(UUID agentID, Scene scene)
535// {
536// if (m_AgentRegions.ContainsKey(agentID))
537// m_AgentRegions.Remove(agentID);
538// }
489 539
490 /// <summary> 540 /// <summary>
491 /// 541 ///
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
index 92cf9d1..232a4fe 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
@@ -42,7 +42,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
42 42
43namespace OpenSim.Region.CoreModules.Avatar.Lure 43namespace OpenSim.Region.CoreModules.Avatar.Lure
44{ 44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGLureModule")]
46 public class HGLureModule : ISharedRegionModule 46 public class HGLureModule : ISharedRegionModule
47 { 47 {
48 private static readonly ILog m_log = LogManager.GetLogger( 48 private static readonly ILog m_log = LogManager.GetLogger(
@@ -186,7 +186,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
186 client.FirstName+" "+client.LastName, targetid, 186 client.FirstName+" "+client.LastName, targetid,
187 (byte)InstantMessageDialog.RequestTeleport, false, 187 (byte)InstantMessageDialog.RequestTeleport, false,
188 message, sessionID, false, presence.AbsolutePosition, 188 message, sessionID, false, presence.AbsolutePosition,
189 new Byte[0]); 189 new Byte[0], true);
190 m.RegionID = client.Scene.RegionInfo.RegionID.Guid; 190 m.RegionID = client.Scene.RegionInfo.RegionID.Guid;
191 191
192 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message); 192 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message);
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index a889984..f3adb95 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
@@ -37,6 +38,7 @@ using OpenSim.Region.Framework.Scenes;
37 38
38namespace OpenSim.Region.CoreModules.Avatar.Lure 39namespace OpenSim.Region.CoreModules.Avatar.Lure
39{ 40{
41 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LureModule")]
40 public class LureModule : ISharedRegionModule 42 public class LureModule : ISharedRegionModule
41 { 43 {
42 private static readonly ILog m_log = LogManager.GetLogger( 44 private static readonly ILog m_log = LogManager.GetLogger(
@@ -173,7 +175,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
173 client.FirstName+" "+client.LastName, targetid, 175 client.FirstName+" "+client.LastName, targetid,
174 (byte)InstantMessageDialog.GodLikeRequestTeleport, false, 176 (byte)InstantMessageDialog.GodLikeRequestTeleport, false,
175 message, dest, false, presence.AbsolutePosition, 177 message, dest, false, presence.AbsolutePosition,
176 new Byte[0]); 178 new Byte[0], true);
177 } 179 }
178 else 180 else
179 { 181 {
@@ -181,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
181 client.FirstName+" "+client.LastName, targetid, 183 client.FirstName+" "+client.LastName, targetid,
182 (byte)InstantMessageDialog.RequestTeleport, false, 184 (byte)InstantMessageDialog.RequestTeleport, false,
183 message, dest, false, presence.AbsolutePosition, 185 message, dest, false, presence.AbsolutePosition,
184 new Byte[0]); 186 new Byte[0], true);
185 } 187 }
186 188
187 if (m_TransferModule != null) 189 if (m_TransferModule != null)
diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
index 87ca327..bf24030 100644
--- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
@@ -42,7 +42,7 @@ using OpenSim.Services.Interfaces;
42 42
43namespace OpenSim.Region.CoreModules.Avatar.Profile 43namespace OpenSim.Region.CoreModules.Avatar.Profile
44{ 44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BasicProfileModule")]
46 public class BasicProfileModule : IProfileModule, ISharedRegionModule 46 public class BasicProfileModule : IProfileModule, ISharedRegionModule
47 { 47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index dbe75b5..7f30e5a 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -43,7 +43,7 @@ using Caps=OpenSim.Framework.Capabilities.Caps;
43 43
44namespace OpenSim.Region.CoreModules.Framework 44namespace OpenSim.Region.CoreModules.Framework
45{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CapabilitiesModule")]
47 public class CapabilitiesModule : INonSharedRegionModule, ICapabilitiesModule 47 public class CapabilitiesModule : INonSharedRegionModule, ICapabilitiesModule
48 { 48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 880b2cc..7e72d47 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -43,9 +43,11 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
43using OpenMetaverse; 43using OpenMetaverse;
44using log4net; 44using log4net;
45using Nini.Config; 45using Nini.Config;
46using Mono.Addins;
46 47
47namespace OpenSim.Region.CoreModules.Framework.EntityTransfer 48namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
48{ 49{
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EntityTransferModule")]
49 public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule 51 public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule
50 { 52 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -327,6 +329,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
327 return; 329 return;
328 } 330 }
329 331
332 // Validate assorted conditions
333 string reason = string.Empty;
334 if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason))
335 {
336 sp.ControllingClient.SendTeleportFailed(reason);
337 return;
338 }
339
330 // 340 //
331 // This is it 341 // This is it
332 // 342 //
@@ -358,6 +368,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
358 } 368 }
359 } 369 }
360 370
371 // Nothing to validate here
372 protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
373 {
374 reason = String.Empty;
375 return true;
376 }
377
361 /// <summary> 378 /// <summary>
362 /// Determines whether this instance is within the max transfer distance. 379 /// Determines whether this instance is within the max transfer distance.
363 /// </summary> 380 /// </summary>
@@ -473,10 +490,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
473 // both regions 490 // both regions
474 if (sp.ParentID != (uint)0) 491 if (sp.ParentID != (uint)0)
475 sp.StandUp(); 492 sp.StandUp();
476
477 else if (sp.Flying) 493 else if (sp.Flying)
478 teleportFlags |= (uint)TeleportFlags.IsFlying; 494 teleportFlags |= (uint)TeleportFlags.IsFlying;
479 495
496 // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to
497 // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested).
480 sp.ControllingClient.SendTeleportStart(teleportFlags); 498 sp.ControllingClient.SendTeleportStart(teleportFlags);
481 499
482 // the avatar.Close below will clear the child region list. We need this below for (possibly) 500 // the avatar.Close below will clear the child region list. We need this below for (possibly)
@@ -552,8 +570,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
552 // So let's wait 570 // So let's wait
553 Thread.Sleep(200); 571 Thread.Sleep(200);
554 572
573 // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears
574 // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly
575 // only on TeleportFinish). This is untested for region teleport between different simulators
576 // though this probably also works.
555 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); 577 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
556
557 } 578 }
558 else 579 else
559 { 580 {
@@ -574,7 +595,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
574 595
575 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); 596 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
576 597
577 if (!UpdateAgent(reg, finalDestination, agent)) 598 if (!UpdateAgent(reg, finalDestination, agent, sp))
578 { 599 {
579 // Region doesn't take it 600 // Region doesn't take it
580 m_log.WarnFormat( 601 m_log.WarnFormat(
@@ -650,7 +671,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
650 // an agent cannot teleport back to this region if it has teleported away. 671 // an agent cannot teleport back to this region if it has teleported away.
651 Thread.Sleep(3000); 672 Thread.Sleep(3000);
652 673
653 sp.Scene.IncomingCloseAgent(sp.UUID); 674 sp.Scene.IncomingCloseAgent(sp.UUID, false);
654 } 675 }
655 else 676 else
656 { 677 {
@@ -658,13 +679,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
658 sp.Reset(); 679 sp.Reset();
659 } 680 }
660 681
661 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! 682 // Commented pending deletion since this method no longer appears to do anything at all
662 if (sp.Scene.NeedSceneCacheClear(sp.UUID)) 683// // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
663 { 684// if (sp.Scene.NeedSceneCacheClear(sp.UUID))
664 m_log.DebugFormat( 685// {
665 "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", 686// m_log.DebugFormat(
666 sp.UUID); 687// "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
667 } 688// sp.UUID);
689// }
668 690
669 m_entityTransferStateMachine.ResetFromTransit(sp.UUID); 691 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
670 } 692 }
@@ -701,7 +723,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
701 return success; 723 return success;
702 } 724 }
703 725
704 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent) 726 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp)
705 { 727 {
706 return Scene.SimulationService.UpdateAgent(finalDestination, agent); 728 return Scene.SimulationService.UpdateAgent(finalDestination, agent);
707 } 729 }
@@ -1013,6 +1035,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1013 Scene initiatingScene) 1035 Scene initiatingScene)
1014 { 1036 {
1015 Thread.Sleep(10000); 1037 Thread.Sleep(10000);
1038
1016 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>(); 1039 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>();
1017 if (im != null) 1040 if (im != null)
1018 { 1041 {
@@ -1025,11 +1048,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1025 (uint)(int)position.X, 1048 (uint)(int)position.X,
1026 (uint)(int)position.Y, 1049 (uint)(int)position.Y,
1027 (uint)(int)position.Z); 1050 (uint)(int)position.Z);
1028 GridInstantMessage m = new GridInstantMessage(initiatingScene, UUID.Zero, 1051
1029 "Region", agent.UUID, 1052 GridInstantMessage m
1030 (byte)InstantMessageDialog.GodLikeRequestTeleport, false, 1053 = new GridInstantMessage(
1031 "", gotoLocation, false, new Vector3(127, 0, 0), 1054 initiatingScene,
1032 new Byte[0]); 1055 UUID.Zero,
1056 "Region",
1057 agent.UUID,
1058 (byte)InstantMessageDialog.GodLikeRequestTeleport,
1059 false,
1060 "",
1061 gotoLocation,
1062 false,
1063 new Vector3(127, 0, 0),
1064 new Byte[0],
1065 false);
1066
1033 im.SendInstantMessage(m, delegate(bool success) 1067 im.SendInstantMessage(m, delegate(bool success)
1034 { 1068 {
1035 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success); 1069 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success);
@@ -1191,11 +1225,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1191 // the user may change their profile information in other region, 1225 // the user may change their profile information in other region,
1192 // so the userinfo in UserProfileCache is not reliable any more, delete it 1226 // so the userinfo in UserProfileCache is not reliable any more, delete it
1193 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! 1227 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
1194 if (agent.Scene.NeedSceneCacheClear(agent.UUID)) 1228// if (agent.Scene.NeedSceneCacheClear(agent.UUID))
1195 { 1229// {
1196 m_log.DebugFormat( 1230// m_log.DebugFormat(
1197 "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); 1231// "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID);
1198 } 1232// }
1199 1233
1200 //m_log.Debug("AFTER CROSS"); 1234 //m_log.Debug("AFTER CROSS");
1201 //Scene.DumpChildrenSeeds(UUID); 1235 //Scene.DumpChildrenSeeds(UUID);
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 3010b59..f3a0b01 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -42,9 +42,11 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
42using OpenMetaverse; 42using OpenMetaverse;
43using log4net; 43using log4net;
44using Nini.Config; 44using Nini.Config;
45using Mono.Addins;
45 46
46namespace OpenSim.Region.CoreModules.Framework.EntityTransfer 47namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
47{ 48{
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGEntityTransferModule")]
48 public class HGEntityTransferModule 50 public class HGEntityTransferModule
49 : EntityTransferModule, INonSharedRegionModule, IEntityTransferModule, IUserAgentVerificationModule 51 : EntityTransferModule, INonSharedRegionModule, IEntityTransferModule, IUserAgentVerificationModule
50 { 52 {
@@ -54,6 +56,59 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
54 56
55 private GatekeeperServiceConnector m_GatekeeperConnector; 57 private GatekeeperServiceConnector m_GatekeeperConnector;
56 58
59 protected bool m_RestrictAppearanceAbroad;
60 protected string m_AccountName;
61 protected List<AvatarAppearance> m_ExportedAppearances;
62 protected List<AvatarAttachment> m_Attachs;
63
64 protected List<AvatarAppearance> ExportedAppearance
65 {
66 get
67 {
68 if (m_ExportedAppearances != null)
69 return m_ExportedAppearances;
70
71 m_ExportedAppearances = new List<AvatarAppearance>();
72 m_Attachs = new List<AvatarAttachment>();
73
74 string[] names = m_AccountName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
75
76 foreach (string name in names)
77 {
78 string[] parts = name.Trim().Split();
79 if (parts.Length != 2)
80 {
81 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Wrong user account name format {0}. Specify 'First Last'", name);
82 return null;
83 }
84 UserAccount account = Scene.UserAccountService.GetUserAccount(UUID.Zero, parts[0], parts[1]);
85 if (account == null)
86 {
87 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unknown account {0}", m_AccountName);
88 return null;
89 }
90 AvatarAppearance a = Scene.AvatarService.GetAppearance(account.PrincipalID);
91 if (a != null)
92 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Successfully retrieved appearance for {0}", name);
93
94 foreach (AvatarAttachment att in a.GetAttachments())
95 {
96 InventoryItemBase item = new InventoryItemBase(att.ItemID, account.PrincipalID);
97 item = Scene.InventoryService.GetItem(item);
98 if (item != null)
99 a.SetAttachment(att.AttachPoint, att.ItemID, item.AssetID);
100 else
101 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve item {0} from inventory {1}", att.ItemID, name);
102 }
103
104 m_ExportedAppearances.Add(a);
105 m_Attachs.AddRange(a.GetAttachments());
106 }
107
108 return m_ExportedAppearances;
109 }
110 }
111
57 #region ISharedRegionModule 112 #region ISharedRegionModule
58 113
59 public override string Name 114 public override string Name
@@ -72,8 +127,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
72 { 127 {
73 IConfig transferConfig = source.Configs["EntityTransfer"]; 128 IConfig transferConfig = source.Configs["EntityTransfer"];
74 if (transferConfig != null) 129 if (transferConfig != null)
130 {
75 m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0); 131 m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0);
76 132
133 m_RestrictAppearanceAbroad = transferConfig.GetBoolean("RestrictAppearanceAbroad", false);
134 if (m_RestrictAppearanceAbroad)
135 {
136 m_AccountName = transferConfig.GetString("AccountForAppearance", string.Empty);
137 if (m_AccountName == string.Empty)
138 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is on, but no account has been given for avatar appearance!");
139 }
140 }
141
77 InitialiseCommon(source); 142 InitialiseCommon(source);
78 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); 143 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
79 } 144 }
@@ -85,7 +150,36 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
85 base.AddRegion(scene); 150 base.AddRegion(scene);
86 151
87 if (m_Enabled) 152 if (m_Enabled)
153 {
88 scene.RegisterModuleInterface<IUserAgentVerificationModule>(this); 154 scene.RegisterModuleInterface<IUserAgentVerificationModule>(this);
155 scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject;
156 }
157 }
158
159 void OnIncomingSceneObject(SceneObjectGroup so)
160 {
161 if (!so.IsAttachment)
162 return;
163
164 if (so.Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar))
165 return;
166
167 // foreign user
168 AgentCircuitData aCircuit = so.Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar);
169 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
170 {
171 if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
172 {
173 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);
175 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
176 HGUuidGatherer uuidGatherer = new HGUuidGatherer(so.Scene.AssetService, url);
177 uuidGatherer.GatherAssetUuids(so, ids);
178
179 foreach (KeyValuePair<UUID, AssetType> kvp in ids)
180 uuidGatherer.FetchAsset(kvp.Key);
181 }
182 }
89 } 183 }
90 184
91 protected override void OnNewClient(IClientAPI client) 185 protected override void OnNewClient(IClientAPI client)
@@ -120,7 +214,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
120 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); 214 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID);
121 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); 215 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags);
122 216
123 if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) 217 if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
124 { 218 {
125 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); 219 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID);
126 GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); 220 GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID);
@@ -140,7 +234,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
140 return true; 234 return true;
141 235
142 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); 236 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
143 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) 237 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
144 return true; 238 return true;
145 239
146 return false; 240 return false;
@@ -153,6 +247,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
153 { 247 {
154 // Log them out of this grid 248 // Log them out of this grid
155 Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 249 Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
250 string userId = Scene.UserManagementModule.GetUserUUI(sp.UUID);
251 Scene.GridUserService.LoggedOut(userId, UUID.Zero, Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
156 } 252 }
157 } 253 }
158 254
@@ -162,11 +258,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
162 reason = string.Empty; 258 reason = string.Empty;
163 logout = false; 259 logout = false;
164 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); 260 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
165 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) 261 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
166 { 262 {
167 // this user is going to another grid 263 // this user is going to another grid
168 // check if HyperGrid teleport is allowed, based on user level 264 // for local users, check if HyperGrid teleport is allowed, based on user level
169 if (sp.UserLevel < m_levelHGTeleport) 265 if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID) && sp.UserLevel < m_levelHGTeleport)
170 { 266 {
171 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel."); 267 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel.");
172 reason = "Hypergrid teleport not allowed"; 268 reason = "Hypergrid teleport not allowed";
@@ -200,6 +296,124 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
200 TeleportHome(id, client); 296 TeleportHome(id, client);
201 } 297 }
202 298
299 protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
300 {
301 reason = "Please wear your grid's allowed appearance before teleporting to another grid";
302 if (!m_RestrictAppearanceAbroad)
303 return true;
304
305 // The rest is only needed for controlling appearance
306
307 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
308 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
309 {
310 // this user is going to another grid
311 if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID))
312 {
313 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance");
314
315 // Check wearables
316 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
317 {
318 for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++)
319 {
320 if (sp.Appearance.Wearables[i] == null)
321 continue;
322
323 bool found = false;
324 foreach (AvatarAppearance a in ExportedAppearance)
325 if (a.Wearables[i] != null)
326 {
327 found = true;
328 break;
329 }
330
331 if (!found)
332 {
333 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i);
334 return false;
335 }
336
337 found = false;
338 foreach (AvatarAppearance a in ExportedAppearance)
339 if (sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID)
340 {
341 found = true;
342 break;
343 }
344
345 if (!found)
346 {
347 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i);
348 return false;
349 }
350 }
351 }
352
353 // Check attachments
354 foreach (AvatarAttachment att in sp.Appearance.GetAttachments())
355 {
356 bool found = false;
357 foreach (AvatarAttachment att2 in m_Attachs)
358 {
359 if (att2.AssetID == att.AssetID)
360 {
361 found = true;
362 break;
363 }
364 }
365 if (!found)
366 {
367 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Attachment not allowed to go outside {0}", att.AttachPoint);
368 return false;
369 }
370 }
371 }
372 }
373
374 reason = string.Empty;
375 return true;
376 }
377
378
379 //protected override bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agentData, ScenePresence sp)
380 //{
381 // int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
382 // if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
383 // {
384 // // this user is going to another grid
385 // if (m_RestrictAppearanceAbroad && Scene.UserManagementModule.IsLocalGridUser(agentData.AgentID))
386 // {
387 // // We need to strip the agent off its appearance
388 // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Sending generic appearance");
389
390 // // Delete existing npc attachments
391 // Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, false);
392
393 // // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet since it doesn't transfer attachments
394 // AvatarAppearance newAppearance = new AvatarAppearance(ExportedAppearance, true);
395 // sp.Appearance = newAppearance;
396
397 // // Rez needed npc attachments
398 // Scene.AttachmentsModule.RezAttachments(sp);
399
400
401 // IAvatarFactoryModule module = Scene.RequestModuleInterface<IAvatarFactoryModule>();
402 // //module.SendAppearance(sp.UUID);
403 // module.RequestRebake(sp, false);
404
405 // Scene.AttachmentsModule.CopyAttachments(sp, agentData);
406 // agentData.Appearance = sp.Appearance;
407 // }
408 // }
409
410 // foreach (AvatarAttachment a in agentData.Appearance.GetAttachments())
411 // m_log.DebugFormat("[XXX]: {0}-{1}", a.ItemID, a.AssetID);
412
413
414 // return base.UpdateAgent(reg, finalDestination, agentData, sp);
415 //}
416
203 public override bool TeleportHome(UUID id, IClientAPI client) 417 public override bool TeleportHome(UUID id, IClientAPI client)
204 { 418 {
205 m_log.DebugFormat( 419 m_log.DebugFormat(
@@ -375,4 +589,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
375 return region; 589 return region;
376 } 590 }
377 } 591 }
378} \ No newline at end of file 592}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
index eaadc1b..f8ec6de 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -71,19 +71,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
71 71
72 #region Internal functions 72 #region Internal functions
73 73
74 public AssetBase FetchAsset(string url, UUID assetID) 74 public AssetMetadata FetchMetadata(string url, UUID assetID)
75 { 75 {
76 if (!url.EndsWith("/") && !url.EndsWith("=")) 76 if (!url.EndsWith("/") && !url.EndsWith("="))
77 url = url + "/"; 77 url = url + "/";
78 78
79 AssetBase asset = m_scene.AssetService.Get(url + assetID.ToString()); 79 AssetMetadata meta = m_scene.AssetService.GetMetadata(url + assetID.ToString());
80 80
81 if (asset != null) 81 if (meta != null)
82 { 82 m_log.DebugFormat("[HG ASSET MAPPER]: Fetched metadata for asset {0} of type {1} from {2} ", assetID, meta.Type, url);
83 m_log.DebugFormat("[HG ASSET MAPPER]: Copied asset {0} from {1} to local asset server. ", asset.ID, url); 83 else
84 return asset; 84 m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetched metadata for asset {0} from {1} ", assetID, url);
85 } 85
86 return null; 86 return meta;
87 } 87 }
88 88
89 public bool PostAsset(string url, AssetBase asset) 89 public bool PostAsset(string url, AssetBase asset)
@@ -93,6 +93,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
93 if (!url.EndsWith("/") && !url.EndsWith("=")) 93 if (!url.EndsWith("/") && !url.EndsWith("="))
94 url = url + "/"; 94 url = url + "/";
95 95
96 bool success = true;
96 // See long comment in AssetCache.AddAsset 97 // See long comment in AssetCache.AddAsset
97 if (!asset.Temporary || asset.Local) 98 if (!asset.Temporary || asset.Local)
98 { 99 {
@@ -103,14 +104,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
103 // not having a global naming infrastructure 104 // not having a global naming infrastructure
104 AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID); 105 AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID);
105 Copy(asset, asset1); 106 Copy(asset, asset1);
106 try 107 asset1.ID = url + asset.ID;
107 {
108 asset1.ID = url + asset.ID;
109 }
110 catch
111 {
112 m_log.Warn("[HG ASSET MAPPER]: Oops.");
113 }
114 108
115 AdjustIdentifiers(asset1.Metadata); 109 AdjustIdentifiers(asset1.Metadata);
116 if (asset1.Metadata.Type == (sbyte)AssetType.Object) 110 if (asset1.Metadata.Type == (sbyte)AssetType.Object)
@@ -118,11 +112,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
118 else 112 else
119 asset1.Data = asset.Data; 113 asset1.Data = asset.Data;
120 114
121 m_scene.AssetService.Store(asset1); 115 string id = m_scene.AssetService.Store(asset1);
122 m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url); 116 if (id == string.Empty)
117 {
118 m_log.DebugFormat("[HG ASSET MAPPER]: Asset server {0} did not accept {1}", url, asset.ID);
119 success = false;
120 }
121 else
122 m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url);
123 } 123 }
124 return true; 124 return success;
125 } 125 }
126 else 126 else
127 m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache."); 127 m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache.");
128 128
@@ -222,28 +222,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
222 222
223 public void Get(UUID assetID, UUID ownerID, string userAssetURL) 223 public void Get(UUID assetID, UUID ownerID, string userAssetURL)
224 { 224 {
225 // Get the item from the remote asset server onto the local AssetCache 225 // Get the item from the remote asset server onto the local AssetService
226 // and place an entry in m_assetMap
227
228 m_log.Debug("[HG ASSET MAPPER]: Fetching object " + assetID + " from asset server " + userAssetURL);
229 AssetBase asset = FetchAsset(userAssetURL, assetID);
230 226
231 if (asset != null) 227 AssetMetadata meta = FetchMetadata(userAssetURL, assetID);
232 { 228 if (meta == null)
233 // OK, now fetch the inside. 229 return;
234 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
235 HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL);
236 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
237 if (ids.ContainsKey(assetID))
238 ids.Remove(assetID);
239 foreach (UUID uuid in ids.Keys)
240 FetchAsset(userAssetURL, uuid);
241 230
242 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", asset.ID, userAssetURL); 231 // The act of gathering UUIDs downloads the assets from the remote server
232 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
233 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
234 uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids);
243 235
244 }
245 else
246 m_log.Warn("[HG ASSET MAPPER]: Could not fetch asset from remote asset server " + userAssetURL);
247 } 236 }
248 237
249 238
@@ -257,19 +246,23 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
257 if (asset != null) 246 if (asset != null)
258 { 247 {
259 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 248 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
260 HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty); 249 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty);
261 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); 250 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
251 bool success = false;
262 foreach (UUID uuid in ids.Keys) 252 foreach (UUID uuid in ids.Keys)
263 { 253 {
264 asset = m_scene.AssetService.Get(uuid.ToString()); 254 asset = m_scene.AssetService.Get(uuid.ToString());
265 if (asset == null) 255 if (asset == null)
266 m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid); 256 m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid);
267 else 257 else
268 PostAsset(userAssetURL, asset); 258 success = PostAsset(userAssetURL, asset);
269 } 259 }
270 260
271 // maybe all pieces got there... 261 // maybe all pieces got there...
272 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL); 262 if (!success)
263 m_log.DebugFormat("[HG ASSET MAPPER]: Problems posting item {0} to asset server {1}", assetID, userAssetURL);
264 else
265 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL);
273 266
274 } 267 }
275 else 268 else
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index cf72b58..964efda 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -42,9 +42,11 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
42using OpenMetaverse; 42using OpenMetaverse;
43using log4net; 43using log4net;
44using Nini.Config; 44using Nini.Config;
45using Mono.Addins;
45 46
46namespace OpenSim.Region.CoreModules.Framework.InventoryAccess 47namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
47{ 48{
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGInventoryAccessModule")]
48 public class HGInventoryAccessModule : BasicInventoryAccessModule, INonSharedRegionModule, IInventoryAccessModule 50 public class HGInventoryAccessModule : BasicInventoryAccessModule, INonSharedRegionModule, IInventoryAccessModule
49 { 51 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -92,7 +94,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
92 m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI); 94 m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI);
93 m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); 95 m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true);
94 m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); 96 m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty);
95 m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", false); 97 m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true);
96 } 98 }
97 else 99 else
98 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); 100 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!");
@@ -263,8 +265,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
263 //} 265 //}
264 266
265 // OK, we're done fetching. Pass it up to the default RezObject 267 // OK, we're done fetching. Pass it up to the default RezObject
266 return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, 268 SceneObjectGroup sog = base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
267 RezSelected, RemoveItem, fromTaskID, attachment); 269 RezSelected, RemoveItem, fromTaskID, attachment);
270
271 if (sog == null)
272 remoteClient.SendAgentAlertMessage("Unable to rez: problem accessing inventory or locating assets", false);
273
274 return sog;
268 275
269 } 276 }
270 277
@@ -308,6 +315,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
308 protected override InventoryItemBase GetItem(UUID agentID, UUID itemID) 315 protected override InventoryItemBase GetItem(UUID agentID, UUID itemID)
309 { 316 {
310 InventoryItemBase item = base.GetItem(agentID, itemID); 317 InventoryItemBase item = base.GetItem(agentID, itemID);
318 if (item == null)
319 return null;
311 320
312 string userAssetServer = string.Empty; 321 string userAssetServer = string.Empty;
313 if (IsForeignUser(agentID, out userAssetServer)) 322 if (IsForeignUser(agentID, out userAssetServer))
@@ -344,6 +353,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
344 353
345 private void ProcessInventoryForArriving(IClientAPI client) 354 private void ProcessInventoryForArriving(IClientAPI client)
346 { 355 {
356 // No-op for now, but we may need to do something for freign users inventory
347 } 357 }
348 358
349 // 359 //
@@ -390,6 +400,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
390 400
391 private void ProcessInventoryForLeaving(IClientAPI client) 401 private void ProcessInventoryForLeaving(IClientAPI client)
392 { 402 {
403 // No-op for now
393 } 404 }
394 405
395 #endregion 406 #endregion
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 50f5f68..6e5a4a5 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -46,9 +46,11 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
46using OpenMetaverse; 46using OpenMetaverse;
47using log4net; 47using log4net;
48using Nini.Config; 48using Nini.Config;
49using Mono.Addins;
49 50
50namespace OpenSim.Region.CoreModules.Framework.InventoryAccess 51namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
51{ 52{
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BasicInventoryAccessModule")]
52 public class BasicInventoryAccessModule : INonSharedRegionModule, IInventoryAccessModule 54 public class BasicInventoryAccessModule : INonSharedRegionModule, IInventoryAccessModule
53 { 55 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
index 3155ce7..ec22146 100644
--- a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
@@ -41,10 +41,12 @@ using OpenSim.Server.Base;
41 41
42using OpenMetaverse; 42using OpenMetaverse;
43using log4net; 43using log4net;
44using Mono.Addins;
44using Nini.Config; 45using Nini.Config;
45 46
46namespace OpenSim.Region.CoreModules.Framework.Library 47namespace OpenSim.Region.CoreModules.Framework.Library
47{ 48{
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LibraryModule")]
48 public class LibraryModule : ISharedRegionModule 50 public class LibraryModule : ISharedRegionModule
49 { 51 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
index e135c21..d84460a 100644
--- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
@@ -38,10 +38,12 @@ using OpenSim.Region.CoreModules.Framework.Monitoring.Alerts;
38using OpenSim.Region.CoreModules.Framework.Monitoring.Monitors; 38using OpenSim.Region.CoreModules.Framework.Monitoring.Monitors;
39using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41using Mono.Addins;
41 42
42namespace OpenSim.Region.CoreModules.Framework.Monitoring 43namespace OpenSim.Region.CoreModules.Framework.Monitoring
43{ 44{
44 public class MonitorModule : IRegionModule 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MonitorModule")]
46 public class MonitorModule : INonSharedRegionModule
45 { 47 {
46 /// <summary> 48 /// <summary>
47 /// Is this module enabled? 49 /// Is this module enabled?
@@ -62,14 +64,14 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
62 private readonly List<IAlert> m_alerts = new List<IAlert>(); 64 private readonly List<IAlert> m_alerts = new List<IAlert>();
63 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 65 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
64 66
65 #region Implementation of IRegionModule
66
67 public MonitorModule() 67 public MonitorModule()
68 { 68 {
69 Enabled = true; 69 Enabled = true;
70 } 70 }
71 71
72 public void Initialise(Scene scene, IConfigSource source) 72 #region Implementation of INonSharedRegionModule
73
74 public void Initialise(IConfigSource source)
73 { 75 {
74 IConfig cnfg = source.Configs["Monitoring"]; 76 IConfig cnfg = source.Configs["Monitoring"];
75 77
@@ -79,6 +81,13 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
79 if (!Enabled) 81 if (!Enabled)
80 return; 82 return;
81 83
84 }
85
86 public void AddRegion(Scene scene)
87 {
88 if (!Enabled)
89 return;
90
82 m_scene = scene; 91 m_scene = scene;
83 92
84 m_scene.AddCommand("General", this, "monitor report", 93 m_scene.AddCommand("General", this, "monitor report",
@@ -89,101 +98,42 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
89 MainServer.Instance.AddHTTPHandler("/monitorstats/" + m_scene.RegionInfo.RegionID, StatsPage); 98 MainServer.Instance.AddHTTPHandler("/monitorstats/" + m_scene.RegionInfo.RegionID, StatsPage);
90 MainServer.Instance.AddHTTPHandler( 99 MainServer.Instance.AddHTTPHandler(
91 "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName), StatsPage); 100 "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName), StatsPage);
101
102 AddMonitors();
92 } 103 }
93 104
94 public void DebugMonitors(string module, string[] args) 105 public void RemoveRegion(Scene scene)
95 { 106 {
96 foreach (IMonitor monitor in m_staticMonitors) 107 if (!Enabled)
97 { 108 return;
98 m_log.InfoFormat(
99 "[MONITOR MODULE]: {0} reports {1} = {2}",
100 m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue());
101 }
102 109
103 foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats()) 110 MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + m_scene.RegionInfo.RegionID);
104 { 111 MainServer.Instance.RemoveHTTPHandler("GET", "/monitorstats/" + Uri.EscapeDataString(m_scene.RegionInfo.RegionName));
105 m_log.InfoFormat( 112 m_scene = null;
106 "[MONITOR MODULE]: {0} reports {1} = {2}",
107 m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value);
108 }
109 } 113 }
110 114
111 public void TestAlerts() 115 public void Close()
112 { 116 {
113 foreach (IAlert alert in m_alerts)
114 {
115 alert.Test();
116 }
117 } 117 }
118 118
119 public Hashtable StatsPage(Hashtable request) 119 public string Name
120 { 120 {
121 // If request was for a specific monitor 121 get { return "Region Health Monitoring Module"; }
122 // eg url/?monitor=Monitor.Name 122 }
123 if (request.ContainsKey("monitor"))
124 {
125 string monID = (string) request["monitor"];
126
127 foreach (IMonitor monitor in m_staticMonitors)
128 {
129 string elemName = monitor.ToString();
130 if (elemName.StartsWith(monitor.GetType().Namespace))
131 elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1);
132
133 if (elemName == monID || monitor.ToString() == monID)
134 {
135 Hashtable ereply3 = new Hashtable();
136
137 ereply3["int_response_code"] = 404; // 200 OK
138 ereply3["str_response_string"] = monitor.GetValue().ToString();
139 ereply3["content_type"] = "text/plain";
140
141 return ereply3;
142 }
143 }
144
145 // FIXME: Arguably this should also be done with dynamic monitors but I'm not sure what the above code
146 // is even doing. Why are we inspecting the type of the monitor???
147
148 // No monitor with that name
149 Hashtable ereply2 = new Hashtable();
150
151 ereply2["int_response_code"] = 404; // 200 OK
152 ereply2["str_response_string"] = "No such monitor";
153 ereply2["content_type"] = "text/plain";
154
155 return ereply2;
156 }
157
158 string xml = "<data>";
159 foreach (IMonitor monitor in m_staticMonitors)
160 {
161 string elemName = monitor.GetName();
162 xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">";
163// m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue());
164 }
165
166 foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
167 {
168 xml += "<" + tuple.Key + ">" + tuple.Value + "</" + tuple.Key + ">";
169 }
170
171 xml += "</data>";
172
173 Hashtable ereply = new Hashtable();
174
175 ereply["int_response_code"] = 200; // 200 OK
176 ereply["str_response_string"] = xml;
177 ereply["content_type"] = "text/xml";
178 123
179 return ereply; 124 public void RegionLoaded(Scene scene)
125 {
180 } 126 }
181 127
182 public void PostInitialise() 128 public Type ReplaceableInterface
183 { 129 {
184 if (!Enabled) 130 get { return null; }
185 return; 131 }
132
133 #endregion
186 134
135 public void AddMonitors()
136 {
187 m_staticMonitors.Add(new AgentCountMonitor(m_scene)); 137 m_staticMonitors.Add(new AgentCountMonitor(m_scene));
188 m_staticMonitors.Add(new ChildAgentCountMonitor(m_scene)); 138 m_staticMonitors.Add(new ChildAgentCountMonitor(m_scene));
189 m_staticMonitors.Add(new GCMemoryMonitor()); 139 m_staticMonitors.Add(new GCMemoryMonitor());
@@ -196,7 +146,7 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
196 m_staticMonitors.Add(new EventFrameMonitor(m_scene)); 146 m_staticMonitors.Add(new EventFrameMonitor(m_scene));
197 m_staticMonitors.Add(new LandFrameMonitor(m_scene)); 147 m_staticMonitors.Add(new LandFrameMonitor(m_scene));
198 m_staticMonitors.Add(new LastFrameTimeMonitor(m_scene)); 148 m_staticMonitors.Add(new LastFrameTimeMonitor(m_scene));
199 149
200 m_staticMonitors.Add( 150 m_staticMonitors.Add(
201 new GenericMonitor( 151 new GenericMonitor(
202 m_scene, 152 m_scene,
@@ -357,25 +307,98 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
357 } 307 }
358 } 308 }
359 309
360 void OnTriggerAlert(System.Type reporter, string reason, bool fatal) 310 public void DebugMonitors(string module, string[] args)
361 { 311 {
362 m_log.Error("[Monitor] " + reporter.Name + " for " + m_scene.RegionInfo.RegionName + " reports " + reason + " (Fatal: " + fatal + ")"); 312 foreach (IMonitor monitor in m_staticMonitors)
313 {
314 MainConsole.Instance.OutputFormat(
315 "[MONITOR MODULE]: {0} reports {1} = {2}",
316 m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue());
317 }
318
319 foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
320 {
321 MainConsole.Instance.OutputFormat(
322 "[MONITOR MODULE]: {0} reports {1} = {2}",
323 m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value);
324 }
363 } 325 }
364 326
365 public void Close() 327 public void TestAlerts()
366 { 328 {
329 foreach (IAlert alert in m_alerts)
330 {
331 alert.Test();
332 }
367 } 333 }
368 334
369 public string Name 335 public Hashtable StatsPage(Hashtable request)
370 { 336 {
371 get { return "Region Health Monitoring Module"; } 337 // If request was for a specific monitor
338 // eg url/?monitor=Monitor.Name
339 if (request.ContainsKey("monitor"))
340 {
341 string monID = (string) request["monitor"];
342
343 foreach (IMonitor monitor in m_staticMonitors)
344 {
345 string elemName = monitor.ToString();
346 if (elemName.StartsWith(monitor.GetType().Namespace))
347 elemName = elemName.Substring(monitor.GetType().Namespace.Length + 1);
348
349 if (elemName == monID || monitor.ToString() == monID)
350 {
351 Hashtable ereply3 = new Hashtable();
352
353 ereply3["int_response_code"] = 404; // 200 OK
354 ereply3["str_response_string"] = monitor.GetValue().ToString();
355 ereply3["content_type"] = "text/plain";
356
357 return ereply3;
358 }
359 }
360
361 // FIXME: Arguably this should also be done with dynamic monitors but I'm not sure what the above code
362 // is even doing. Why are we inspecting the type of the monitor???
363
364 // No monitor with that name
365 Hashtable ereply2 = new Hashtable();
366
367 ereply2["int_response_code"] = 404; // 200 OK
368 ereply2["str_response_string"] = "No such monitor";
369 ereply2["content_type"] = "text/plain";
370
371 return ereply2;
372 }
373
374 string xml = "<data>";
375 foreach (IMonitor monitor in m_staticMonitors)
376 {
377 string elemName = monitor.GetName();
378 xml += "<" + elemName + ">" + monitor.GetValue().ToString() + "</" + elemName + ">";
379// m_log.DebugFormat("[MONITOR MODULE]: {0} = {1}", elemName, monitor.GetValue());
380 }
381
382 foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
383 {
384 xml += "<" + tuple.Key + ">" + tuple.Value + "</" + tuple.Key + ">";
385 }
386
387 xml += "</data>";
388
389 Hashtable ereply = new Hashtable();
390
391 ereply["int_response_code"] = 200; // 200 OK
392 ereply["str_response_string"] = xml;
393 ereply["content_type"] = "text/xml";
394
395 return ereply;
372 } 396 }
373 397
374 public bool IsSharedModule 398 void OnTriggerAlert(System.Type reporter, string reason, bool fatal)
375 { 399 {
376 get { return false; } 400 m_log.Error("[Monitor] " + reporter.Name + " for " + m_scene.RegionInfo.RegionName + " reports " + reason + " (Fatal: " + fatal + ")");
377 } 401 }
378 402
379 #endregion
380 } 403 }
381} 404}
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
index 65e4c90..fd8d5e3 100755
--- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
+++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
@@ -1,161 +1,170 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.IO; 29using System.IO;
30using System.Text; 30using System.Text;
31using log4net; 31using log4net;
32 32
33namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging 33namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
34{ 34{
35 /// <summary> 35 /// <summary>
36 /// Class for writing a high performance, high volume log file. 36 /// Class for writing a high performance, high volume log file.
37 /// Sometimes, to debug, one has a high volume logging to do and the regular 37 /// Sometimes, to debug, one has a high volume logging to do and the regular
38 /// log file output is not appropriate. 38 /// log file output is not appropriate.
39 /// Create a new instance with the parameters needed and 39 /// Create a new instance with the parameters needed and
40 /// call Write() to output a line. Call Close() when finished. 40 /// call Write() to output a line. Call Close() when finished.
41 /// If created with no parameters, it will not log anything. 41 /// If created with no parameters, it will not log anything.
42 /// </summary> 42 /// </summary>
43 public class LogWriter : IDisposable 43 public class LogWriter : IDisposable
44 { 44 {
45 public bool Enabled { get; private set; } 45 public bool Enabled { get; private set; }
46 46
47 private string m_logDirectory = "."; 47 private string m_logDirectory = ".";
48 private int m_logMaxFileTimeMin = 5; // 5 minutes 48 private int m_logMaxFileTimeMin = 5; // 5 minutes
49 public String LogFileHeader { get; set; } 49 public String LogFileHeader { get; set; }
50 50
51 private StreamWriter m_logFile = null; 51 private StreamWriter m_logFile = null;
52 private TimeSpan m_logFileLife; 52 private TimeSpan m_logFileLife;
53 private DateTime m_logFileEndTime; 53 private DateTime m_logFileEndTime;
54 private Object m_logFileWriteLock = new Object(); 54 private Object m_logFileWriteLock = new Object();
55 55
56 // set externally when debugging. If let 'null', this does not write any error messages. 56 // set externally when debugging. If let 'null', this does not write any error messages.
57 public ILog ErrorLogger = null; 57 public ILog ErrorLogger = null;
58 private string LogHeader = "[LOG WRITER]"; 58 private string LogHeader = "[LOG WRITER]";
59 59
60 /// <summary> 60 /// <summary>
61 /// Create a log writer that will not write anything. Good for when not enabled 61 /// Create a log writer that will not write anything. Good for when not enabled
62 /// but the write statements are still in the code. 62 /// but the write statements are still in the code.
63 /// </summary> 63 /// </summary>
64 public LogWriter() 64 public LogWriter()
65 { 65 {
66 Enabled = false; 66 Enabled = false;
67 m_logFile = null; 67 m_logFile = null;
68 } 68 }
69 69
70 /// <summary> 70 /// <summary>
71 /// Create a log writer instance. 71 /// Create a log writer instance.
72 /// </summary> 72 /// </summary>
73 /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param> 73 /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param>
74 /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param> 74 /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param>
75 /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param> 75 /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param>
76 public LogWriter(string dir, string headr, int maxFileTime) 76 public LogWriter(string dir, string headr, int maxFileTime)
77 { 77 {
78 m_logDirectory = dir == null ? "." : dir; 78 m_logDirectory = dir == null ? "." : dir;
79 79
80 LogFileHeader = headr == null ? "log-" : headr; 80 LogFileHeader = headr == null ? "log-" : headr;
81 81
82 m_logMaxFileTimeMin = maxFileTime; 82 m_logMaxFileTimeMin = maxFileTime;
83 if (m_logMaxFileTimeMin < 1) 83 if (m_logMaxFileTimeMin < 1)
84 m_logMaxFileTimeMin = 5; 84 m_logMaxFileTimeMin = 5;
85 85
86 m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); 86 m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0);
87 m_logFileEndTime = DateTime.Now + m_logFileLife; 87 m_logFileEndTime = DateTime.Now + m_logFileLife;
88 88
89 Enabled = true; 89 Enabled = true;
90 } 90 }
91 91
92 public void Dispose() 92 public void Dispose()
93 { 93 {
94 this.Close(); 94 this.Close();
95 } 95 }
96 96
97 public void Close() 97 public void Close()
98 { 98 {
99 Enabled = false; 99 Enabled = false;
100 if (m_logFile != null) 100 if (m_logFile != null)
101 { 101 {
102 m_logFile.Close(); 102 m_logFile.Close();
103 m_logFile.Dispose(); 103 m_logFile.Dispose();
104 m_logFile = null; 104 m_logFile = null;
105 } 105 }
106 } 106 }
107 107
108 public void Write(string line, params object[] args) 108 public void Write(string line, params object[] args)
109 { 109 {
110 if (!Enabled) return; 110 if (!Enabled) return;
111 Write(String.Format(line, args)); 111 Write(String.Format(line, args));
112 } 112 }
113 113
114 public void Write(string line) 114 public void Flush()
115 { 115 {
116 if (!Enabled) return; 116 if (!Enabled) return;
117 try 117 if (m_logFile != null)
118 { 118 {
119 lock (m_logFileWriteLock) 119 m_logFile.Flush();
120 { 120 }
121 DateTime now = DateTime.Now; 121 }
122 if (m_logFile == null || now > m_logFileEndTime) 122
123 { 123 public void Write(string line)
124 if (m_logFile != null) 124 {
125 { 125 if (!Enabled) return;
126 m_logFile.Close(); 126 try
127 m_logFile.Dispose(); 127 {
128 m_logFile = null; 128 lock (m_logFileWriteLock)
129 } 129 {
130 130 DateTime now = DateTime.Now;
131 // First log file or time has expired, start writing to a new log file 131 if (m_logFile == null || now > m_logFileEndTime)
132 m_logFileEndTime = now + m_logFileLife; 132 {
133 string path = (m_logDirectory.Length > 0 ? m_logDirectory 133 if (m_logFile != null)
134 + System.IO.Path.DirectorySeparatorChar.ToString() : "") 134 {
135 + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); 135 m_logFile.Close();
136 m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); 136 m_logFile.Dispose();
137 } 137 m_logFile = null;
138 if (m_logFile != null) 138 }
139 { 139
140 StringBuilder buff = new StringBuilder(line.Length + 25); 140 // First log file or time has expired, start writing to a new log file
141 buff.Append(now.ToString("yyyyMMddHHmmssfff")); 141 m_logFileEndTime = now + m_logFileLife;
142 // buff.Append(now.ToString("yyyyMMddHHmmss")); 142 string path = (m_logDirectory.Length > 0 ? m_logDirectory
143 buff.Append(","); 143 + System.IO.Path.DirectorySeparatorChar.ToString() : "")
144 buff.Append(line); 144 + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss"));
145 buff.Append("\r\n"); 145 m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write));
146 m_logFile.Write(buff.ToString()); 146 }
147 } 147 if (m_logFile != null)
148 } 148 {
149 } 149 StringBuilder buff = new StringBuilder(line.Length + 25);
150 catch (Exception e) 150 buff.Append(now.ToString("yyyyMMddHHmmssfff"));
151 { 151 // buff.Append(now.ToString("yyyyMMddHHmmss"));
152 if (ErrorLogger != null) 152 buff.Append(",");
153 { 153 buff.Append(line);
154 ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); 154 buff.Append("\r\n");
155 } 155 m_logFile.Write(buff.ToString());
156 Enabled = false; 156 }
157 } 157 }
158 return; 158 }
159 } 159 catch (Exception e)
160 } 160 {
161} \ No newline at end of file 161 if (ErrorLogger != null)
162 {
163 ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
164 }
165 Enabled = false;
166 }
167 return;
168 }
169 }
170}
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
index 4eecaa2..4ef57fe 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
@@ -41,9 +41,11 @@ using OpenMetaverse;
41using OpenMetaverse.Packets; 41using OpenMetaverse.Packets;
42using log4net; 42using log4net;
43using Nini.Config; 43using Nini.Config;
44using Mono.Addins;
44 45
45namespace OpenSim.Region.CoreModules.Framework.UserManagement 46namespace OpenSim.Region.CoreModules.Framework.UserManagement
46{ 47{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGUserManagementModule")]
47 public class HGUserManagementModule : UserManagementModule, ISharedRegionModule, IUserManagement 49 public class HGUserManagementModule : UserManagementModule, ISharedRegionModule, IUserManagement
48 { 50 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -137,6 +139,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
137 ud.FirstName = words[0]; 139 ud.FirstName = words[0];
138 ud.LastName = "@" + words[1]; 140 ud.LastName = "@" + words[1];
139 users.Add(ud); 141 users.Add(ud);
142 // WARNING! that uriStr is not quite right... it may be missing the / at the end,
143 // which will cause trouble (duplicate entries on some tables). We should
144 // get the UUI instead from the UAS. TO BE FIXED.
140 AddUser(userID, names[0], names[1], uriStr); 145 AddUser(userID, names[0], names[1], uriStr);
141 m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]); 146 m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]);
142 } 147 }
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index f4ed67b..86e7004 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -31,6 +31,7 @@ using System.Reflection;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Framework.Console; 33using OpenSim.Framework.Console;
34using OpenSim.Region.ClientStack.LindenUDP;
34using OpenSim.Region.Framework; 35using OpenSim.Region.Framework;
35using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
@@ -41,6 +42,7 @@ using OpenMetaverse;
41using OpenMetaverse.Packets; 42using OpenMetaverse.Packets;
42using log4net; 43using log4net;
43using Nini.Config; 44using Nini.Config;
45using Mono.Addins;
44 46
45namespace OpenSim.Region.CoreModules.Framework.UserManagement 47namespace OpenSim.Region.CoreModules.Framework.UserManagement
46{ 48{
@@ -53,6 +55,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
53 public Dictionary<string, object> ServerURLs { get; set; } 55 public Dictionary<string, object> ServerURLs { get; set; }
54 } 56 }
55 57
58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")]
56 public class UserManagementModule : ISharedRegionModule, IUserManagement 59 public class UserManagementModule : ISharedRegionModule, IUserManagement
57 { 60 {
58 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -429,8 +432,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
429 432
430 public void AddUser(UUID uuid, string first, string last, string homeURL) 433 public void AddUser(UUID uuid, string first, string last, string homeURL)
431 { 434 {
432 // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); 435 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL);
433
434 AddUser(uuid, homeURL + ";" + first + " " + last); 436 AddUser(uuid, homeURL + ";" + first + " " + last);
435 } 437 }
436 438
@@ -553,8 +555,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
553 MainConsole.Instance.Output("-----------------------------------------------------------------------------"); 555 MainConsole.Instance.Output("-----------------------------------------------------------------------------");
554 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache) 556 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache)
555 { 557 {
556 MainConsole.Instance.Output(String.Format("{0} {1} {2}", 558 MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})",
557 kvp.Key, kvp.Value.FirstName, kvp.Value.LastName)); 559 kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL));
558 } 560 }
559 561
560 return; 562 return;
diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
index 4f18b53..ec94420 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 Mono.Addins;
34using OpenSim.Framework; 35using OpenSim.Framework;
35using OpenSim.Region.CoreModules.World.WorldMap; 36using OpenSim.Region.CoreModules.World.WorldMap;
36using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
@@ -39,6 +40,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39 40
40namespace OpenSim.Region.CoreModules.Hypergrid 41namespace OpenSim.Region.CoreModules.Hypergrid
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGWorldMapModule")]
42 public class HGWorldMapModule : WorldMapModule 44 public class HGWorldMapModule : WorldMapModule
43 { 45 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/CoreModules/InterGrid/OGSRadmin.cs b/OpenSim/Region/CoreModules/InterGrid/OGSRadmin.cs
deleted file mode 100644
index 2cc0a07..0000000
--- a/OpenSim/Region/CoreModules/InterGrid/OGSRadmin.cs
+++ /dev/null
@@ -1,150 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33using System.Text;
34using log4net;
35using Nini.Config;
36using Nwc.XmlRpc;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Communications;
40using OpenSim.Framework.Servers;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43
44namespace OpenSim.Region.CoreModules.InterGrid
45{
46 public class OGSRadmin : IRegionModule
47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 private readonly List<Scene> m_scenes = new List<Scene>();
50 private IConfigSource m_settings;
51
52 #region Implementation of IRegionModuleBase
53
54 public string Name
55 {
56 get { return "OGS Supporting RAdmin"; }
57 }
58
59
60 public void Initialise(IConfigSource source)
61 {
62 m_settings = source;
63 }
64
65 public void Close()
66 {
67
68 }
69
70 public void AddRegion(Scene scene)
71 {
72 lock (m_scenes)
73 m_scenes.Add(scene);
74 }
75
76 public void RemoveRegion(Scene scene)
77 {
78 lock (m_scenes)
79 m_scenes.Remove(scene);
80 }
81
82 public void RegionLoaded(Scene scene)
83 {
84
85 }
86
87 public void PostInitialise()
88 {
89 if (m_settings.Configs["Startup"].GetBoolean("gridmode", false))
90 {
91 MainServer.Instance.AddXmlRPCHandler("grid_message", GridWideMessage);
92 }
93 }
94
95 #endregion
96
97 #region IRegionModule
98
99 public void Initialise(Scene scene, IConfigSource source)
100 {
101 m_settings = source;
102
103 lock (m_scenes)
104 m_scenes.Add(scene);
105 }
106
107 public bool IsSharedModule
108 {
109 get { return true; }
110 }
111
112 #endregion
113
114 public XmlRpcResponse GridWideMessage(XmlRpcRequest req, IPEndPoint remoteClient)
115 {
116 XmlRpcResponse response = new XmlRpcResponse();
117 Hashtable responseData = new Hashtable();
118
119 Hashtable requestData = (Hashtable)req.Params[0];
120
121 // REFACTORING PROBLEM. This authorization needs to be replaced with some other
122 //if ((!requestData.Contains("password") || (string)requestData["password"] != m_com.NetworkServersInfo.GridRecvKey))
123 //{
124 // responseData["accepted"] = false;
125 // responseData["success"] = false;
126 // responseData["error"] = "Invalid Key";
127 // response.Value = responseData;
128 // return response;
129 //}
130
131 string message = (string)requestData["message"];
132 string user = (string)requestData["user"];
133 m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message);
134
135 lock (m_scenes)
136 foreach (Scene scene in m_scenes)
137 {
138 IDialogModule dialogModule = scene.RequestModuleInterface<IDialogModule>();
139 if (dialogModule != null)
140 dialogModule.SendNotificationToUsersInRegion(UUID.Random(), user, message);
141 }
142
143 responseData["accepted"] = true;
144 responseData["success"] = true;
145 response.Value = responseData;
146
147 return response;
148 }
149 }
150}
diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
deleted file mode 100644
index 4a76b00..0000000
--- a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
+++ /dev/null
@@ -1,1297 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Net;
32using System.Net.Security;
33using System.Reflection;
34using System.Security.Cryptography.X509Certificates;
35using System.Threading;
36using System.Web;
37using log4net;
38using Nini.Config;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41using OpenSim.Framework;
42using OpenSim.Framework.Capabilities;
43using OpenSim.Framework.Monitoring;
44using OpenSim.Framework.Servers;
45using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes;
47using Caps=OpenSim.Framework.Capabilities.Caps;
48using OSDArray=OpenMetaverse.StructuredData.OSDArray;
49using OSDMap=OpenMetaverse.StructuredData.OSDMap;
50
51namespace OpenSim.Region.CoreModules.InterGrid
52{
53 public struct OGPState
54 {
55 public string first_name;
56 public string last_name;
57 public UUID agent_id;
58 public UUID local_agent_id;
59 public UUID region_id;
60 public uint circuit_code;
61 public UUID secure_session_id;
62 public UUID session_id;
63 public bool agent_access;
64 public string sim_access;
65 public uint god_level;
66 public bool god_overide;
67 public bool identified;
68 public bool transacted;
69 public bool age_verified;
70 public bool allow_redirect;
71 public int limited_to_estate;
72 public string inventory_host;
73 public bool src_can_see_mainland;
74 public int src_estate_id;
75 public int src_version;
76 public int src_parent_estate_id;
77 public bool visible_to_parent;
78 public string teleported_into_region;
79 }
80
81 public class OpenGridProtocolModule : IRegionModule
82 {
83 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
84 private List<Scene> m_scene = new List<Scene>();
85
86 private Dictionary<string, AgentCircuitData> CapsLoginID = new Dictionary<string, AgentCircuitData>();
87 private Dictionary<UUID, OGPState> m_OGPState = new Dictionary<UUID, OGPState>();
88 private Dictionary<string, string> m_loginToRegionState = new Dictionary<string, string>();
89
90
91 private string LastNameSuffix = "_EXTERNAL";
92 private string FirstNamePrefix = "";
93 private string httpsCN = "";
94 private bool httpSSL = false;
95 private uint httpsslport = 0;
96// private bool GridMode = false;
97
98 #region IRegionModule Members
99
100 public void Initialise(Scene scene, IConfigSource config)
101 {
102 bool enabled = false;
103 IConfig cfg = null;
104 IConfig httpcfg = null;
105// IConfig startupcfg = null;
106 try
107 {
108 cfg = config.Configs["OpenGridProtocol"];
109 } catch (NullReferenceException)
110 {
111 enabled = false;
112 }
113
114 try
115 {
116 httpcfg = config.Configs["Network"];
117 }
118 catch (NullReferenceException)
119 {
120
121 }
122// try
123// {
124// startupcfg = config.Configs["Startup"];
125// }
126// catch (NullReferenceException)
127// {
128//
129// }
130
131// if (startupcfg != null)
132// {
133// GridMode = enabled = startupcfg.GetBoolean("gridmode", false);
134// }
135
136 if (cfg != null)
137 {
138 enabled = cfg.GetBoolean("ogp_enabled", false);
139 LastNameSuffix = cfg.GetString("ogp_lastname_suffix", "_EXTERNAL");
140 FirstNamePrefix = cfg.GetString("ogp_firstname_prefix", "");
141 if (enabled)
142 {
143 m_log.Warn("[OGP]: Open Grid Protocol is on, Listening for Clients on /agent/");
144 lock (m_scene)
145 {
146 if (m_scene.Count == 0)
147 {
148 MainServer.Instance.AddLLSDHandler("/agent/", ProcessAgentDomainMessage);
149 MainServer.Instance.AddLLSDHandler("/", ProcessRegionDomainSeed);
150 try
151 {
152 ServicePointManager.ServerCertificateValidationCallback += customXertificateValidation;
153 }
154 catch (NotImplementedException)
155 {
156 try
157 {
158#pragma warning disable 0612, 0618
159 // Mono does not implement the ServicePointManager.ServerCertificateValidationCallback yet! Don't remove this!
160 ServicePointManager.CertificatePolicy = new MonoCert();
161#pragma warning restore 0612, 0618
162 }
163 catch (Exception)
164 {
165 m_log.Error("[OGP]: Certificate validation handler change not supported. You may get ssl certificate validation errors teleporting from your region to some SSL regions.");
166 }
167 }
168
169 }
170 // can't pick the region 'agent' because it would conflict with our agent domain handler
171 // a zero length region name would conflict with are base region seed cap
172 if (!SceneListDuplicateCheck(scene.RegionInfo.RegionName) && scene.RegionInfo.RegionName.ToLower() != "agent" && scene.RegionInfo.RegionName.Length > 0)
173 {
174 MainServer.Instance.AddLLSDHandler(
175 "/" + HttpUtility.UrlPathEncode(scene.RegionInfo.RegionName.ToLower()),
176 ProcessRegionDomainSeed);
177 }
178
179 if (!m_scene.Contains(scene))
180 m_scene.Add(scene);
181 }
182 }
183 }
184 lock (m_scene)
185 {
186 if (m_scene.Count == 1)
187 {
188 if (httpcfg != null)
189 {
190 httpSSL = httpcfg.GetBoolean("http_listener_ssl", false);
191 httpsCN = httpcfg.GetString("http_listener_cn", scene.RegionInfo.ExternalHostName);
192 if (httpsCN.Length == 0)
193 httpsCN = scene.RegionInfo.ExternalHostName;
194 httpsslport = (uint)httpcfg.GetInt("http_listener_sslport",((int)scene.RegionInfo.HttpPort + 1));
195 }
196 }
197 }
198 }
199
200 public void PostInitialise()
201 {
202 }
203
204 public void Close()
205 {
206 //scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel;
207 }
208
209 public string Name
210 {
211 get { return "OpenGridProtocolModule"; }
212 }
213
214 public bool IsSharedModule
215 {
216 get { return true; }
217 }
218
219 #endregion
220
221 public OSD ProcessRegionDomainSeed(string path, OSD request, string endpoint)
222 {
223 string[] pathSegments = path.Split('/');
224
225 if (pathSegments.Length <= 1)
226 {
227 return GenerateNoHandlerMessage();
228
229 }
230
231 return GenerateRezAvatarRequestMessage(pathSegments[1]);
232
233
234
235 //m_log.InfoFormat("[OGP]: path {0}, segments {1} segment[1] {2} Last segment {3}",
236 // path, pathSegments.Length, pathSegments[1], pathSegments[pathSegments.Length - 1]);
237 //return new OSDMap();
238
239 }
240
241 public OSD ProcessAgentDomainMessage(string path, OSD request, string endpoint)
242 {
243 // /agent/*
244
245 string[] pathSegments = path.Split('/');
246 if (pathSegments.Length <= 1)
247 {
248 return GenerateNoHandlerMessage();
249
250 }
251 if (pathSegments[0].Length == 0 && pathSegments[1].Length == 0)
252 {
253 return GenerateRezAvatarRequestMessage("");
254 }
255 m_log.InfoFormat("[OGP]: path {0}, segments {1} segment[1] {2} Last segment {3}",
256 path, pathSegments.Length, pathSegments[1], pathSegments[pathSegments.Length - 1]);
257
258 switch (pathSegments[pathSegments.Length - 1])
259 {
260 case "rez_avatar":
261 return RezAvatarMethod(path, request);
262 //break;
263 case "derez_avatar":
264 return DerezAvatarMethod(path, request);
265 //break;
266
267 }
268 if (path.Length < 2)
269 {
270 return GenerateNoHandlerMessage();
271 }
272
273 switch (pathSegments[pathSegments.Length - 2] + "/" + pathSegments[pathSegments.Length - 1])
274 {
275 case "rez_avatar/rez":
276 return RezAvatarMethod(path, request);
277 //break;
278 case "rez_avatar/request":
279 return RequestRezAvatarMethod(path, request);
280 case "rez_avatar/place":
281 return RequestRezAvatarMethod(path, request);
282 case "rez_avatar/derez":
283 return DerezAvatarMethod(path, request);
284 //break;
285 default:
286 return GenerateNoHandlerMessage();
287 }
288 //return null;
289 }
290
291 private OSD GenerateRezAvatarRequestMessage(string regionname)
292 {
293 Scene region = null;
294 bool usedroot = false;
295
296 if (regionname.Length == 0)
297 {
298 region = GetRootScene();
299 usedroot = true;
300 }
301 else
302 {
303 region = GetScene(HttpUtility.UrlDecode(regionname).ToLower());
304 }
305
306 // this shouldn't happen since we don't listen for a region that is down.. but
307 // it might if the region was taken down or is in the middle of restarting
308
309 if (region == null)
310 {
311 region = GetRootScene();
312 usedroot = true;
313 }
314
315 UUID statekeeper = UUID.Random();
316
317
318
319
320 RegionInfo reg = region.RegionInfo;
321
322 OSDMap responseMap = new OSDMap();
323 string rezHttpProtocol = "http://";
324 //string regionCapsHttpProtocol = "http://";
325 string httpaddr = reg.ExternalHostName;
326 string urlport = reg.HttpPort.ToString();
327 string requestpath = "/agent/" + statekeeper + "/rez_avatar/request";
328
329 if (!usedroot)
330 {
331 lock (m_loginToRegionState)
332 {
333 if (!m_loginToRegionState.ContainsKey(requestpath))
334 {
335 m_loginToRegionState.Add(requestpath, region.RegionInfo.RegionName.ToLower());
336 }
337 }
338 }
339
340 if (httpSSL)
341 {
342 rezHttpProtocol = "https://";
343 //regionCapsHttpProtocol = "https://";
344 urlport = httpsslport.ToString();
345
346 if (httpsCN.Length > 0)
347 httpaddr = httpsCN;
348 }
349
350 responseMap["connect"] = OSD.FromBoolean(true);
351 OSDMap capabilitiesMap = new OSDMap();
352 capabilitiesMap["rez_avatar/request"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + requestpath);
353 responseMap["capabilities"] = capabilitiesMap;
354
355 return responseMap;
356 }
357
358 // Using OpenSim.Framework.Capabilities.Caps here one time..
359 // so the long name is probably better then a using statement
360 public void OnRegisterCaps(UUID agentID, Caps caps)
361 {
362 /* If we ever want to register our own caps here....
363 *
364 string capsBase = "/CAPS/" + caps.CapsObjectPath;
365 caps.RegisterHandler("CAPNAME",
366 new RestStreamHandler("POST", capsBase + CAPSPOSTFIX!,
367 delegate(string request, string path, string param,
368 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
369 {
370 return METHODHANDLER(request, path, param,
371 agentID, caps);
372 }));
373
374 *
375 */
376 }
377
378 public OSD RequestRezAvatarMethod(string path, OSD request)
379 {
380 //m_log.Debug("[REQUESTREZAVATAR]: " + request.ToString());
381
382 OSDMap requestMap = (OSDMap)request;
383
384
385 Scene homeScene = null;
386
387 lock (m_loginToRegionState)
388 {
389 if (m_loginToRegionState.ContainsKey(path))
390 {
391 homeScene = GetScene(m_loginToRegionState[path]);
392 m_loginToRegionState.Remove(path);
393
394 if (homeScene == null)
395 homeScene = GetRootScene();
396 }
397 else
398 {
399 homeScene = GetRootScene();
400 }
401 }
402
403 // Homescene is still null, we must have no regions that are up
404 if (homeScene == null)
405 return GenerateNoHandlerMessage();
406
407 RegionInfo reg = homeScene.RegionInfo;
408 ulong regionhandle = GetOSCompatibleRegionHandle(reg);
409 //string RegionURI = reg.ServerURI;
410 //int RegionPort = (int)reg.HttpPort;
411
412 UUID RemoteAgentID = requestMap["agent_id"].AsUUID();
413
414 // will be used in the future. The client always connects with the aditi agentid currently
415 UUID LocalAgentID = RemoteAgentID;
416
417 string FirstName = requestMap["first_name"].AsString();
418 string LastName = requestMap["last_name"].AsString();
419
420 FirstName = FirstNamePrefix + FirstName;
421 LastName = LastName + LastNameSuffix;
422
423 OGPState userState = GetOGPState(LocalAgentID);
424
425 userState.first_name = requestMap["first_name"].AsString();
426 userState.last_name = requestMap["last_name"].AsString();
427 userState.age_verified = requestMap["age_verified"].AsBoolean();
428 userState.transacted = requestMap["transacted"].AsBoolean();
429 userState.agent_access = requestMap["agent_access"].AsBoolean();
430 userState.allow_redirect = requestMap["allow_redirect"].AsBoolean();
431 userState.identified = requestMap["identified"].AsBoolean();
432 userState.god_level = (uint)requestMap["god_level"].AsInteger();
433 userState.sim_access = requestMap["sim_access"].AsString();
434 userState.agent_id = RemoteAgentID;
435 userState.limited_to_estate = requestMap["limited_to_estate"].AsInteger();
436 userState.src_can_see_mainland = requestMap["src_can_see_mainland"].AsBoolean();
437 userState.src_estate_id = requestMap["src_estate_id"].AsInteger();
438 userState.local_agent_id = LocalAgentID;
439 userState.teleported_into_region = reg.RegionName.ToLower();
440
441 UpdateOGPState(LocalAgentID, userState);
442
443 OSDMap responseMap = new OSDMap();
444
445 if (RemoteAgentID == UUID.Zero)
446 {
447 responseMap["connect"] = OSD.FromBoolean(false);
448 responseMap["message"] = OSD.FromString("No agent ID was specified in rez_avatar/request");
449 m_log.Error("[OGP]: rez_avatar/request failed because no avatar UUID was provided in the request body");
450 return responseMap;
451 }
452
453 responseMap["sim_host"] = OSD.FromString(reg.ExternalHostName);
454
455 // DEPRECATED
456 responseMap["sim_ip"] = OSD.FromString(Util.GetHostFromDNS(reg.ExternalHostName).ToString());
457
458 responseMap["connect"] = OSD.FromBoolean(true);
459 responseMap["sim_port"] = OSD.FromInteger(reg.InternalEndPoint.Port);
460 responseMap["region_x"] = OSD.FromInteger(reg.RegionLocX * (uint)Constants.RegionSize); // LLX
461 responseMap["region_y"] = OSD.FromInteger(reg.RegionLocY * (uint)Constants.RegionSize); // LLY
462 responseMap["region_id"] = OSD.FromUUID(reg.originRegionID);
463
464 if (reg.RegionSettings.Maturity == 1)
465 {
466 responseMap["sim_access"] = OSD.FromString("Mature");
467 }
468 else if (reg.RegionSettings.Maturity == 2)
469 {
470 responseMap["sim_access"] = OSD.FromString("Adult");
471 }
472 else
473 {
474 responseMap["sim_access"] = OSD.FromString("PG");
475 }
476
477 // Generate a dummy agent for the user so we can get back a CAPS path
478 AgentCircuitData agentData = new AgentCircuitData();
479 agentData.AgentID = LocalAgentID;
480 agentData.BaseFolder = UUID.Zero;
481 agentData.CapsPath = CapsUtil.GetRandomCapsObjectPath();
482 agentData.child = false;
483 agentData.circuitcode = (uint)(Util.RandomClass.Next());
484 agentData.firstname = FirstName;
485 agentData.lastname = LastName;
486 agentData.SecureSessionID = UUID.Random();
487 agentData.SessionID = UUID.Random();
488 agentData.startpos = new Vector3(128f, 128f, 100f);
489
490 // Pre-Fill our region cache with information on the agent.
491 UserAgentData useragent = new UserAgentData();
492 useragent.AgentIP = "unknown";
493 useragent.AgentOnline = true;
494 useragent.AgentPort = (uint)0;
495 useragent.Handle = regionhandle;
496 useragent.InitialRegion = reg.originRegionID;
497 useragent.LoginTime = Util.UnixTimeSinceEpoch();
498 useragent.LogoutTime = 0;
499 useragent.Position = agentData.startpos;
500 useragent.Region = reg.originRegionID;
501 useragent.SecureSessionID = agentData.SecureSessionID;
502 useragent.SessionID = agentData.SessionID;
503
504 UserProfileData userProfile = new UserProfileData();
505 userProfile.AboutText = "OGP User";
506 userProfile.CanDoMask = (uint)0;
507 userProfile.Created = Util.UnixTimeSinceEpoch();
508 userProfile.CurrentAgent = useragent;
509 userProfile.CustomType = "OGP";
510 userProfile.FirstLifeAboutText = "I'm testing OpenGrid Protocol";
511 userProfile.FirstLifeImage = UUID.Zero;
512 userProfile.FirstName = agentData.firstname;
513 userProfile.GodLevel = 0;
514 userProfile.HomeLocation = agentData.startpos;
515 userProfile.HomeLocationX = agentData.startpos.X;
516 userProfile.HomeLocationY = agentData.startpos.Y;
517 userProfile.HomeLocationZ = agentData.startpos.Z;
518 userProfile.HomeLookAt = Vector3.Zero;
519 userProfile.HomeLookAtX = userProfile.HomeLookAt.X;
520 userProfile.HomeLookAtY = userProfile.HomeLookAt.Y;
521 userProfile.HomeLookAtZ = userProfile.HomeLookAt.Z;
522 userProfile.HomeRegion = reg.RegionHandle;
523 userProfile.HomeRegionID = reg.originRegionID;
524 userProfile.HomeRegionX = reg.RegionLocX;
525 userProfile.HomeRegionY = reg.RegionLocY;
526 userProfile.ID = agentData.AgentID;
527 userProfile.Image = UUID.Zero;
528 userProfile.LastLogin = Util.UnixTimeSinceEpoch();
529 userProfile.Partner = UUID.Zero;
530 userProfile.PasswordHash = "$1$";
531 userProfile.PasswordSalt = "";
532 userProfile.SurName = agentData.lastname;
533 //userProfile.UserAssetURI = homeScene.CommsManager.NetworkServersInfo.AssetURL;
534 userProfile.UserFlags = 0;
535 //userProfile.UserInventoryURI = homeScene.CommsManager.NetworkServersInfo.InventoryURL;
536 userProfile.WantDoMask = 0;
537 userProfile.WebLoginKey = UUID.Random();
538
539 // !!! REFACTORING PROBLEM. This needs to be changed for 0.7
540 //
541 //// Do caps registration
542 //// get seed capagentData.firstname = FirstName;agentData.lastname = LastName;
543 //if (homeScene.CommsManager.UserService.GetUserProfile(agentData.AgentID) == null && !GridMode)
544 //{
545 // homeScene.CommsManager.UserAdminService.AddUser(
546 // agentData.firstname, agentData.lastname, CreateRandomStr(7), "",
547 // homeScene.RegionInfo.RegionLocX, homeScene.RegionInfo.RegionLocY, agentData.AgentID);
548
549 // UserProfileData userProfile2 = homeScene.CommsManager.UserService.GetUserProfile(agentData.AgentID);
550 // if (userProfile2 != null)
551 // {
552 // userProfile = userProfile2;
553 // userProfile.AboutText = "OGP USER";
554 // userProfile.FirstLifeAboutText = "OGP USER";
555 // homeScene.CommsManager.UserService.UpdateUserProfile(userProfile);
556 // }
557 //}
558
559 //// Stick our data in the cache so the region will know something about us
560 //homeScene.CommsManager.UserProfileCacheService.PreloadUserCache(userProfile);
561
562 // Call 'new user' event handler
563 string reason;
564 if (!homeScene.NewUserConnection(agentData, (uint)TeleportFlags.ViaLogin, out reason))
565 {
566 responseMap["connect"] = OSD.FromBoolean(false);
567 responseMap["message"] = OSD.FromString(String.Format("Connection refused: {0}", reason));
568 m_log.ErrorFormat("[OGP]: rez_avatar/request failed: {0}", reason);
569 return responseMap;
570 }
571
572
573 //string raCap = string.Empty;
574
575 UUID AvatarRezCapUUID = LocalAgentID;
576 string rezAvatarPath = "/agent/" + AvatarRezCapUUID + "/rez_avatar/rez";
577 string derezAvatarPath = "/agent/" + AvatarRezCapUUID + "/rez_avatar/derez";
578 // Get a reference to the user's cap so we can pull out the Caps Object Path
579 Caps userCap
580 = homeScene.CapsModule.GetCapsForUser(agentData.AgentID);
581
582 string rezHttpProtocol = "http://";
583 string regionCapsHttpProtocol = "http://";
584 string httpaddr = reg.ExternalHostName;
585 string urlport = reg.HttpPort.ToString();
586
587 if (httpSSL)
588 {
589 rezHttpProtocol = "https://";
590 regionCapsHttpProtocol = "https://";
591 urlport = httpsslport.ToString();
592
593 if (httpsCN.Length > 0)
594 httpaddr = httpsCN;
595 }
596
597 // DEPRECATED
598 responseMap["seed_capability"]
599 = OSD.FromString(
600 regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + "/" + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath));
601
602 // REPLACEMENT
603 responseMap["region_seed_capability"]
604 = OSD.FromString(
605 regionCapsHttpProtocol + httpaddr + ":" + reg.HttpPort + "/" + CapsUtil.GetCapsSeedPath(userCap.CapsObjectPath));
606
607 responseMap["rez_avatar"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath);
608 responseMap["rez_avatar/rez"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + rezAvatarPath);
609 responseMap["rez_avatar/derez"] = OSD.FromString(rezHttpProtocol + httpaddr + ":" + urlport + derezAvatarPath);
610
611 // Add the user to the list of CAPS that are outstanding.
612 // well allow the caps hosts in this dictionary
613 lock (CapsLoginID)
614 {
615 if (CapsLoginID.ContainsKey(rezAvatarPath))
616 {
617 CapsLoginID[rezAvatarPath] = agentData;
618
619 // This is a joke, if you didn't notice... It's so unlikely to happen, that I'll print this message if it does occur!
620 m_log.Error("[OGP]: Holy anomoly batman! Caps path already existed! All the UUID Duplication worries were founded!");
621 }
622 else
623 {
624 CapsLoginID.Add(rezAvatarPath, agentData);
625 }
626 }
627
628 //m_log.Debug("Response:" + responseMap.ToString());
629 return responseMap;
630 }
631
632 public OSD RezAvatarMethod(string path, OSD request)
633 {
634 m_log.WarnFormat("[REZAVATAR]: {0}", request.ToString());
635
636 OSDMap responseMap = new OSDMap();
637
638 AgentCircuitData userData = null;
639
640 // Only people we've issued a cap can go further
641 if (TryGetAgentCircuitData(path,out userData))
642 {
643 OSDMap requestMap = (OSDMap)request;
644
645 // take these values to start. There's a few more
646 UUID SecureSessionID=requestMap["secure_session_id"].AsUUID();
647 UUID SessionID = requestMap["session_id"].AsUUID();
648 int circuitcode = requestMap["circuit_code"].AsInteger();
649 OSDArray Parameter = new OSDArray();
650 if (requestMap.ContainsKey("parameter"))
651 {
652 Parameter = (OSDArray)requestMap["parameter"];
653 }
654
655 //int version = 1;
656 int estateID = 1;
657 int parentEstateID = 1;
658 UUID regionID = UUID.Zero;
659 bool visibleToParent = true;
660
661 for (int i = 0; i < Parameter.Count; i++)
662 {
663 OSDMap item = (OSDMap)Parameter[i];
664// if (item.ContainsKey("version"))
665// {
666// version = item["version"].AsInteger();
667// }
668 if (item.ContainsKey("estate_id"))
669 {
670 estateID = item["estate_id"].AsInteger();
671 }
672 if (item.ContainsKey("parent_estate_id"))
673 {
674 parentEstateID = item["parent_estate_id"].AsInteger();
675
676 }
677 if (item.ContainsKey("region_id"))
678 {
679 regionID = item["region_id"].AsUUID();
680
681 }
682 if (item.ContainsKey("visible_to_parent"))
683 {
684 visibleToParent = item["visible_to_parent"].AsBoolean();
685 }
686 }
687 //Update our Circuit data with the real values
688 userData.SecureSessionID = SecureSessionID;
689 userData.SessionID = SessionID;
690
691 OGPState userState = GetOGPState(userData.AgentID);
692
693 // Locate a home scene suitable for the user.
694 Scene homeScene = null;
695
696 homeScene = GetScene(userState.teleported_into_region);
697
698 if (homeScene == null)
699 homeScene = GetRootScene();
700
701 if (homeScene != null)
702 {
703 // Get a referenceokay - to their Cap object so we can pull out the capobjectroot
704 Caps userCap
705 = homeScene.CapsModule.GetCapsForUser(userData.AgentID);
706
707 //Update the circuit data in the region so this user is authorized
708 homeScene.UpdateCircuitData(userData);
709 homeScene.ChangeCircuitCode(userData.circuitcode,(uint)circuitcode);
710
711 // Load state
712
713
714 // Keep state changes
715 userState.first_name = requestMap["first_name"].AsString();
716 userState.secure_session_id = requestMap["secure_session_id"].AsUUID();
717 userState.age_verified = requestMap["age_verified"].AsBoolean();
718 userState.region_id = homeScene.RegionInfo.originRegionID; // replace 0000000 with our regionid
719 userState.transacted = requestMap["transacted"].AsBoolean();
720 userState.agent_access = requestMap["agent_access"].AsBoolean();
721 userState.inventory_host = requestMap["inventory_host"].AsString();
722 userState.identified = requestMap["identified"].AsBoolean();
723 userState.session_id = requestMap["session_id"].AsUUID();
724 userState.god_level = (uint)requestMap["god_level"].AsInteger();
725 userState.last_name = requestMap["last_name"].AsString();
726 userState.god_overide = requestMap["god_override"].AsBoolean();
727 userState.circuit_code = (uint)requestMap["circuit_code"].AsInteger();
728 userState.limited_to_estate = requestMap["limited_to_estate"].AsInteger();
729 userState.src_estate_id = estateID;
730 userState.region_id = regionID;
731 userState.src_parent_estate_id = parentEstateID;
732 userState.visible_to_parent = visibleToParent;
733
734 // Save state changes
735 UpdateOGPState(userData.AgentID, userState);
736
737 // Get the region information for the home region.
738 RegionInfo reg = homeScene.RegionInfo;
739
740 // Dummy positional and look at info.. we don't have it.
741 OSDArray PositionArray = new OSDArray();
742 PositionArray.Add(OSD.FromInteger(128));
743 PositionArray.Add(OSD.FromInteger(128));
744 PositionArray.Add(OSD.FromInteger(40));
745
746 OSDArray LookAtArray = new OSDArray();
747 LookAtArray.Add(OSD.FromInteger(1));
748 LookAtArray.Add(OSD.FromInteger(1));
749 LookAtArray.Add(OSD.FromInteger(1));
750
751 // Our region's X and Y position in OpenSimulator space.
752 uint fooX = reg.RegionLocX;
753 uint fooY = reg.RegionLocY;
754 m_log.InfoFormat("[OGP]: region x({0}) region y({1})", fooX, fooY);
755 m_log.InfoFormat("[OGP]: region http {0} {1}", reg.ServerURI, reg.HttpPort);
756 m_log.InfoFormat("[OGO]: region UUID {0} ", reg.RegionID);
757
758 // Convert the X and Y position to LL space
759 responseMap["region_x"] = OSD.FromInteger(fooX * (uint)Constants.RegionSize); // convert it to LL X
760 responseMap["region_y"] = OSD.FromInteger(fooY * (uint)Constants.RegionSize); // convert it to LL Y
761
762 // Give em a new seed capability
763 responseMap["seed_capability"] = OSD.FromString("http://" + reg.ExternalHostName + ":" + reg.HttpPort + "/CAPS/" + userCap.CapsObjectPath + "0000/");
764 responseMap["region"] = OSD.FromUUID(reg.originRegionID);
765 responseMap["look_at"] = LookAtArray;
766
767 responseMap["sim_port"] = OSD.FromInteger(reg.InternalEndPoint.Port);
768 responseMap["sim_host"] = OSD.FromString(reg.ExternalHostName);// + ":" + reg.InternalEndPoint.Port.ToString());
769
770 // DEPRECATED
771 responseMap["sim_ip"] = OSD.FromString(Util.GetHostFromDNS(reg.ExternalHostName).ToString());
772
773 responseMap["session_id"] = OSD.FromUUID(SessionID);
774 responseMap["secure_session_id"] = OSD.FromUUID(SecureSessionID);
775 responseMap["circuit_code"] = OSD.FromInteger(circuitcode);
776
777 responseMap["position"] = PositionArray;
778
779 responseMap["region_id"] = OSD.FromUUID(reg.originRegionID);
780
781 responseMap["sim_access"] = OSD.FromString("Mature");
782
783 responseMap["connect"] = OSD.FromBoolean(true);
784
785
786
787 m_log.InfoFormat("[OGP]: host: {0}, IP {1}", responseMap["sim_host"].ToString(), responseMap["sim_ip"].ToString());
788 }
789 }
790
791 return responseMap;
792 }
793
794 public OSD DerezAvatarMethod(string path, OSD request)
795 {
796 m_log.ErrorFormat("DerezPath: {0}, Request: {1}", path, request.ToString());
797
798 //LLSD llsdResponse = null;
799 OSDMap responseMap = new OSDMap();
800
801 string[] PathArray = path.Split('/');
802 m_log.InfoFormat("[OGP]: prefix {0}, uuid {1}, suffix {2}", PathArray[1], PathArray[2], PathArray[3]);
803 string uuidString = PathArray[2];
804 m_log.InfoFormat("[OGP]: Request to Derez avatar with UUID {0}", uuidString);
805 UUID userUUID = UUID.Zero;
806 if (UUID.TryParse(uuidString, out userUUID))
807 {
808 UUID RemoteID = (UUID)uuidString;
809 UUID LocalID = RemoteID;
810 // FIXME: TODO: Routine to map RemoteUUIDs to LocalUUIds
811 // would be done already.. but the client connects with the Aditi UUID
812 // regardless over the UDP stack
813
814 OGPState userState = GetOGPState(LocalID);
815 if (userState.agent_id != UUID.Zero)
816 {
817 //OSDMap outboundRequestMap = new OSDMap();
818 OSDMap inboundRequestMap = (OSDMap)request;
819 string rezAvatarString = inboundRequestMap["rez_avatar"].AsString();
820 if (rezAvatarString.Length == 0)
821 {
822 rezAvatarString = inboundRequestMap["rez_avatar/rez"].AsString();
823 }
824 OSDArray LookAtArray = new OSDArray();
825 LookAtArray.Add(OSD.FromInteger(1));
826 LookAtArray.Add(OSD.FromInteger(1));
827 LookAtArray.Add(OSD.FromInteger(1));
828
829 OSDArray PositionArray = new OSDArray();
830 PositionArray.Add(OSD.FromInteger(128));
831 PositionArray.Add(OSD.FromInteger(128));
832 PositionArray.Add(OSD.FromInteger(40));
833
834 OSDArray lookArray = new OSDArray();
835 lookArray.Add(OSD.FromInteger(128));
836 lookArray.Add(OSD.FromInteger(128));
837 lookArray.Add(OSD.FromInteger(40));
838
839 responseMap["connect"] = OSD.FromBoolean(true);// it's okay to give this user up
840 responseMap["look_at"] = LookAtArray;
841
842 m_log.WarnFormat("[OGP]: Invoking rez_avatar on host:{0} for avatar: {1} {2}", rezAvatarString, userState.first_name, userState.last_name);
843
844 OSDMap rezResponseMap = invokeRezAvatarCap(responseMap, rezAvatarString,userState);
845
846 // If invoking it returned an error, parse and end
847 if (rezResponseMap.ContainsKey("connect"))
848 {
849 if (rezResponseMap["connect"].AsBoolean() == false)
850 {
851 return responseMap;
852 }
853 }
854
855 string rezRespSeedCap = "";
856
857 // DEPRECATED
858 if (rezResponseMap.ContainsKey("seed_capability"))
859 rezRespSeedCap = rezResponseMap["seed_capability"].AsString();
860
861 // REPLACEMENT
862 if (rezResponseMap.ContainsKey("region_seed_capability"))
863 rezRespSeedCap = rezResponseMap["region_seed_capability"].AsString();
864
865 // REPLACEMENT
866 if (rezResponseMap.ContainsKey("rez_avatar/rez"))
867 rezRespSeedCap = rezResponseMap["rez_avatar/rez"].AsString();
868
869 // DEPRECATED
870 string rezRespSim_ip = rezResponseMap["sim_ip"].AsString();
871
872 string rezRespSim_host = rezResponseMap["sim_host"].AsString();
873
874 int rrPort = rezResponseMap["sim_port"].AsInteger();
875 int rrX = rezResponseMap["region_x"].AsInteger();
876 int rrY = rezResponseMap["region_y"].AsInteger();
877 m_log.ErrorFormat("X:{0}, Y:{1}", rrX, rrY);
878 UUID rrRID = rezResponseMap["region_id"].AsUUID();
879 OSDArray RezResponsePositionArray = null;
880 string rrAccess = rezResponseMap["sim_access"].AsString();
881 if (rezResponseMap.ContainsKey("position"))
882 {
883 RezResponsePositionArray = (OSDArray)rezResponseMap["position"];
884 }
885 // DEPRECATED
886 responseMap["seed_capability"] = OSD.FromString(rezRespSeedCap);
887
888 // REPLACEMENT r3
889 responseMap["region_seed_capability"] = OSD.FromString(rezRespSeedCap);
890
891 // DEPRECATED
892 responseMap["sim_ip"] = OSD.FromString(Util.GetHostFromDNS(rezRespSim_ip).ToString());
893
894 responseMap["sim_host"] = OSD.FromString(rezRespSim_host);
895 responseMap["sim_port"] = OSD.FromInteger(rrPort);
896 responseMap["region_x"] = OSD.FromInteger(rrX);
897 responseMap["region_y"] = OSD.FromInteger(rrY);
898 responseMap["region_id"] = OSD.FromUUID(rrRID);
899 responseMap["sim_access"] = OSD.FromString(rrAccess);
900
901 if (RezResponsePositionArray != null)
902 {
903 responseMap["position"] = RezResponsePositionArray;
904 }
905 responseMap["look_at"] = lookArray;
906 responseMap["connect"] = OSD.FromBoolean(true);
907
908 ShutdownConnection(LocalID,this);
909 // PLEASE STOP CHANGING THIS TO an M_LOG, M_LOG DOESN'T WORK ON MULTILINE .TOSTRINGS
910 Console.WriteLine("RESPONSEDEREZ: " + responseMap.ToString());
911 return responseMap;
912 }
913 else
914 {
915 return GenerateNoStateMessage(LocalID);
916 }
917 }
918 else
919 {
920 return GenerateNoHandlerMessage();
921 }
922
923 //return responseMap;
924 }
925
926 private OSDMap invokeRezAvatarCap(OSDMap responseMap, string CapAddress, OGPState userState)
927 {
928 Scene reg = GetRootScene();
929
930 WebRequest DeRezRequest = WebRequest.Create(CapAddress);
931 DeRezRequest.Method = "POST";
932 DeRezRequest.ContentType = "application/xml+llsd";
933
934 OSDMap RAMap = new OSDMap();
935 OSDMap AgentParms = new OSDMap();
936 OSDMap RegionParms = new OSDMap();
937
938 OSDArray Parameter = new OSDArray(2);
939
940 OSDMap version = new OSDMap();
941 version["version"] = OSD.FromInteger(userState.src_version);
942 Parameter.Add(version);
943
944 OSDMap SrcData = new OSDMap();
945 SrcData["estate_id"] = OSD.FromInteger(reg.RegionInfo.EstateSettings.EstateID);
946 SrcData["parent_estate_id"] = OSD.FromInteger((reg.RegionInfo.EstateSettings.ParentEstateID == 100 ? 1 : reg.RegionInfo.EstateSettings.ParentEstateID));
947 SrcData["region_id"] = OSD.FromUUID(reg.RegionInfo.originRegionID);
948 SrcData["visible_to_parent"] = OSD.FromBoolean(userState.visible_to_parent);
949 Parameter.Add(SrcData);
950
951 AgentParms["first_name"] = OSD.FromString(userState.first_name);
952 AgentParms["last_name"] = OSD.FromString(userState.last_name);
953 AgentParms["agent_id"] = OSD.FromUUID(userState.agent_id);
954 RegionParms["region_id"] = OSD.FromUUID(userState.region_id);
955 AgentParms["circuit_code"] = OSD.FromInteger(userState.circuit_code);
956 AgentParms["secure_session_id"] = OSD.FromUUID(userState.secure_session_id);
957 AgentParms["session_id"] = OSD.FromUUID(userState.session_id);
958 AgentParms["agent_access"] = OSD.FromBoolean(userState.agent_access);
959 AgentParms["god_level"] = OSD.FromInteger(userState.god_level);
960 AgentParms["god_overide"] = OSD.FromBoolean(userState.god_overide);
961 AgentParms["identified"] = OSD.FromBoolean(userState.identified);
962 AgentParms["transacted"] = OSD.FromBoolean(userState.transacted);
963 AgentParms["age_verified"] = OSD.FromBoolean(userState.age_verified);
964 AgentParms["limited_to_estate"] = OSD.FromInteger(userState.limited_to_estate);
965 AgentParms["inventory_host"] = OSD.FromString(userState.inventory_host);
966
967 // version 1
968 RAMap = AgentParms;
969
970 // Planned for version 2
971 // RAMap["agent_params"] = AgentParms;
972
973 RAMap["region_params"] = RegionParms;
974 RAMap["parameter"] = Parameter;
975
976 string RAMapString = RAMap.ToString();
977 m_log.InfoFormat("[OGP] RAMap string {0}", RAMapString);
978 OSD LLSDofRAMap = RAMap; // RENAME if this works
979
980 m_log.InfoFormat("[OGP]: LLSD of map as string was {0}", LLSDofRAMap.ToString());
981 //m_log.InfoFormat("[OGP]: LLSD+XML: {0}", LLSDParser.SerializeXmlString(LLSDofRAMap));
982 byte[] buffer = OSDParser.SerializeLLSDXmlBytes(LLSDofRAMap);
983
984 //string bufferDump = System.Text.Encoding.ASCII.GetString(buffer);
985 //m_log.InfoFormat("[OGP]: buffer form is {0}",bufferDump);
986 //m_log.InfoFormat("[OGP]: LLSD of map was {0}",buffer.Length);
987
988 Stream os = null;
989 try
990 { // send the Post
991 DeRezRequest.ContentLength = buffer.Length; //Count bytes to send
992 os = DeRezRequest.GetRequestStream();
993 os.Write(buffer, 0, buffer.Length); //Send it
994 os.Close();
995 m_log.InfoFormat("[OGP]: Derez Avatar Posted Rez Avatar request to remote sim {0}", CapAddress);
996 }
997 catch (WebException ex)
998 {
999 m_log.InfoFormat("[OGP] Bad send on de_rez_avatar {0}", ex.Message);
1000 responseMap["connect"] = OSD.FromBoolean(false);
1001
1002 return responseMap;
1003 }
1004
1005 m_log.Info("[OGP] waiting for a reply after rez avatar send");
1006 string rez_avatar_reply = null;
1007 { // get the response
1008 try
1009 {
1010 WebResponse webResponse = DeRezRequest.GetResponse();
1011 if (webResponse == null)
1012 {
1013 m_log.Info("[OGP:] Null reply on rez_avatar post");
1014 }
1015
1016 StreamReader sr = new StreamReader(webResponse.GetResponseStream());
1017 rez_avatar_reply = sr.ReadToEnd().Trim();
1018 m_log.InfoFormat("[OGP]: rez_avatar reply was {0} ", rez_avatar_reply);
1019
1020 }
1021 catch (WebException ex)
1022 {
1023 m_log.InfoFormat("[OGP]: exception on read after send of rez avatar {0}", ex.Message);
1024 responseMap["connect"] = OSD.FromBoolean(false);
1025
1026 return responseMap;
1027 }
1028 OSD rezResponse = null;
1029 try
1030 {
1031 rezResponse = OSDParser.DeserializeLLSDXml(rez_avatar_reply);
1032
1033 responseMap = (OSDMap)rezResponse;
1034 }
1035 catch (Exception ex)
1036 {
1037 m_log.InfoFormat("[OGP]: exception on parse of rez reply {0}", ex.Message);
1038 responseMap["connect"] = OSD.FromBoolean(false);
1039
1040 return responseMap;
1041 }
1042 }
1043 return responseMap;
1044 }
1045
1046 public OSD GenerateNoHandlerMessage()
1047 {
1048 OSDMap map = new OSDMap();
1049 map["reason"] = OSD.FromString("LLSDRequest");
1050 map["message"] = OSD.FromString("No handler registered for LLSD Requests");
1051 map["login"] = OSD.FromString("false");
1052 map["connect"] = OSD.FromString("false");
1053 return map;
1054 }
1055 public OSD GenerateNoStateMessage(UUID passedAvatar)
1056 {
1057 OSDMap map = new OSDMap();
1058 map["reason"] = OSD.FromString("derez failed");
1059 map["message"] = OSD.FromString("Unable to locate OGP state for avatar " + passedAvatar.ToString());
1060 map["login"] = OSD.FromString("false");
1061 map["connect"] = OSD.FromString("false");
1062 return map;
1063 }
1064 private bool TryGetAgentCircuitData(string path, out AgentCircuitData userdata)
1065 {
1066 userdata = null;
1067 lock (CapsLoginID)
1068 {
1069 if (CapsLoginID.ContainsKey(path))
1070 {
1071 userdata = CapsLoginID[path];
1072 DiscardUsedCap(path);
1073 return true;
1074 }
1075 }
1076 return false;
1077 }
1078
1079 private void DiscardUsedCap(string path)
1080 {
1081 CapsLoginID.Remove(path);
1082 }
1083
1084 private Scene GetRootScene()
1085 {
1086 Scene ReturnScene = null;
1087 lock (m_scene)
1088 {
1089 if (m_scene.Count > 0)
1090 {
1091 ReturnScene = m_scene[0];
1092 }
1093 }
1094
1095 return ReturnScene;
1096 }
1097
1098 private Scene GetScene(string scenename)
1099 {
1100 Scene ReturnScene = null;
1101 lock (m_scene)
1102 {
1103 foreach (Scene s in m_scene)
1104 {
1105 if (s.RegionInfo.RegionName.ToLower() == scenename)
1106 {
1107 ReturnScene = s;
1108 break;
1109 }
1110 }
1111 }
1112
1113 return ReturnScene;
1114 }
1115
1116 private ulong GetOSCompatibleRegionHandle(RegionInfo reg)
1117 {
1118 return Util.UIntsToLong(reg.RegionLocX, reg.RegionLocY);
1119 }
1120
1121 private OGPState InitializeNewState()
1122 {
1123 OGPState returnState = new OGPState();
1124 returnState.first_name = "";
1125 returnState.last_name = "";
1126 returnState.agent_id = UUID.Zero;
1127 returnState.local_agent_id = UUID.Zero;
1128 returnState.region_id = UUID.Zero;
1129 returnState.circuit_code = 0;
1130 returnState.secure_session_id = UUID.Zero;
1131 returnState.session_id = UUID.Zero;
1132 returnState.agent_access = true;
1133 returnState.god_level = 0;
1134 returnState.god_overide = false;
1135 returnState.identified = false;
1136 returnState.transacted = false;
1137 returnState.age_verified = false;
1138 returnState.limited_to_estate = 1;
1139 returnState.inventory_host = "http://inv4.mysql.aditi.lindenlab.com";
1140 returnState.allow_redirect = true;
1141 returnState.sim_access = "";
1142 returnState.src_can_see_mainland = true;
1143 returnState.src_estate_id = 1;
1144 returnState.src_version = 1;
1145 returnState.src_parent_estate_id = 1;
1146 returnState.visible_to_parent = true;
1147 returnState.teleported_into_region = "";
1148
1149 return returnState;
1150 }
1151
1152 private OGPState GetOGPState(UUID agentId)
1153 {
1154 lock (m_OGPState)
1155 {
1156 if (m_OGPState.ContainsKey(agentId))
1157 {
1158 return m_OGPState[agentId];
1159 }
1160 else
1161 {
1162 return InitializeNewState();
1163 }
1164 }
1165 }
1166
1167 public void DeleteOGPState(UUID agentId)
1168 {
1169 lock (m_OGPState)
1170 {
1171 if (m_OGPState.ContainsKey(agentId))
1172 m_OGPState.Remove(agentId);
1173 }
1174 }
1175
1176 private void UpdateOGPState(UUID agentId, OGPState state)
1177 {
1178 lock (m_OGPState)
1179 {
1180 if (m_OGPState.ContainsKey(agentId))
1181 {
1182 m_OGPState[agentId] = state;
1183 }
1184 else
1185 {
1186 m_OGPState.Add(agentId,state);
1187 }
1188 }
1189 }
1190 private bool SceneListDuplicateCheck(string str)
1191 {
1192 // no lock, called from locked space!
1193 bool found = false;
1194
1195 foreach (Scene s in m_scene)
1196 {
1197 if (s.RegionInfo.RegionName == str)
1198 {
1199 found = true;
1200 break;
1201 }
1202 }
1203
1204 return found;
1205 }
1206
1207 public void ShutdownConnection(UUID avatarId, OpenGridProtocolModule mod)
1208 {
1209 Scene homeScene = GetRootScene();
1210 ScenePresence avatar = null;
1211 if (homeScene.TryGetScenePresence(avatarId,out avatar))
1212 {
1213 KillAUser ku = new KillAUser(avatar,mod);
1214 Watchdog.StartThread(ku.ShutdownNoLogout, "OGPShutdown", ThreadPriority.Normal, true, true);
1215 }
1216 }
1217
1218// private string CreateRandomStr(int len)
1219// {
1220// Random rnd = new Random(Environment.TickCount);
1221// string returnstring = "";
1222// string chars = "abcdefghijklmnopqrstuvwxyz0123456789";
1223//
1224// for (int i = 0; i < len; i++)
1225// {
1226// returnstring += chars.Substring(rnd.Next(chars.Length), 1);
1227// }
1228// return returnstring;
1229// }
1230
1231 // Temporary hack to allow teleporting to and from Vaak
1232 private static bool customXertificateValidation(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
1233 {
1234 //if (cert.Subject == "E=root@lindenlab.com, CN=*.vaak.lindenlab.com, O=\"Linden Lab, Inc.\", L=San Francisco, S=California, C=US")
1235 //{
1236 return true;
1237 //}
1238
1239 //return false;
1240 }
1241 }
1242
1243 public class KillAUser
1244 {
1245 private ScenePresence avToBeKilled = null;
1246 private OpenGridProtocolModule m_mod = null;
1247
1248 public KillAUser(ScenePresence avatar, OpenGridProtocolModule mod)
1249 {
1250 avToBeKilled = avatar;
1251 m_mod = mod;
1252 }
1253
1254 public void ShutdownNoLogout()
1255 {
1256 UUID avUUID = UUID.Zero;
1257
1258 if (avToBeKilled != null)
1259 {
1260 avUUID = avToBeKilled.UUID;
1261 avToBeKilled.MakeChildAgent();
1262
1263 avToBeKilled.ControllingClient.SendLogoutPacketWhenClosing = false;
1264
1265 int sleepMS = 30000;
1266 while (sleepMS > 0)
1267 {
1268 Watchdog.UpdateThread();
1269 Thread.Sleep(1000);
1270 sleepMS -= 1000;
1271 }
1272
1273 // test for child agent because they might have come back
1274 if (avToBeKilled.IsChildAgent)
1275 {
1276 m_mod.DeleteOGPState(avUUID);
1277 avToBeKilled.ControllingClient.Close();
1278 }
1279 }
1280
1281 Watchdog.RemoveThread();
1282 }
1283
1284 }
1285
1286 public class MonoCert : ICertificatePolicy
1287 {
1288 #region ICertificatePolicy Members
1289
1290 public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem)
1291 {
1292 return true;
1293 }
1294
1295 #endregion
1296 }
1297}
diff --git a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..5a8c4a2
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
@@ -0,0 +1,38 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4using Mono.Addins;
5
6// General Information about an assembly is controlled through the following
7// set of attributes. Change these attribute values to modify the information
8// associated with an assembly.
9[assembly: AssemblyTitle("OpenSim.Region.CoreModules")]
10[assembly: AssemblyDescription("Core modules for OpenSim")]
11[assembly: AssemblyConfiguration("")]
12[assembly: AssemblyCompany("")]
13[assembly: AssemblyProduct("OpenSim.Region.CoreModules.Properties")]
14[assembly: AssemblyCopyright("Copyright © 2012")]
15[assembly: AssemblyTrademark("")]
16[assembly: AssemblyCulture("")]
17
18// Setting ComVisible to false makes the types in this assembly not visible
19// to COM components. If you need to access a type in this assembly from
20// COM, set the ComVisible attribute to true on that type.
21[assembly: ComVisible(false)]
22
23// The following GUID is for the ID of the typelib if this project is exposed to COM
24[assembly: Guid("94f62dd1-bcf3-4218-9844-9a3996286e3e")]
25
26// Version information for an assembly consists of the following four values:
27//
28// Major Version
29// Minor Version
30// Build Number
31// Revision
32//
33[assembly: AssemblyVersion("0.7.5.*")]
34[assembly: AssemblyFileVersion("1.0.0.0")]
35
36[assembly: Addin("OpenSim.Region.CoreModules", "0.1")]
37[assembly: AddinDependency("OpenSim", "0.5")]
38
diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
deleted file mode 100644
index 424e0ab..0000000
--- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
+++ /dev/null
@@ -1,90 +0,0 @@
1<Addin id="OpenSim.Region.CoreModules" version="0.3">
2 <Runtime>
3 <Import assembly="OpenSim.Region.CoreModules.dll"/>
4 </Runtime>
5
6 <Dependencies>
7 <Addin id="OpenSim" version="0.5" />
8 </Dependencies>
9
10 <Extension path = "/OpenSim/RegionModules">
11 <RegionModule id="UserManagementModule" type="OpenSim.Region.CoreModules.Framework.UserManagement.UserManagementModule" />
12 <RegionModule id="HGUserManagementModule" type="OpenSim.Region.CoreModules.Framework.UserManagement.HGUserManagementModule" />
13 <RegionModule id="EntityTransferModule" type="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule" />
14 <RegionModule id="HGEntityTransferModule" type="OpenSim.Region.CoreModules.Framework.EntityTransfer.HGEntityTransferModule" />
15 <RegionModule id="InventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.BasicInventoryAccessModule" />
16 <RegionModule id="HGInventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.HGInventoryAccessModule" />
17 <RegionModule id="LandManagementModule" type="OpenSim.Region.CoreModules.World.Land.LandManagementModule" />
18 <RegionModule id="PrimCountModule" type="OpenSim.Region.CoreModules.World.Land.PrimCountModule" />
19 <RegionModule id="ExportSerialisationModule" type="OpenSim.Region.CoreModules.World.Serialiser.SerialiserModule" />
20 <RegionModule id="ArchiverModule" type="OpenSim.Region.CoreModules.World.Archiver.ArchiverModule" />
21 <RegionModule id="TerrainModule" type="OpenSim.Region.CoreModules.World.Terrain.TerrainModule" />
22 <RegionModule id="WorldMapModule" type="OpenSim.Region.CoreModules.World.WorldMap.WorldMapModule" />
23 <RegionModule id="Warp3DImageModule" type="OpenSim.Region.CoreModules.World.Warp3DMap.Warp3DImageModule" />
24 <RegionModule id="HGWorldMapModule" type="OpenSim.Region.CoreModules.Hypergrid.HGWorldMapModule" />
25 <RegionModule id="UrlModule" type="OpenSim.Region.CoreModules.Scripting.LSLHttp.UrlModule" />
26 <RegionModule id="Chat" type="OpenSim.Region.CoreModules.Avatar.Chat.ChatModule" />
27 <RegionModule id="FriendsModule" type="OpenSim.Region.CoreModules.Avatar.Friends.FriendsModule" />
28 <RegionModule id="HGFriendsModule" type="OpenSim.Region.CoreModules.Avatar.Friends.HGFriendsModule" />
29 <RegionModule id="PresenceModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.PresenceModule" />
30 <RegionModule id="MuteListModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.MuteListModule" />
31 <RegionModule id="OfflineMessageModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.OfflineMessageModule" />
32 <RegionModule id="InstantMessageModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.InstantMessageModule" />
33 <RegionModule id="MessageTransferModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.MessageTransferModule" />
34 <RegionModule id="LureModule" type="OpenSim.Region.CoreModules.Avatar.Lure.LureModule" />
35 <RegionModule id="InventoryTransferModule" type="OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.InventoryTransferModule" />
36 <RegionModule id="CoreAssetCache" type="OpenSim.Region.CoreModules.Asset.CoreAssetCache" />
37 <RegionModule id="GlynnTuckerAssetCache" type="OpenSim.Region.CoreModules.Asset.GlynnTuckerAssetCache" />
38 <RegionModule id="CenomeMemoryAssetCache" type="OpenSim.Region.CoreModules.Asset.CenomeMemoryAssetCache"/>
39 <RegionModule id="LibraryModule" type="OpenSim.Region.CoreModules.Framework.Library.LibraryModule"/>
40 <!-- Service connectors OUT modules -->
41 <RegionModule id="LocalAssetServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.LocalAssetServicesConnector" />
42 <RegionModule id="RemoteAssetServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.RemoteAssetServicesConnector" />
43 <RegionModule id="LocalAvatarServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar.LocalAvatarServicesConnector" />
44 <RegionModule id="RemoteAvatarServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar.RemoteAvatarServicesConnector" />
45 <RegionModule id="LocalAuthenticationServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication.LocalAuthenticationServicesConnector" />
46 <RegionModule id="RemoteAuthenticationServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication.RemoteAuthenticationServicesConnector" />
47 <RegionModule id="LocalAuthorizationServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization.LocalAuthorizationServicesConnector" />
48 <RegionModule id="RemoteAuthorizationServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization.RemoteAuthorizationServicesConnector" />
49 <RegionModule id="HGAssetBroker" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.HGAssetBroker" />
50 <RegionModule id="LocalInventoryServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory.LocalInventoryServicesConnector" />
51 <RegionModule id="RemoteXInventoryServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory.RemoteXInventoryServicesConnector" />
52 <RegionModule id="HGInventoryBroker" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory.HGInventoryBroker" />
53 <RegionModule id="LocalNeighbourServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour.LocalNeighbourServicesConnector" />
54 <RegionModule id="RemoteNeighbourServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour.RemoteNeighbourServicesConnector" />
55 <RegionModule id="LocalLandServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Land.LocalLandServicesConnector" />
56 <RegionModule id="RemoteLandServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Land.RemoteLandServicesConnector" />
57 <RegionModule id="LocalGridServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.LocalGridServicesConnector" />
58 <RegionModule id="RemoteGridServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.RemoteGridServicesConnector" />
59 <RegionModule id="LocalPresenceServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.LocalPresenceServicesConnector" />
60 <RegionModule id="RemotePresenceServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.RemotePresenceServicesConnector" />
61 <RegionModule id="LocalUserAccountServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts.LocalUserAccountServicesConnector" />
62 <RegionModule id="RemoteUserAccountServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts.RemoteUserAccountServicesConnector" />
63
64 <RegionModule id="LocalGridUserServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser.LocalGridUserServicesConnector" />
65 <RegionModule id="RemoteGridUserServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser.RemoteGridUserServicesConnector" />
66
67 <RegionModule id="LocalSimulationConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation.LocalSimulationConnectorModule" />
68 <RegionModule id="RemoteSimulationConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation.RemoteSimulationConnectorModule" />
69
70 <!-- Service connectors IN modules -->
71 <RegionModule id="AssetServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Asset.AssetServiceInConnectorModule" />
72 <RegionModule id="InventoryServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory.InventoryServiceInConnectorModule" />
73 <RegionModule id="LandServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Land.LandServiceInConnectorModule" />
74 <RegionModule id="NeighbourServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Neighbour.NeighbourServiceInConnectorModule" /> \
75 <RegionModule id="HypergridServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid.HypergridServiceInConnectorModule" /> \
76 <RegionModule id="LLLoginServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Login.LLLoginServiceInConnectorModule" /> \
77 <RegionModule id="SimulationServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Simulation.SimulationServiceInConnectorModule" /> \
78 <RegionModule id="GridInfoServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Grid.GridInfoServiceInConnectorModule" /> \
79 <RegionModule id="AuthenticationServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication.AuthenticationServiceInConnectorModule" />
80 <RegionModule id="AccessModule" type="OpenSim.Region.CoreModules.World.AccessModule" /> \
81 <RegionModule id="MapImageModule" type="OpenSim.Region.CoreModules.World.LegacyMap.MapImageModule" /> \
82
83 </Extension>
84
85 <Extension path = "/OpenSim/WindModule">
86 <WindModel id="ConfigurableWind" type="OpenSim.Region.CoreModules.World.Wind.Plugins.ConfigurableWind" />
87 <WindModel id="SimpleRandomWind" type="OpenSim.Region.CoreModules.World.Wind.Plugins.SimpleRandomWind" />
88 </Extension>
89
90</Addin>
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
new file mode 100644
index 0000000..fce9490
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
@@ -0,0 +1,61 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Drawing;
30using OpenSim.Region.Framework.Interfaces;
31
32namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
33{
34 public class DynamicTexture : IDynamicTexture
35 {
36 public string InputCommands { get; private set; }
37 public Uri InputUri { get; private set; }
38 public string InputParams { get; private set; }
39 public byte[] Data { get; private set; }
40 public Size Size { get; private set; }
41 public bool IsReuseable { get; private set; }
42
43 public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable)
44 {
45 InputCommands = inputCommands;
46 InputParams = inputParams;
47 Data = data;
48 Size = size;
49 IsReuseable = isReuseable;
50 }
51
52 public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable)
53 {
54 InputUri = inputUri;
55 InputParams = inputParams;
56 Data = data;
57 Size = size;
58 IsReuseable = isReuseable;
59 }
60 }
61} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index 18bd018..9d77b19 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -37,18 +37,36 @@ using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using log4net; 38using log4net;
39using System.Reflection; 39using System.Reflection;
40using Mono.Addins;
40 41
41namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture 42namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
42{ 43{
43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DynamicTextureModule")]
45 public class DynamicTextureModule : ISharedRegionModule, IDynamicTextureManager
44 { 46 {
45 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 48
47 private const int ALL_SIDES = -1; 49 private const int ALL_SIDES = -1;
48 50
49 public const int DISP_EXPIRE = 1; 51 public const int DISP_EXPIRE = 1;
50 public const int DISP_TEMP = 2; 52 public const int DISP_TEMP = 2;
51 53
54 /// <summary>
55 /// If true then where possible dynamic textures are reused.
56 /// </summary>
57 public bool ReuseTextures { get; set; }
58
59 /// <summary>
60 /// If false, then textures which have a low data size are not reused when ReuseTextures = true.
61 /// </summary>
62 /// <remarks>
63 /// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those
64 /// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen
65 /// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is
66 /// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused
67 /// to work around this problem.</remarks>
68 public bool ReuseLowDataTextures { get; set; }
69
52 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); 70 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
53 71
54 private Dictionary<string, IDynamicTextureRender> RenderPlugins = 72 private Dictionary<string, IDynamicTextureRender> RenderPlugins =
@@ -56,6 +74,25 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
56 74
57 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>(); 75 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>();
58 76
77 /// <summary>
78 /// Record dynamic textures that we can reuse for a given data and parameter combination rather than
79 /// regenerate.
80 /// </summary>
81 /// <remarks>
82 /// Key is string.Format("{0}{1}", data
83 /// </remarks>
84 private Cache m_reuseableDynamicTextures;
85
86 /// <summary>
87 /// This constructor is only here because of the Unit Tests...
88 /// Don't use it.
89 /// </summary>
90 public DynamicTextureModule()
91 {
92 m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
93 m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
94 }
95
59 #region IDynamicTextureManager Members 96 #region IDynamicTextureManager Members
60 97
61 public void RegisterRender(string handleType, IDynamicTextureRender render) 98 public void RegisterRender(string handleType, IDynamicTextureRender render)
@@ -69,17 +106,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
69 /// <summary> 106 /// <summary>
70 /// Called by code which actually renders the dynamic texture to supply texture data. 107 /// Called by code which actually renders the dynamic texture to supply texture data.
71 /// </summary> 108 /// </summary>
72 /// <param name="id"></param> 109 /// <param name="updaterId"></param>
73 /// <param name="data"></param> 110 /// <param name="texture"></param>
74 public void ReturnData(UUID id, byte[] data) 111 public void ReturnData(UUID updaterId, IDynamicTexture texture)
75 { 112 {
76 DynamicTextureUpdater updater = null; 113 DynamicTextureUpdater updater = null;
77 114
78 lock (Updaters) 115 lock (Updaters)
79 { 116 {
80 if (Updaters.ContainsKey(id)) 117 if (Updaters.ContainsKey(updaterId))
81 { 118 {
82 updater = Updaters[id]; 119 updater = Updaters[updaterId];
83 } 120 }
84 } 121 }
85 122
@@ -88,7 +125,16 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
88 if (RegisteredScenes.ContainsKey(updater.SimUUID)) 125 if (RegisteredScenes.ContainsKey(updater.SimUUID))
89 { 126 {
90 Scene scene = RegisteredScenes[updater.SimUUID]; 127 Scene scene = RegisteredScenes[updater.SimUUID];
91 updater.DataReceived(data, scene); 128 UUID newTextureID = updater.DataReceived(texture.Data, scene);
129
130 if (ReuseTextures
131 && !updater.BlendWithOldTexture
132 && texture.IsReuseable
133 && (ReuseLowDataTextures || IsDataSizeReuseable(texture)))
134 {
135 m_reuseableDynamicTextures.Store(
136 GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
137 }
92 } 138 }
93 } 139 }
94 140
@@ -104,6 +150,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
104 } 150 }
105 } 151 }
106 152
153 /// <summary>
154 /// Determines whether the texture is reuseable based on its data size.
155 /// </summary>
156 /// <remarks>
157 /// This is a workaround for a viewer bug where very small data size textures relative to their pixel size
158 /// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard
159 /// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5).
160 /// </remarks>
161 /// <returns></returns>
162 private bool IsDataSizeReuseable(IDynamicTexture texture)
163 {
164// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height);
165 int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5);
166
167// m_log.DebugFormat(
168// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}",
169// discardLevel2DataThreshold, texture.Data.Length);
170
171 return discardLevel2DataThreshold < texture.Data.Length;
172 }
173
107 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, 174 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
108 string extraParams, int updateTimer) 175 string extraParams, int updateTimer)
109 { 176 {
@@ -167,22 +234,61 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
167 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, 234 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
168 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) 235 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face)
169 { 236 {
170 if (RenderPlugins.ContainsKey(contentType)) 237 if (!RenderPlugins.ContainsKey(contentType))
238 return UUID.Zero;
239
240 Scene scene;
241 RegisteredScenes.TryGetValue(simID, out scene);
242
243 if (scene == null)
244 return UUID.Zero;
245
246 SceneObjectPart part = scene.GetSceneObjectPart(primID);
247
248 if (part == null)
249 return UUID.Zero;
250
251 // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire
252 // them.
253 if (ReuseTextures)
254 disp = disp & ~DISP_EXPIRE;
255
256 DynamicTextureUpdater updater = new DynamicTextureUpdater();
257 updater.SimUUID = simID;
258 updater.PrimID = primID;
259 updater.ContentType = contentType;
260 updater.BodyData = data;
261 updater.UpdateTimer = updateTimer;
262 updater.UpdaterID = UUID.Random();
263 updater.Params = extraParams;
264 updater.BlendWithOldTexture = SetBlending;
265 updater.FrontAlpha = AlphaValue;
266 updater.Face = face;
267 updater.Url = "Local image";
268 updater.Disp = disp;
269
270 object objReusableTextureUUID = null;
271
272 if (ReuseTextures && !updater.BlendWithOldTexture)
171 { 273 {
172 DynamicTextureUpdater updater = new DynamicTextureUpdater(); 274 string reuseableTextureKey = GenerateReusableTextureKey(data, extraParams);
173 updater.SimUUID = simID; 275 objReusableTextureUUID = m_reuseableDynamicTextures.Get(reuseableTextureKey);
174 updater.PrimID = primID;
175 updater.ContentType = contentType;
176 updater.BodyData = data;
177 updater.UpdateTimer = updateTimer;
178 updater.UpdaterID = UUID.Random();
179 updater.Params = extraParams;
180 updater.BlendWithOldTexture = SetBlending;
181 updater.FrontAlpha = AlphaValue;
182 updater.Face = face;
183 updater.Url = "Local image";
184 updater.Disp = disp;
185 276
277 if (objReusableTextureUUID != null)
278 {
279 // If something else has removed this temporary asset from the cache, detect and invalidate
280 // our cached uuid.
281 if (scene.AssetService.GetMetadata(objReusableTextureUUID.ToString()) == null)
282 {
283 m_reuseableDynamicTextures.Invalidate(reuseableTextureKey);
284 objReusableTextureUUID = null;
285 }
286 }
287 }
288
289 // We cannot reuse a dynamic texture if the data is going to be blended with something already there.
290 if (objReusableTextureUUID == null)
291 {
186 lock (Updaters) 292 lock (Updaters)
187 { 293 {
188 if (!Updaters.ContainsKey(updater.UpdaterID)) 294 if (!Updaters.ContainsKey(updater.UpdaterID))
@@ -191,11 +297,29 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
191 } 297 }
192 } 298 }
193 299
300// m_log.DebugFormat(
301// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}",
302// part.Name, part.ParentGroup.Scene.Name);
303
194 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); 304 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
195 return updater.UpdaterID;
196 } 305 }
197 306 else
198 return UUID.Zero; 307 {
308// m_log.DebugFormat(
309// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}",
310// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name);
311
312 // No need to add to updaters as the texture is always the same. Not that this functionality
313 // apppears to be implemented anyway.
314 updater.UpdatePart(part, (UUID)objReusableTextureUUID);
315 }
316
317 return updater.UpdaterID;
318 }
319
320 private string GenerateReusableTextureKey(string data, string extraParams)
321 {
322 return string.Format("{0}{1}", data, extraParams);
199 } 323 }
200 324
201 public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, 325 public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
@@ -211,9 +335,29 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
211 335
212 #endregion 336 #endregion
213 337
214 #region IRegionModule Members 338 #region ISharedRegionModule Members
215 339
216 public void Initialise(Scene scene, IConfigSource config) 340 public void Initialise(IConfigSource config)
341 {
342 IConfig texturesConfig = config.Configs["Textures"];
343 if (texturesConfig != null)
344 {
345 ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
346 ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false);
347
348 if (ReuseTextures)
349 {
350 m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
351 m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
352 }
353 }
354 }
355
356 public void PostInitialise()
357 {
358 }
359
360 public void AddRegion(Scene scene)
217 { 361 {
218 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) 362 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
219 { 363 {
@@ -222,8 +366,14 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
222 } 366 }
223 } 367 }
224 368
225 public void PostInitialise() 369 public void RegionLoaded(Scene scene)
370 {
371 }
372
373 public void RemoveRegion(Scene scene)
226 { 374 {
375 if (RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
376 RegisteredScenes.Remove(scene.RegionInfo.RegionID);
227 } 377 }
228 378
229 public void Close() 379 public void Close()
@@ -235,9 +385,9 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
235 get { return "DynamicTextureModule"; } 385 get { return "DynamicTextureModule"; }
236 } 386 }
237 387
238 public bool IsSharedModule 388 public Type ReplaceableInterface
239 { 389 {
240 get { return true; } 390 get { return null; }
241 } 391 }
242 392
243 #endregion 393 #endregion
@@ -269,9 +419,60 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
269 } 419 }
270 420
271 /// <summary> 421 /// <summary>
422 /// Update the given part with the new texture.
423 /// </summary>
424 /// <returns>
425 /// The old texture UUID.
426 /// </returns>
427 public UUID UpdatePart(SceneObjectPart part, UUID textureID)
428 {
429 UUID oldID;
430
431 lock (part)
432 {
433 // mostly keep the values from before
434 Primitive.TextureEntry tmptex = part.Shape.Textures;
435
436 // FIXME: Need to return the appropriate ID if only a single face is replaced.
437 oldID = tmptex.DefaultTexture.TextureID;
438
439 if (Face == ALL_SIDES)
440 {
441 oldID = tmptex.DefaultTexture.TextureID;
442 tmptex.DefaultTexture.TextureID = textureID;
443 }
444 else
445 {
446 try
447 {
448 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
449 texface.TextureID = textureID;
450 tmptex.FaceTextures[Face] = texface;
451 }
452 catch (Exception)
453 {
454 tmptex.DefaultTexture.TextureID = textureID;
455 }
456 }
457
458 // I'm pretty sure we always want to force this to true
459 // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
460 // tmptex.DefaultTexture.Fullbright = true;
461
462 part.UpdateTextureEntry(tmptex.GetBytes());
463 }
464
465 return oldID;
466 }
467
468 /// <summary>
272 /// Called once new texture data has been received for this updater. 469 /// Called once new texture data has been received for this updater.
273 /// </summary> 470 /// </summary>
274 public void DataReceived(byte[] data, Scene scene) 471 /// <param name="data"></param>
472 /// <param name="scene"></param>
473 /// <param name="isReuseable">True if the data given is reuseable.</param>
474 /// <returns>The asset UUID given to the incoming data.</returns>
475 public UUID DataReceived(byte[] data, Scene scene)
275 { 476 {
276 SceneObjectPart part = scene.GetSceneObjectPart(PrimID); 477 SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
277 478
@@ -281,7 +482,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
281 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); 482 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
282 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, 483 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say,
283 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); 484 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false);
284 return; 485
486 return UUID.Zero;
285 } 487 }
286 488
287 byte[] assetData = null; 489 byte[] assetData = null;
@@ -319,56 +521,29 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
319 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>(); 521 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
320 if (cacheLayerDecode != null) 522 if (cacheLayerDecode != null)
321 { 523 {
322 cacheLayerDecode.Decode(asset.FullID, asset.Data); 524 if (!cacheLayerDecode.Decode(asset.FullID, asset.Data))
323 cacheLayerDecode = null; 525 m_log.WarnFormat(
526 "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed",
527 asset.ID, part.Name, part.ParentGroup.Scene.Name);
324 } 528 }
325 529
326 UUID oldID = UUID.Zero; 530 UUID oldID = UpdatePart(part, asset.FullID);
327
328 lock (part)
329 {
330 // mostly keep the values from before
331 Primitive.TextureEntry tmptex = part.Shape.Textures;
332
333 // remove the old asset from the cache
334 oldID = tmptex.DefaultTexture.TextureID;
335
336 if (Face == ALL_SIDES)
337 {
338 tmptex.DefaultTexture.TextureID = asset.FullID;
339 }
340 else
341 {
342 try
343 {
344 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
345 texface.TextureID = asset.FullID;
346 tmptex.FaceTextures[Face] = texface;
347 }
348 catch (Exception)
349 {
350 tmptex.DefaultTexture.TextureID = asset.FullID;
351 }
352 }
353
354 // I'm pretty sure we always want to force this to true
355 // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
356 // tmptex.DefaultTexture.Fullbright = true;
357
358 part.UpdateTextureEntry(tmptex.GetBytes());
359 }
360 531
361 if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) 532 if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
362 { 533 {
363 if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); 534 if (oldAsset == null)
535 oldAsset = scene.AssetService.Get(oldID.ToString());
536
364 if (oldAsset != null) 537 if (oldAsset != null)
365 { 538 {
366 if (oldAsset.Temporary == true) 539 if (oldAsset.Temporary)
367 { 540 {
368 scene.AssetService.Delete(oldID.ToString()); 541 scene.AssetService.Delete(oldID.ToString());
369 } 542 }
370 } 543 }
371 } 544 }
545
546 return asset.FullID;
372 } 547 }
373 548
374 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) 549 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
index e91e8b9..d943b20 100644
--- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs
@@ -37,10 +37,12 @@ using OpenMetaverse;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
40using Mono.Addins;
40 41
41namespace OpenSim.Region.CoreModules.Scripting.EmailModules 42namespace OpenSim.Region.CoreModules.Scripting.EmailModules
42{ 43{
43 public class EmailModule : IRegionModule, IEmailModule 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EmailModule")]
45 public class EmailModule : ISharedRegionModule, IEmailModule
44 { 46 {
45 // 47 //
46 // Log 48 // Log
@@ -72,31 +74,9 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
72 74
73 private bool m_Enabled = false; 75 private bool m_Enabled = false;
74 76
75 public void InsertEmail(UUID to, Email email) 77 #region ISharedRegionModule
76 {
77 // It's tempting to create the queue here. Don't; objects which have
78 // not yet called GetNextEmail should have no queue, and emails to them
79 // should be silently dropped.
80
81 lock (m_MailQueues)
82 {
83 if (m_MailQueues.ContainsKey(to))
84 {
85 if (m_MailQueues[to].Count >= m_MaxQueueSize)
86 {
87 // fail silently
88 return;
89 }
90
91 lock (m_MailQueues[to])
92 {
93 m_MailQueues[to].Add(email);
94 }
95 }
96 }
97 }
98 78
99 public void Initialise(Scene scene, IConfigSource config) 79 public void Initialise(IConfigSource config)
100 { 80 {
101 m_Config = config; 81 m_Config = config;
102 IConfig SMTPConfig; 82 IConfig SMTPConfig;
@@ -129,36 +109,44 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
129 SMTP_SERVER_PORT = SMTPConfig.GetInt("SMTP_SERVER_PORT", SMTP_SERVER_PORT); 109 SMTP_SERVER_PORT = SMTPConfig.GetInt("SMTP_SERVER_PORT", SMTP_SERVER_PORT);
130 SMTP_SERVER_LOGIN = SMTPConfig.GetString("SMTP_SERVER_LOGIN", SMTP_SERVER_LOGIN); 110 SMTP_SERVER_LOGIN = SMTPConfig.GetString("SMTP_SERVER_LOGIN", SMTP_SERVER_LOGIN);
131 SMTP_SERVER_PASSWORD = SMTPConfig.GetString("SMTP_SERVER_PASSWORD", SMTP_SERVER_PASSWORD); 111 SMTP_SERVER_PASSWORD = SMTPConfig.GetString("SMTP_SERVER_PASSWORD", SMTP_SERVER_PASSWORD);
132 m_MaxEmailSize = SMTPConfig.GetInt("email_max_size", m_MaxEmailSize); 112 m_MaxEmailSize = SMTPConfig.GetInt("email_max_size", m_MaxEmailSize);
133 } 113 }
134 catch (Exception e) 114 catch (Exception e)
135 { 115 {
136 m_log.Error("[EMAIL] DefaultEmailModule not configured: "+ e.Message); 116 m_log.Error("[EMAIL] DefaultEmailModule not configured: " + e.Message);
137 m_Enabled = false; 117 m_Enabled = false;
138 return; 118 return;
139 } 119 }
140 120
141 // It's a go! 121 }
142 if (m_Enabled) 122
123 public void AddRegion(Scene scene)
124 {
125 if (!m_Enabled)
126 return;
127
128 // It's a go!
129 lock (m_Scenes)
143 { 130 {
144 lock (m_Scenes) 131 // Claim the interface slot
145 { 132 scene.RegisterModuleInterface<IEmailModule>(this);
146 // Claim the interface slot
147 scene.RegisterModuleInterface<IEmailModule>(this);
148 133
149 // Add to scene list 134 // Add to scene list
150 if (m_Scenes.ContainsKey(scene.RegionInfo.RegionHandle)) 135 if (m_Scenes.ContainsKey(scene.RegionInfo.RegionHandle))
151 { 136 {
152 m_Scenes[scene.RegionInfo.RegionHandle] = scene; 137 m_Scenes[scene.RegionInfo.RegionHandle] = scene;
153 } 138 }
154 else 139 else
155 { 140 {
156 m_Scenes.Add(scene.RegionInfo.RegionHandle, scene); 141 m_Scenes.Add(scene.RegionInfo.RegionHandle, scene);
157 }
158 } 142 }
159
160 m_log.Info("[EMAIL] Activated DefaultEmailModule");
161 } 143 }
144
145 m_log.Info("[EMAIL] Activated DefaultEmailModule");
146 }
147
148 public void RemoveRegion(Scene scene)
149 {
162 } 150 }
163 151
164 public void PostInitialise() 152 public void PostInitialise()
@@ -174,9 +162,39 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
174 get { return "DefaultEmailModule"; } 162 get { return "DefaultEmailModule"; }
175 } 163 }
176 164
177 public bool IsSharedModule 165 public Type ReplaceableInterface
166 {
167 get { return null; }
168 }
169
170 public void RegionLoaded(Scene scene)
178 { 171 {
179 get { return true; } 172 }
173
174 #endregion
175
176 public void InsertEmail(UUID to, Email email)
177 {
178 // It's tempting to create the queue here. Don't; objects which have
179 // not yet called GetNextEmail should have no queue, and emails to them
180 // should be silently dropped.
181
182 lock (m_MailQueues)
183 {
184 if (m_MailQueues.ContainsKey(to))
185 {
186 if (m_MailQueues[to].Count >= m_MaxQueueSize)
187 {
188 // fail silently
189 return;
190 }
191
192 lock (m_MailQueues[to])
193 {
194 m_MailQueues[to].Add(email);
195 }
196 }
197 }
180 } 198 }
181 199
182 private bool IsLocal(UUID objectID) 200 private bool IsLocal(UUID objectID)
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 9dac6b9..a0ae203 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -41,6 +41,7 @@ using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer; 41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
44using Mono.Addins;
44 45
45/***************************************************** 46/*****************************************************
46 * 47 *
@@ -87,7 +88,8 @@ using OpenSim.Region.Framework.Scenes;
87 88
88namespace OpenSim.Region.CoreModules.Scripting.HttpRequest 89namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
89{ 90{
90 public class HttpRequestModule : IRegionModule, IHttpRequestModule 91 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HttpRequestModule")]
92 public class HttpRequestModule : ISharedRegionModule, IHttpRequestModule
91 { 93 {
92 private object HttpListLock = new object(); 94 private object HttpListLock = new object();
93 private int httpTimeout = 30000; 95 private int httpTimeout = 30000;
@@ -270,24 +272,38 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
270 272
271 #endregion 273 #endregion
272 274
273 #region IRegionModule Members 275 #region ISharedRegionModule Members
274 276
275 public void Initialise(Scene scene, IConfigSource config) 277 public void Initialise(IConfigSource config)
276 { 278 {
277 m_scene = scene;
278
279 m_scene.RegisterModuleInterface<IHttpRequestModule>(this);
280
281 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); 279 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
282 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); 280 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
283 281
284 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); 282 m_pendingRequests = new Dictionary<UUID, HttpRequestClass>();
285 } 283 }
286 284
285 public void AddRegion(Scene scene)
286 {
287 m_scene = scene;
288
289 m_scene.RegisterModuleInterface<IHttpRequestModule>(this);
290 }
291
292 public void RemoveRegion(Scene scene)
293 {
294 scene.UnregisterModuleInterface<IHttpRequestModule>(this);
295 if (scene == m_scene)
296 m_scene = null;
297 }
298
287 public void PostInitialise() 299 public void PostInitialise()
288 { 300 {
289 } 301 }
290 302
303 public void RegionLoaded(Scene scene)
304 {
305 }
306
291 public void Close() 307 public void Close()
292 { 308 {
293 } 309 }
@@ -297,9 +313,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
297 get { return m_name; } 313 get { return m_name; }
298 } 314 }
299 315
300 public bool IsSharedModule 316 public Type ReplaceableInterface
301 { 317 {
302 get { return true; } 318 get { return null; }
303 } 319 }
304 320
305 #endregion 321 #endregion
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 56221aa..da59eab 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Collections; 31using System.Collections;
32using System.Reflection; 32using System.Reflection;
33using log4net; 33using log4net;
34using Mono.Addins;
34using Nini.Config; 35using Nini.Config;
35using OpenMetaverse; 36using OpenMetaverse;
36using OpenSim.Framework; 37using OpenSim.Framework;
@@ -58,6 +59,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
58 public string body; 59 public string body;
59 public int responseCode; 60 public int responseCode;
60 public string responseBody; 61 public string responseBody;
62 public string responseType = "text/plain";
61 //public ManualResetEvent ev; 63 //public ManualResetEvent ev;
62 public bool requestDone; 64 public bool requestDone;
63 public int startTime; 65 public int startTime;
@@ -65,6 +67,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
65 public string uri; 67 public string uri;
66 } 68 }
67 69
70 /// <summary>
71 /// This module provides external URLs for in-world scripts.
72 /// </summary>
73 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UrlModule")]
68 public class UrlModule : ISharedRegionModule, IUrlModule 74 public class UrlModule : ISharedRegionModule, IUrlModule
69 { 75 {
70 private static readonly ILog m_log = 76 private static readonly ILog m_log =
@@ -270,6 +276,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
270 } 276 }
271 } 277 }
272 278
279 public void HttpContentType(UUID request, string type)
280 {
281 lock (m_UrlMap)
282 {
283 if (m_RequestMap.ContainsKey(request))
284 {
285 UrlData urlData = m_RequestMap[request];
286 urlData.requests[request].responseType = type;
287 }
288 else
289 {
290 m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
291 }
292 }
293 }
294
273 public void HttpResponse(UUID request, int status, string body) 295 public void HttpResponse(UUID request, int status, string body)
274 { 296 {
275 lock (m_RequestMap) 297 lock (m_RequestMap)
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 6f83948..65737fa 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -32,14 +32,17 @@ using System.Net;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Imaging; 34using OpenMetaverse.Imaging;
35using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
35using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using log4net; 38using log4net;
38using System.Reflection; 39using System.Reflection;
40using Mono.Addins;
39 41
40namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL 42namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
41{ 43{
42 public class LoadImageURLModule : IRegionModule, IDynamicTextureRender 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LoadImageURLModule")]
45 public class LoadImageURLModule : ISharedRegionModule, IDynamicTextureRender
43 { 46 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 48
@@ -67,12 +70,18 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
67 return true; 70 return true;
68 } 71 }
69 72
70 public byte[] ConvertUrl(string url, string extraParams) 73// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
74// {
75// // We don't support conversion of body data.
76// return false;
77// }
78
79 public IDynamicTexture ConvertUrl(string url, string extraParams)
71 { 80 {
72 return null; 81 return null;
73 } 82 }
74 83
75 public byte[] ConvertStream(Stream data, string extraParams) 84 public IDynamicTexture ConvertData(string bodyData, string extraParams)
76 { 85 {
77 return null; 86 return null;
78 } 87 }
@@ -97,22 +106,32 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
97 106
98 #endregion 107 #endregion
99 108
100 #region IRegionModule Members 109 #region ISharedRegionModule Members
101 110
102 public void Initialise(Scene scene, IConfigSource config) 111 public void Initialise(IConfigSource config)
103 { 112 {
104 if (m_scene == null)
105 {
106 m_scene = scene;
107 }
108
109 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); 113 m_proxyurl = config.Configs["Startup"].GetString("HttpProxy");
110 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); 114 m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions");
111 } 115 }
112 116
113 public void PostInitialise() 117 public void PostInitialise()
114 { 118 {
115 if (m_scene != null) 119 }
120
121 public void AddRegion(Scene scene)
122 {
123 if (m_scene == null)
124 m_scene = scene;
125
126 }
127
128 public void RemoveRegion(Scene scene)
129 {
130 }
131
132 public void RegionLoaded(Scene scene)
133 {
134 if (m_textureManager == null && m_scene == scene)
116 { 135 {
117 m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>(); 136 m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
118 if (m_textureManager != null) 137 if (m_textureManager != null)
@@ -131,9 +150,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
131 get { return m_name; } 150 get { return m_name; }
132 } 151 }
133 152
134 public bool IsSharedModule 153 public Type ReplaceableInterface
135 { 154 {
136 get { return true; } 155 get { return null; }
137 } 156 }
138 157
139 #endregion 158 #endregion
@@ -165,11 +184,17 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
165 184
166 private void HttpRequestReturn(IAsyncResult result) 185 private void HttpRequestReturn(IAsyncResult result)
167 { 186 {
187 if (m_textureManager == null)
188 {
189 m_log.WarnFormat("[LOADIMAGEURLMODULE]: No texture manager. Can't function.");
190 return;
191 }
168 192
169 RequestState state = (RequestState) result.AsyncState; 193 RequestState state = (RequestState) result.AsyncState;
170 WebRequest request = (WebRequest) state.Request; 194 WebRequest request = (WebRequest) state.Request;
171 Stream stream = null; 195 Stream stream = null;
172 byte[] imageJ2000 = new byte[0]; 196 byte[] imageJ2000 = new byte[0];
197 Size newSize = new Size(0, 0);
173 198
174 try 199 try
175 { 200 {
@@ -182,37 +207,43 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
182 try 207 try
183 { 208 {
184 Bitmap image = new Bitmap(stream); 209 Bitmap image = new Bitmap(stream);
185 Size newsize;
186 210
187 // TODO: make this a bit less hard coded 211 // TODO: make this a bit less hard coded
188 if ((image.Height < 64) && (image.Width < 64)) 212 if ((image.Height < 64) && (image.Width < 64))
189 { 213 {
190 newsize = new Size(32, 32); 214 newSize.Width = 32;
215 newSize.Height = 32;
191 } 216 }
192 else if ((image.Height < 128) && (image.Width < 128)) 217 else if ((image.Height < 128) && (image.Width < 128))
193 { 218 {
194 newsize = new Size(64, 64); 219 newSize.Width = 64;
220 newSize.Height = 64;
195 } 221 }
196 else if ((image.Height < 256) && (image.Width < 256)) 222 else if ((image.Height < 256) && (image.Width < 256))
197 { 223 {
198 newsize = new Size(128, 128); 224 newSize.Width = 128;
225 newSize.Height = 128;
199 } 226 }
200 else if ((image.Height < 512 && image.Width < 512)) 227 else if ((image.Height < 512 && image.Width < 512))
201 { 228 {
202 newsize = new Size(256, 256); 229 newSize.Width = 256;
230 newSize.Height = 256;
203 } 231 }
204 else if ((image.Height < 1024 && image.Width < 1024)) 232 else if ((image.Height < 1024 && image.Width < 1024))
205 { 233 {
206 newsize = new Size(512, 512); 234 newSize.Width = 512;
235 newSize.Height = 512;
207 } 236 }
208 else 237 else
209 { 238 {
210 newsize = new Size(1024, 1024); 239 newSize.Width = 1024;
240 newSize.Height = 1024;
211 } 241 }
212 242
213 Bitmap resize = new Bitmap(image, newsize); 243 using (Bitmap resize = new Bitmap(image, newSize))
214 244 {
215 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); 245 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
246 }
216 } 247 }
217 catch (Exception) 248 catch (Exception)
218 { 249 {
@@ -227,7 +258,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
227 } 258 }
228 catch (WebException) 259 catch (WebException)
229 { 260 {
230
231 } 261 }
232 finally 262 finally
233 { 263 {
@@ -236,9 +266,14 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
236 stream.Close(); 266 stream.Close();
237 } 267 }
238 } 268 }
239 m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", 269
270 m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
240 imageJ2000.Length, state.RequestID); 271 imageJ2000.Length, state.RequestID);
241 m_textureManager.ReturnData(state.RequestID, imageJ2000); 272
273 m_textureManager.ReturnData(
274 state.RequestID,
275 new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
276 request.RequestUri, null, imageJ2000, newSize, false));
242 } 277 }
243 278
244 #region Nested type: RequestState 279 #region Nested type: RequestState
diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index 705a847..f6e1d39 100644
--- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -38,7 +38,7 @@ using OpenMetaverse;
38using System.Linq; 38using System.Linq;
39using System.Linq.Expressions; 39using System.Linq.Expressions;
40 40
41namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms 41namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
42{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")] 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ScriptModuleCommsModule")]
44 class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms 44 class ScriptModuleCommsModule : INonSharedRegionModule, IScriptModuleComms
@@ -130,13 +130,25 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
130 m_scriptModule.PostScriptEvent(script, "link_message", args); 130 m_scriptModule.PostScriptEvent(script, "link_message", args);
131 } 131 }
132 132
133 private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods)
134 {
135 BindingFlags getMethodFlags =
136 BindingFlags.NonPublic | BindingFlags.Public;
137
138 if (searchInstanceMethods)
139 getMethodFlags |= BindingFlags.Instance;
140 else
141 getMethodFlags |= BindingFlags.Static;
142
143 return target.GetMethod(meth, getMethodFlags);
144 }
145
133 public void RegisterScriptInvocation(object target, string meth) 146 public void RegisterScriptInvocation(object target, string meth)
134 { 147 {
135 MethodInfo mi = target.GetType().GetMethod(meth, 148 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
136 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
137 if (mi == null) 149 if (mi == null)
138 { 150 {
139 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth); 151 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth);
140 return; 152 return;
141 } 153 }
142 154
@@ -151,38 +163,71 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
151 163
152 public void RegisterScriptInvocation(object target, MethodInfo mi) 164 public void RegisterScriptInvocation(object target, MethodInfo mi)
153 { 165 {
154 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, target.GetType().Name); 166 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
155 167
156 Type delegateType; 168 Type delegateType;
157 var typeArgs = mi.GetParameters() 169 List<Type> typeArgs = mi.GetParameters()
158 .Select(p => p.ParameterType) 170 .Select(p => p.ParameterType)
159 .ToList(); 171 .ToList();
160 172
161 if (mi.ReturnType == typeof(void)) 173 if (mi.ReturnType == typeof(void))
162 { 174 {
163 delegateType = Expression.GetActionType(typeArgs.ToArray()); 175 delegateType = Expression.GetActionType(typeArgs.ToArray());
164 } 176 }
165 else 177 else
166 { 178 {
167 typeArgs.Add(mi.ReturnType); 179 typeArgs.Add(mi.ReturnType);
168 delegateType = Expression.GetFuncType(typeArgs.ToArray()); 180 delegateType = Expression.GetFuncType(typeArgs.ToArray());
169 } 181 }
170 182
171 Delegate fcall = Delegate.CreateDelegate(delegateType, target, mi); 183 Delegate fcall;
184 if (!(target is Type))
185 fcall = Delegate.CreateDelegate(delegateType, target, mi);
186 else
187 fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name);
172 188
173 lock (m_scriptInvocation) 189 lock (m_scriptInvocation)
174 { 190 {
175 ParameterInfo[] parameters = fcall.Method.GetParameters (); 191 ParameterInfo[] parameters = fcall.Method.GetParameters();
176 if (parameters.Length < 2) // Must have two UUID params 192 if (parameters.Length < 2) // Must have two UUID params
177 return; 193 return;
178 194
179 // Hide the first two parameters 195 // Hide the first two parameters
180 Type[] parmTypes = new Type[parameters.Length - 2]; 196 Type[] parmTypes = new Type[parameters.Length - 2];
181 for (int i = 2 ; i < parameters.Length ; i++) 197 for (int i = 2; i < parameters.Length; i++)
182 parmTypes[i - 2] = parameters[i].ParameterType; 198 parmTypes[i - 2] = parameters[i].ParameterType;
183 m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); 199 m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType);
184 } 200 }
185 } 201 }
202
203 public void RegisterScriptInvocation(Type target, string[] methods)
204 {
205 foreach (string method in methods)
206 {
207 MethodInfo mi = GetMethodInfoFromType(target, method, false);
208 if (mi == null)
209 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method);
210 else
211 RegisterScriptInvocation(target, mi);
212 }
213 }
214
215 public void RegisterScriptInvocations(IRegionModuleBase target)
216 {
217 foreach(MethodInfo method in target.GetType().GetMethods(
218 BindingFlags.Public | BindingFlags.Instance |
219 BindingFlags.Static))
220 {
221 if(method.GetCustomAttributes(
222 typeof(ScriptInvocationAttribute), true).Any())
223 {
224 if(method.IsStatic)
225 RegisterScriptInvocation(target.GetType(), method);
226 else
227 RegisterScriptInvocation(target, method);
228 }
229 }
230 }
186 231
187 public Delegate[] GetScriptInvocationList() 232 public Delegate[] GetScriptInvocationList()
188 { 233 {
@@ -285,6 +330,20 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
285 } 330 }
286 } 331 }
287 332
333 public void RegisterConstants(IRegionModuleBase target)
334 {
335 foreach (FieldInfo field in target.GetType().GetFields(
336 BindingFlags.Public | BindingFlags.Static |
337 BindingFlags.Instance))
338 {
339 if (field.GetCustomAttributes(
340 typeof(ScriptConstantAttribute), true).Any())
341 {
342 RegisterConstant(field.Name, field.GetValue(target));
343 }
344 }
345 }
346
288 /// <summary> 347 /// <summary>
289 /// Operation to check for a registered constant 348 /// Operation to check for a registered constant
290 /// </summary> 349 /// </summary>
@@ -302,6 +361,22 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
302 return null; 361 return null;
303 } 362 }
304 363
364 /// <summary>
365 /// Get all registered constants
366 /// </summary>
367 public Dictionary<string, object> GetConstants()
368 {
369 Dictionary<string, object> ret = new Dictionary<string, object>();
370
371 lock (m_constants)
372 {
373 foreach (KeyValuePair<string, object> kvp in m_constants)
374 ret[kvp.Key] = kvp.Value;
375 }
376
377 return ret;
378 }
379
305#endregion 380#endregion
306 381
307 } 382 }
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index 9787c8c..41baccc 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -45,31 +45,292 @@ using OpenSim.Tests.Common.Mock;
45namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests 45namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
46{ 46{
47 [TestFixture] 47 [TestFixture]
48 public class VectorRenderModuleTests 48 public class VectorRenderModuleTests : OpenSimTestCase
49 { 49 {
50 Scene m_scene;
51 DynamicTextureModule m_dtm;
52 VectorRenderModule m_vrm;
53
54 private void SetupScene(bool reuseTextures)
55 {
56 m_scene = new SceneHelpers().SetupScene();
57
58 m_dtm = new DynamicTextureModule();
59 m_dtm.ReuseTextures = reuseTextures;
60// m_dtm.ReuseLowDataTextures = reuseTextures;
61
62 m_vrm = new VectorRenderModule();
63
64 SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm);
65 }
66
50 [Test] 67 [Test]
51 public void TestDraw() 68 public void TestDraw()
52 { 69 {
53 TestHelpers.InMethod(); 70 TestHelpers.InMethod();
54 71
55 Scene scene = new SceneHelpers().SetupScene(); 72 SetupScene(false);
56 DynamicTextureModule dtm = new DynamicTextureModule(); 73 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
57 VectorRenderModule vrm = new VectorRenderModule();
58 SceneHelpers.SetupSceneModules(scene, dtm, vrm);
59
60 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
61 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 74 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
62 75
63 dtm.AddDynamicTextureData( 76 m_dtm.AddDynamicTextureData(
64 scene.RegionInfo.RegionID, 77 m_scene.RegionInfo.RegionID,
65 so.UUID, 78 so.UUID,
66 vrm.GetContentType(), 79 m_vrm.GetContentType(),
67 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", 80 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
68 "", 81 "",
69 0); 82 0);
70 83
84 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
85 }
86
87 [Test]
88 public void TestRepeatSameDraw()
89 {
90 TestHelpers.InMethod();
91
92 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
93
94 SetupScene(false);
95 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
96
97 m_dtm.AddDynamicTextureData(
98 m_scene.RegionInfo.RegionID,
99 so.UUID,
100 m_vrm.GetContentType(),
101 dtText,
102 "",
103 0);
104
105 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
106
107 m_dtm.AddDynamicTextureData(
108 m_scene.RegionInfo.RegionID,
109 so.UUID,
110 m_vrm.GetContentType(),
111 dtText,
112 "",
113 0);
114
115 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
116 }
117
118 [Test]
119 public void TestRepeatSameDrawDifferentExtraParams()
120 {
121 TestHelpers.InMethod();
122
123 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
124
125 SetupScene(false);
126 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
127
128 m_dtm.AddDynamicTextureData(
129 m_scene.RegionInfo.RegionID,
130 so.UUID,
131 m_vrm.GetContentType(),
132 dtText,
133 "",
134 0);
135
136 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
137
138 m_dtm.AddDynamicTextureData(
139 m_scene.RegionInfo.RegionID,
140 so.UUID,
141 m_vrm.GetContentType(),
142 dtText,
143 "alpha:250",
144 0);
145
146 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
147 }
148
149 [Test]
150 public void TestRepeatSameDrawContainingImage()
151 {
152 TestHelpers.InMethod();
153
154 string dtText
155 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
156
157 SetupScene(false);
158 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
159
160 m_dtm.AddDynamicTextureData(
161 m_scene.RegionInfo.RegionID,
162 so.UUID,
163 m_vrm.GetContentType(),
164 dtText,
165 "",
166 0);
167
168 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
169
170 m_dtm.AddDynamicTextureData(
171 m_scene.RegionInfo.RegionID,
172 so.UUID,
173 m_vrm.GetContentType(),
174 dtText,
175 "",
176 0);
177
178 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
179 }
180
181 [Test]
182 public void TestDrawReusingTexture()
183 {
184 TestHelpers.InMethod();
185
186 SetupScene(true);
187 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
188 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
189
190 m_dtm.AddDynamicTextureData(
191 m_scene.RegionInfo.RegionID,
192 so.UUID,
193 m_vrm.GetContentType(),
194 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
195 "",
196 0);
71 197
72 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 198 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
73 } 199 }
200
201 [Test]
202 public void TestRepeatSameDrawReusingTexture()
203 {
204 TestHelpers.InMethod();
205// TestHelpers.EnableLogging();
206
207 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
208
209 SetupScene(true);
210 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
211
212 m_dtm.AddDynamicTextureData(
213 m_scene.RegionInfo.RegionID,
214 so.UUID,
215 m_vrm.GetContentType(),
216 dtText,
217 "",
218 0);
219
220 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
221
222 m_dtm.AddDynamicTextureData(
223 m_scene.RegionInfo.RegionID,
224 so.UUID,
225 m_vrm.GetContentType(),
226 dtText,
227 "",
228 0);
229
230 Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
231 }
232
233 /// <summary>
234 /// Test a low data dynamically generated texture such that it is treated as a low data texture that causes
235 /// problems for current viewers.
236 /// </summary>
237 /// <remarks>
238 /// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the
239 /// texture
240 /// </remarks>
241 [Test]
242 public void TestRepeatSameDrawLowDataTexture()
243 {
244 TestHelpers.InMethod();
245// TestHelpers.EnableLogging();
246
247 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
248
249 SetupScene(true);
250 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
251
252 m_dtm.AddDynamicTextureData(
253 m_scene.RegionInfo.RegionID,
254 so.UUID,
255 m_vrm.GetContentType(),
256 dtText,
257 "1024",
258 0);
259
260 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
261
262 m_dtm.AddDynamicTextureData(
263 m_scene.RegionInfo.RegionID,
264 so.UUID,
265 m_vrm.GetContentType(),
266 dtText,
267 "1024",
268 0);
269
270 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
271 }
272
273 [Test]
274 public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
275 {
276 TestHelpers.InMethod();
277
278 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
279
280 SetupScene(true);
281 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
282
283 m_dtm.AddDynamicTextureData(
284 m_scene.RegionInfo.RegionID,
285 so.UUID,
286 m_vrm.GetContentType(),
287 dtText,
288 "",
289 0);
290
291 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
292
293 m_dtm.AddDynamicTextureData(
294 m_scene.RegionInfo.RegionID,
295 so.UUID,
296 m_vrm.GetContentType(),
297 dtText,
298 "alpha:250",
299 0);
300
301 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
302 }
303
304 [Test]
305 public void TestRepeatSameDrawContainingImageReusingTexture()
306 {
307 TestHelpers.InMethod();
308
309 string dtText
310 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
311
312 SetupScene(true);
313 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
314
315 m_dtm.AddDynamicTextureData(
316 m_scene.RegionInfo.RegionID,
317 so.UUID,
318 m_vrm.GetContentType(),
319 dtText,
320 "",
321 0);
322
323 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
324
325 m_dtm.AddDynamicTextureData(
326 m_scene.RegionInfo.RegionID,
327 so.UUID,
328 m_vrm.GetContentType(),
329 dtText,
330 "",
331 0);
332
333 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
334 }
74 } 335 }
75} \ No newline at end of file 336} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index 8b2f2f8..f395441 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -30,26 +30,35 @@ using System.Drawing;
30using System.Drawing.Imaging; 30using System.Drawing.Imaging;
31using System.Globalization; 31using System.Globalization;
32using System.IO; 32using System.IO;
33using System.Linq;
33using System.Net; 34using System.Net;
34using Nini.Config; 35using Nini.Config;
35using OpenMetaverse; 36using OpenMetaverse;
36using OpenMetaverse.Imaging; 37using OpenMetaverse.Imaging;
38using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
37using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
39using log4net; 41using log4net;
40using System.Reflection; 42using System.Reflection;
43using Mono.Addins;
41 44
42//using Cairo; 45//using Cairo;
43 46
44namespace OpenSim.Region.CoreModules.Scripting.VectorRender 47namespace OpenSim.Region.CoreModules.Scripting.VectorRender
45{ 48{
46 public class VectorRenderModule : IRegionModule, IDynamicTextureRender 49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "VectorRenderModule")]
50 public class VectorRenderModule : ISharedRegionModule, IDynamicTextureRender
47 { 51 {
52 // These fields exist for testing purposes, please do not remove.
53// private static bool s_flipper;
54// private static byte[] s_asset1Data;
55// private static byte[] s_asset2Data;
56
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 57 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 58
50 private string m_name = "VectorRenderModule";
51 private Scene m_scene; 59 private Scene m_scene;
52 private IDynamicTextureManager m_textureManager; 60 private IDynamicTextureManager m_textureManager;
61
53 private Graphics m_graph; 62 private Graphics m_graph;
54 private string m_fontName = "Arial"; 63 private string m_fontName = "Arial";
55 64
@@ -61,12 +70,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
61 70
62 public string GetContentType() 71 public string GetContentType()
63 { 72 {
64 return ("vector"); 73 return "vector";
65 } 74 }
66 75
67 public string GetName() 76 public string GetName()
68 { 77 {
69 return m_name; 78 return Name;
70 } 79 }
71 80
72 public bool SupportsAsynchronous() 81 public bool SupportsAsynchronous()
@@ -74,14 +83,20 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
74 return true; 83 return true;
75 } 84 }
76 85
77 public byte[] ConvertUrl(string url, string extraParams) 86// public bool AlwaysIdenticalConversion(string bodyData, string extraParams)
87// {
88// string[] lines = GetLines(bodyData);
89// return lines.Any((str, r) => str.StartsWith("Image"));
90// }
91
92 public IDynamicTexture ConvertUrl(string url, string extraParams)
78 { 93 {
79 return null; 94 return null;
80 } 95 }
81 96
82 public byte[] ConvertStream(Stream data, string extraParams) 97 public IDynamicTexture ConvertData(string bodyData, string extraParams)
83 { 98 {
84 return null; 99 return Draw(bodyData, extraParams);
85 } 100 }
86 101
87 public bool AsyncConvertUrl(UUID id, string url, string extraParams) 102 public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@@ -91,78 +106,101 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
91 106
92 public bool AsyncConvertData(UUID id, string bodyData, string extraParams) 107 public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
93 { 108 {
94 Draw(bodyData, id, extraParams); 109 if (m_textureManager == null)
110 {
111 m_log.Warn("[VECTORRENDERMODULE]: No texture manager. Can't function");
112 return false;
113 }
114 // XXX: This isn't actually being done asynchronously!
115 m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
116
95 return true; 117 return true;
96 } 118 }
97 119
98 public void GetDrawStringSize(string text, string fontName, int fontSize, 120 public void GetDrawStringSize(string text, string fontName, int fontSize,
99 out double xSize, out double ySize) 121 out double xSize, out double ySize)
100 { 122 {
101 using (Font myFont = new Font(fontName, fontSize)) 123 lock (this)
102 { 124 {
103 SizeF stringSize = new SizeF(); 125 using (Font myFont = new Font(fontName, fontSize))
104 lock (m_graph)
105 { 126 {
106 stringSize = m_graph.MeasureString(text, myFont); 127 SizeF stringSize = new SizeF();
107 xSize = stringSize.Width; 128
108 ySize = stringSize.Height; 129 // XXX: This lock may be unnecessary.
130 lock (m_graph)
131 {
132 stringSize = m_graph.MeasureString(text, myFont);
133 xSize = stringSize.Width;
134 ySize = stringSize.Height;
135 }
109 } 136 }
110 } 137 }
111 } 138 }
112 139
113 #endregion 140 #endregion
114 141
115 #region IRegionModule Members 142 #region ISharedRegionModule Members
116 143
117 public void Initialise(Scene scene, IConfigSource config) 144 public void Initialise(IConfigSource config)
118 { 145 {
119 if (m_scene == null)
120 {
121 m_scene = scene;
122 }
123
124 if (m_graph == null)
125 {
126 // We won't dispose of these explicitly since this module is only removed when the entire simulator
127 // is shut down.
128 Bitmap bitmap = new Bitmap(1024, 1024, PixelFormat.Format32bppArgb);
129 m_graph = Graphics.FromImage(bitmap);
130 }
131
132 IConfig cfg = config.Configs["VectorRender"]; 146 IConfig cfg = config.Configs["VectorRender"];
133 if (null != cfg) 147 if (null != cfg)
134 { 148 {
135 m_fontName = cfg.GetString("font_name", m_fontName); 149 m_fontName = cfg.GetString("font_name", m_fontName);
136 } 150 }
137 m_log.DebugFormat("[VECTORRENDERMODULE]: using font \"{0}\" for text rendering.", m_fontName); 151 m_log.DebugFormat("[VECTORRENDERMODULE]: using font \"{0}\" for text rendering.", m_fontName);
152
153 // We won't dispose of these explicitly since this module is only removed when the entire simulator
154 // is shut down.
155 Bitmap bitmap = new Bitmap(1024, 1024, PixelFormat.Format32bppArgb);
156 m_graph = Graphics.FromImage(bitmap);
138 } 157 }
139 158
140 public void PostInitialise() 159 public void PostInitialise()
141 { 160 {
142 m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>(); 161 }
143 if (m_textureManager != null) 162
163 public void AddRegion(Scene scene)
164 {
165 if (m_scene == null)
144 { 166 {
145 m_textureManager.RegisterRender(GetContentType(), this); 167 m_scene = scene;
146 } 168 }
147 } 169 }
148 170
171 public void RegionLoaded(Scene scene)
172 {
173 if (m_textureManager == null && m_scene == scene)
174 {
175 m_textureManager = m_scene.RequestModuleInterface<IDynamicTextureManager>();
176 if (m_textureManager != null)
177 {
178 m_textureManager.RegisterRender(GetContentType(), this);
179 }
180 }
181 }
182
183 public void RemoveRegion(Scene scene)
184 {
185 }
186
149 public void Close() 187 public void Close()
150 { 188 {
151 } 189 }
152 190
153 public string Name 191 public string Name
154 { 192 {
155 get { return m_name; } 193 get { return "VectorRenderModule"; }
156 } 194 }
157 195
158 public bool IsSharedModule 196 public Type ReplaceableInterface
159 { 197 {
160 get { return true; } 198 get { return null; }
161 } 199 }
162 200
163 #endregion 201 #endregion
164 202
165 private void Draw(string data, UUID id, string extraParams) 203 private IDynamicTexture Draw(string data, string extraParams)
166 { 204 {
167 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha 205 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
168 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 206 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
@@ -305,40 +343,57 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
305 343
306 Bitmap bitmap = null; 344 Bitmap bitmap = null;
307 Graphics graph = null; 345 Graphics graph = null;
346 bool reuseable = false;
308 347
309 try 348 try
310 { 349 {
311 if (alpha == 256) 350 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
312 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); 351 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
313 else 352 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
314 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); 353 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
315 354 // under lock.
316 graph = Graphics.FromImage(bitmap); 355 lock (this)
317
318 // this is really just to save people filling the
319 // background color in their scripts, only do when fully opaque
320 if (alpha >= 255)
321 { 356 {
322 using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) 357 if (alpha == 256)
358 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
359 else
360 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
361
362 graph = Graphics.FromImage(bitmap);
363
364 // this is really just to save people filling the
365 // background color in their scripts, only do when fully opaque
366 if (alpha >= 255)
323 { 367 {
324 graph.FillRectangle(bgFillBrush, 0, 0, width, height); 368 using (SolidBrush bgFillBrush = new SolidBrush(bgColor))
369 {
370 graph.FillRectangle(bgFillBrush, 0, 0, width, height);
371 }
325 } 372 }
326 } 373
327 374 for (int w = 0; w < bitmap.Width; w++)
328 for (int w = 0; w < bitmap.Width; w++)
329 {
330 if (alpha <= 255)
331 { 375 {
332 for (int h = 0; h < bitmap.Height; h++) 376 if (alpha <= 255)
333 { 377 {
334 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); 378 for (int h = 0; h < bitmap.Height; h++)
379 {
380 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
381 }
335 } 382 }
336 } 383 }
384
385 GDIDraw(data, graph, altDataDelim, out reuseable);
337 } 386 }
338 387
339 GDIDraw(data, graph, altDataDelim);
340
341 byte[] imageJ2000 = new byte[0]; 388 byte[] imageJ2000 = new byte[0];
389
390 // This code exists for testing purposes, please do not remove.
391// if (s_flipper)
392// imageJ2000 = s_asset1Data;
393// else
394// imageJ2000 = s_asset2Data;
395//
396// s_flipper = !s_flipper;
342 397
343 try 398 try
344 { 399 {
@@ -351,15 +406,24 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
351 e.Message, e.StackTrace); 406 e.Message, e.StackTrace);
352 } 407 }
353 408
354 m_textureManager.ReturnData(id, imageJ2000); 409 return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
410 data, extraParams, imageJ2000, new Size(width, height), reuseable);
355 } 411 }
356 finally 412 finally
357 { 413 {
358 if (graph != null) 414 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
359 graph.Dispose(); 415 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
360 416 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
361 if (bitmap != null) 417 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
362 bitmap.Dispose(); 418 // under lock.
419 lock (this)
420 {
421 if (graph != null)
422 graph.Dispose();
423
424 if (bitmap != null)
425 bitmap.Dispose();
426 }
363 } 427 }
364 } 428 }
365 429
@@ -418,8 +482,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
418 } 482 }
419*/ 483*/
420 484
421 private void GDIDraw(string data, Graphics graph, char dataDelim) 485 /// <summary>
486 /// Split input data into discrete command lines.
487 /// </summary>
488 /// <returns></returns>
489 /// <param name='data'></param>
490 /// <param name='dataDelim'></param>
491 private string[] GetLines(string data, char dataDelim)
492 {
493 char[] lineDelimiter = { dataDelim };
494 return data.Split(lineDelimiter);
495 }
496
497 private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable)
422 { 498 {
499 reuseable = true;
423 Point startPoint = new Point(0, 0); 500 Point startPoint = new Point(0, 0);
424 Point endPoint = new Point(0, 0); 501 Point endPoint = new Point(0, 0);
425 Pen drawPen = null; 502 Pen drawPen = null;
@@ -434,11 +511,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
434 myFont = new Font(fontName, fontSize); 511 myFont = new Font(fontName, fontSize);
435 myBrush = new SolidBrush(Color.Black); 512 myBrush = new SolidBrush(Color.Black);
436 513
437 char[] lineDelimiter = {dataDelim};
438 char[] partsDelimiter = {','}; 514 char[] partsDelimiter = {','};
439 string[] lines = data.Split(lineDelimiter);
440 515
441 foreach (string line in lines) 516 foreach (string line in GetLines(data, dataDelim))
442 { 517 {
443 string nextLine = line.Trim(); 518 string nextLine = line.Trim();
444 //replace with switch, or even better, do some proper parsing 519 //replace with switch, or even better, do some proper parsing
@@ -469,6 +544,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
469 } 544 }
470 else if (nextLine.StartsWith("Image")) 545 else if (nextLine.StartsWith("Image"))
471 { 546 {
547 // We cannot reuse any generated texture involving fetching an image via HTTP since that image
548 // can change.
549 reuseable = false;
550
472 float x = 0; 551 float x = 0;
473 float y = 0; 552 float y = 0;
474 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); 553 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
index 07bb291..87a0537 100644
--- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
@@ -28,8 +28,13 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Text.RegularExpressions;
32
31using Nini.Config; 33using Nini.Config;
34using Mono.Addins;
35
32using OpenMetaverse; 36using OpenMetaverse;
37
33using OpenSim.Framework; 38using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
@@ -85,7 +90,8 @@ using OpenSim.Region.Framework.Scenes;
85 90
86namespace OpenSim.Region.CoreModules.Scripting.WorldComm 91namespace OpenSim.Region.CoreModules.Scripting.WorldComm
87{ 92{
88 public class WorldCommModule : IRegionModule, IWorldComm 93 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WorldCommModule")]
94 public class WorldCommModule : IWorldComm, INonSharedRegionModule
89 { 95 {
90 // private static readonly ILog m_log = 96 // private static readonly ILog m_log =
91 // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 97 // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -100,9 +106,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
100 private int m_saydistance = 20; 106 private int m_saydistance = 20;
101 private int m_shoutdistance = 100; 107 private int m_shoutdistance = 100;
102 108
103 #region IRegionModule Members 109 #region INonSharedRegionModule Members
104 110
105 public void Initialise(Scene scene, IConfigSource config) 111 public void Initialise(IConfigSource config)
106 { 112 {
107 // wrap this in a try block so that defaults will work if 113 // wrap this in a try block so that defaults will work if
108 // the config file doesn't specify otherwise. 114 // the config file doesn't specify otherwise.
@@ -110,29 +116,49 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
110 int maxhandles = 64; 116 int maxhandles = 64;
111 try 117 try
112 { 118 {
113 m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); 119 m_whisperdistance = config.Configs["Chat"].GetInt(
114 m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); 120 "whisper_distance", m_whisperdistance);
115 m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); 121 m_saydistance = config.Configs["Chat"].GetInt(
116 maxlisteners = config.Configs["LL-Functions"].GetInt("max_listens_per_region", maxlisteners); 122 "say_distance", m_saydistance);
117 maxhandles = config.Configs["LL-Functions"].GetInt("max_listens_per_script", maxhandles); 123 m_shoutdistance = config.Configs["Chat"].GetInt(
124 "shout_distance", m_shoutdistance);
125 maxlisteners = config.Configs["LL-Functions"].GetInt(
126 "max_listens_per_region", maxlisteners);
127 maxhandles = config.Configs["LL-Functions"].GetInt(
128 "max_listens_per_script", maxhandles);
118 } 129 }
119 catch (Exception) 130 catch (Exception)
120 { 131 {
121 } 132 }
122 if (maxlisteners < 1) maxlisteners = int.MaxValue; 133 if (maxlisteners < 1) maxlisteners = int.MaxValue;
123 if (maxhandles < 1) maxhandles = int.MaxValue; 134 if (maxhandles < 1) maxhandles = int.MaxValue;
135 m_listenerManager = new ListenerManager(maxlisteners, maxhandles);
136 m_pendingQ = new Queue();
137 m_pending = Queue.Synchronized(m_pendingQ);
138 }
124 139
140 public void PostInitialise()
141 {
142 }
143
144 public void AddRegion(Scene scene)
145 {
125 m_scene = scene; 146 m_scene = scene;
126 m_scene.RegisterModuleInterface<IWorldComm>(this); 147 m_scene.RegisterModuleInterface<IWorldComm>(this);
127 m_listenerManager = new ListenerManager(maxlisteners, maxhandles);
128 m_scene.EventManager.OnChatFromClient += DeliverClientMessage; 148 m_scene.EventManager.OnChatFromClient += DeliverClientMessage;
129 m_scene.EventManager.OnChatBroadcast += DeliverClientMessage; 149 m_scene.EventManager.OnChatBroadcast += DeliverClientMessage;
130 m_pendingQ = new Queue();
131 m_pending = Queue.Synchronized(m_pendingQ);
132 } 150 }
133 151
134 public void PostInitialise() 152 public void RegionLoaded(Scene scene) { }
153
154 public void RemoveRegion(Scene scene)
135 { 155 {
156 if (scene != m_scene)
157 return;
158
159 m_scene.UnregisterModuleInterface<IWorldComm>(this);
160 m_scene.EventManager.OnChatBroadcast -= DeliverClientMessage;
161 m_scene.EventManager.OnChatBroadcast -= DeliverClientMessage;
136 } 162 }
137 163
138 public void Close() 164 public void Close()
@@ -144,10 +170,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
144 get { return "WorldCommModule"; } 170 get { return "WorldCommModule"; }
145 } 171 }
146 172
147 public bool IsSharedModule 173 public Type ReplaceableInterface { get { return null; } }
148 {
149 get { return false; }
150 }
151 174
152 #endregion 175 #endregion
153 176
@@ -172,12 +195,42 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
172 /// <param name="hostID">UUID of the SceneObjectPart</param> 195 /// <param name="hostID">UUID of the SceneObjectPart</param>
173 /// <param name="channel">channel to listen on</param> 196 /// <param name="channel">channel to listen on</param>
174 /// <param name="name">name to filter on</param> 197 /// <param name="name">name to filter on</param>
175 /// <param name="id">key to filter on (user given, could be totally faked)</param> 198 /// <param name="id">
199 /// key to filter on (user given, could be totally faked)
200 /// </param>
201 /// <param name="msg">msg to filter on</param>
202 /// <returns>number of the scripts handle</returns>
203 public int Listen(uint localID, UUID itemID, UUID hostID, int channel,
204 string name, UUID id, string msg)
205 {
206 return m_listenerManager.AddListener(localID, itemID, hostID,
207 channel, name, id, msg);
208 }
209
210 /// <summary>
211 /// Create a listen event callback with the specified filters.
212 /// The parameters localID,itemID are needed to uniquely identify
213 /// the script during 'peek' time. Parameter hostID is needed to
214 /// determine the position of the script.
215 /// </summary>
216 /// <param name="localID">localID of the script engine</param>
217 /// <param name="itemID">UUID of the script engine</param>
218 /// <param name="hostID">UUID of the SceneObjectPart</param>
219 /// <param name="channel">channel to listen on</param>
220 /// <param name="name">name to filter on</param>
221 /// <param name="id">
222 /// key to filter on (user given, could be totally faked)
223 /// </param>
176 /// <param name="msg">msg to filter on</param> 224 /// <param name="msg">msg to filter on</param>
225 /// <param name="regexBitfield">
226 /// Bitfield indicating which strings should be processed as regex.
227 /// </param>
177 /// <returns>number of the scripts handle</returns> 228 /// <returns>number of the scripts handle</returns>
178 public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) 229 public int Listen(uint localID, UUID itemID, UUID hostID, int channel,
230 string name, UUID id, string msg, int regexBitfield)
179 { 231 {
180 return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); 232 return m_listenerManager.AddListener(localID, itemID, hostID,
233 channel, name, id, msg, regexBitfield);
181 } 234 }
182 235
183 /// <summary> 236 /// <summary>
@@ -226,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
226 279
227 if ((source = m_scene.GetSceneObjectPart(id)) != null) 280 if ((source = m_scene.GetSceneObjectPart(id)) != null)
228 position = source.AbsolutePosition; 281 position = source.AbsolutePosition;
229 else if ((avatar = m_scene.GetScenePresence(id)) != null) 282 else if ((avatar = m_scene.GetScenePresence(id)) != null)
230 position = avatar.AbsolutePosition; 283 position = avatar.AbsolutePosition;
231 else if (ChatTypeEnum.Region == type) 284 else if (ChatTypeEnum.Region == type)
232 position = CenterOfRegion; 285 position = CenterOfRegion;
@@ -249,7 +302,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
249 /// <param name="name">name of sender (object or avatar)</param> 302 /// <param name="name">name of sender (object or avatar)</param>
250 /// <param name="id">key of sender (object or avatar)</param> 303 /// <param name="id">key of sender (object or avatar)</param>
251 /// <param name="msg">msg to sent</param> 304 /// <param name="msg">msg to sent</param>
252 public void DeliverMessage(ChatTypeEnum type, int channel, string name, UUID id, string msg, Vector3 position) 305 public void DeliverMessage(ChatTypeEnum type, int channel,
306 string name, UUID id, string msg, Vector3 position)
253 { 307 {
254 // m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}", 308 // m_log.DebugFormat("[WorldComm] got[2] type {0}, channel {1}, name {2}, id {3}, msg {4}",
255 // type, channel, name, id, msg); 309 // type, channel, name, id, msg);
@@ -257,17 +311,21 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
257 // Determine which listen event filters match the given set of arguments, this results 311 // Determine which listen event filters match the given set of arguments, this results
258 // in a limited set of listeners, each belonging a host. If the host is in range, add them 312 // in a limited set of listeners, each belonging a host. If the host is in range, add them
259 // to the pending queue. 313 // to the pending queue.
260 foreach (ListenerInfo li in m_listenerManager.GetListeners(UUID.Zero, channel, name, id, msg)) 314 foreach (ListenerInfo li
315 in m_listenerManager.GetListeners(UUID.Zero, channel,
316 name, id, msg))
261 { 317 {
262 // Dont process if this message is from yourself! 318 // Dont process if this message is from yourself!
263 if (li.GetHostID().Equals(id)) 319 if (li.GetHostID().Equals(id))
264 continue; 320 continue;
265 321
266 SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.GetHostID()); 322 SceneObjectPart sPart = m_scene.GetSceneObjectPart(
323 li.GetHostID());
267 if (sPart == null) 324 if (sPart == null)
268 continue; 325 continue;
269 326
270 double dis = Util.GetDistanceTo(sPart.AbsolutePosition, position); 327 double dis = Util.GetDistanceTo(sPart.AbsolutePosition,
328 position);
271 switch (type) 329 switch (type)
272 { 330 {
273 case ChatTypeEnum.Whisper: 331 case ChatTypeEnum.Whisper:
@@ -326,7 +384,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
326 if (channel == 0) 384 if (channel == 0)
327 { 385 {
328 // Channel 0 goes to viewer ONLY 386 // Channel 0 goes to viewer ONLY
329 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, false, false, target); 387 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false);
330 return true; 388 return true;
331 } 389 }
332 390
@@ -369,11 +427,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
369 if (li.GetHostID().Equals(id)) 427 if (li.GetHostID().Equals(id))
370 continue; 428 continue;
371 429
372 SceneObjectPart sPart = m_scene.GetSceneObjectPart(li.GetHostID()); 430 SceneObjectPart sPart = m_scene.GetSceneObjectPart(
431 li.GetHostID());
373 if (sPart == null) 432 if (sPart == null)
374 continue; 433 continue;
375 434
376 if ( li.GetHostID().Equals(target)) 435 if (li.GetHostID().Equals(target))
377 { 436 {
378 QueueMessage(new ListenerInfo(li, name, id, msg)); 437 QueueMessage(new ListenerInfo(li, name, id, msg));
379 break; 438 break;
@@ -427,9 +486,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
427 private void DeliverClientMessage(Object sender, OSChatMessage e) 486 private void DeliverClientMessage(Object sender, OSChatMessage e)
428 { 487 {
429 if (null != e.Sender) 488 if (null != e.Sender)
430 DeliverMessage(e.Type, e.Channel, e.Sender.Name, e.Sender.AgentId, e.Message, e.Position); 489 {
490 DeliverMessage(e.Type, e.Channel, e.Sender.Name,
491 e.Sender.AgentId, e.Message, e.Position);
492 }
431 else 493 else
432 DeliverMessage(e.Type, e.Channel, e.From, UUID.Zero, e.Message, e.Position); 494 {
495 DeliverMessage(e.Type, e.Channel, e.From, UUID.Zero,
496 e.Message, e.Position);
497 }
433 } 498 }
434 499
435 public Object[] GetSerializationData(UUID itemID) 500 public Object[] GetSerializationData(UUID itemID)
@@ -446,7 +511,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
446 511
447 public class ListenerManager 512 public class ListenerManager
448 { 513 {
449 private Dictionary<int, List<ListenerInfo>> m_listeners = new Dictionary<int, List<ListenerInfo>>(); 514 private Dictionary<int, List<ListenerInfo>> m_listeners =
515 new Dictionary<int, List<ListenerInfo>>();
450 private int m_maxlisteners; 516 private int m_maxlisteners;
451 private int m_maxhandles; 517 private int m_maxhandles;
452 private int m_curlisteners; 518 private int m_curlisteners;
@@ -470,15 +536,25 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
470 m_curlisteners = 0; 536 m_curlisteners = 0;
471 } 537 }
472 538
473 public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) 539 public int AddListener(uint localID, UUID itemID, UUID hostID,
540 int channel, string name, UUID id, string msg)
541 {
542 return AddListener(localID, itemID, hostID, channel, name, id,
543 msg, 0);
544 }
545
546 public int AddListener(uint localID, UUID itemID, UUID hostID,
547 int channel, string name, UUID id, string msg,
548 int regexBitfield)
474 { 549 {
475 // do we already have a match on this particular filter event? 550 // do we already have a match on this particular filter event?
476 List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, msg); 551 List<ListenerInfo> coll = GetListeners(itemID, channel, name, id,
552 msg);
477 553
478 if (coll.Count > 0) 554 if (coll.Count > 0)
479 { 555 {
480 // special case, called with same filter settings, return same handle 556 // special case, called with same filter settings, return same
481 // (2008-05-02, tested on 1.21.1 server, still holds) 557 // handle (2008-05-02, tested on 1.21.1 server, still holds)
482 return coll[0].GetHandle(); 558 return coll[0].GetHandle();
483 } 559 }
484 560
@@ -490,16 +566,19 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
490 566
491 if (newHandle > 0) 567 if (newHandle > 0)
492 { 568 {
493 ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg); 569 ListenerInfo li = new ListenerInfo(newHandle, localID,
570 itemID, hostID, channel, name, id, msg,
571 regexBitfield);
494 572
495 List<ListenerInfo> listeners; 573 List<ListenerInfo> listeners;
496 if (!m_listeners.TryGetValue(channel,out listeners)) 574 if (!m_listeners.TryGetValue(
497 { 575 channel, out listeners))
498 listeners = new List<ListenerInfo>(); 576 {
499 m_listeners.Add(channel, listeners); 577 listeners = new List<ListenerInfo>();
500 } 578 m_listeners.Add(channel, listeners);
501 listeners.Add(li); 579 }
502 m_curlisteners++; 580 listeners.Add(li);
581 m_curlisteners++;
503 582
504 return newHandle; 583 return newHandle;
505 } 584 }
@@ -512,11 +591,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
512 { 591 {
513 lock (m_listeners) 592 lock (m_listeners)
514 { 593 {
515 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) 594 foreach (KeyValuePair<int, List<ListenerInfo>> lis
595 in m_listeners)
516 { 596 {
517 foreach (ListenerInfo li in lis.Value) 597 foreach (ListenerInfo li in lis.Value)
518 { 598 {
519 if (li.GetItemID().Equals(itemID) && li.GetHandle().Equals(handle)) 599 if (li.GetItemID().Equals(itemID) &&
600 li.GetHandle().Equals(handle))
520 { 601 {
521 lis.Value.Remove(li); 602 lis.Value.Remove(li);
522 if (lis.Value.Count == 0) 603 if (lis.Value.Count == 0)
@@ -539,13 +620,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
539 620
540 lock (m_listeners) 621 lock (m_listeners)
541 { 622 {
542 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) 623 foreach (KeyValuePair<int, List<ListenerInfo>> lis
624 in m_listeners)
543 { 625 {
544 foreach (ListenerInfo li in lis.Value) 626 foreach (ListenerInfo li in lis.Value)
545 { 627 {
546 if (li.GetItemID().Equals(itemID)) 628 if (li.GetItemID().Equals(itemID))
547 { 629 {
548 // store them first, else the enumerated bails on us 630 // store them first, else the enumerated bails on
631 // us
549 removedListeners.Add(li); 632 removedListeners.Add(li);
550 } 633 }
551 } 634 }
@@ -572,11 +655,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
572 { 655 {
573 lock (m_listeners) 656 lock (m_listeners)
574 { 657 {
575 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) 658 foreach (KeyValuePair<int, List<ListenerInfo>> lis
659 in m_listeners)
576 { 660 {
577 foreach (ListenerInfo li in lis.Value) 661 foreach (ListenerInfo li in lis.Value)
578 { 662 {
579 if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle) 663 if (li.GetItemID().Equals(itemID) &&
664 li.GetHandle() == handle)
580 { 665 {
581 li.Activate(); 666 li.Activate();
582 // only one, bail out 667 // only one, bail out
@@ -591,11 +676,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
591 { 676 {
592 lock (m_listeners) 677 lock (m_listeners)
593 { 678 {
594 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) 679 foreach (KeyValuePair<int, List<ListenerInfo>> lis
680 in m_listeners)
595 { 681 {
596 foreach (ListenerInfo li in lis.Value) 682 foreach (ListenerInfo li in lis.Value)
597 { 683 {
598 if (li.GetItemID().Equals(itemID) && li.GetHandle() == handle) 684 if (li.GetItemID().Equals(itemID) &&
685 li.GetHandle() == handle)
599 { 686 {
600 li.Deactivate(); 687 li.Deactivate();
601 // only one, bail out 688 // only one, bail out
@@ -606,19 +693,24 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
606 } 693 }
607 } 694 }
608 695
609 // non-locked access, since its always called in the context of the lock 696 /// <summary>
697 /// non-locked access, since its always called in the context of the
698 /// lock
699 /// </summary>
700 /// <param name="itemID"></param>
701 /// <returns></returns>
610 private int GetNewHandle(UUID itemID) 702 private int GetNewHandle(UUID itemID)
611 { 703 {
612 List<int> handles = new List<int>(); 704 List<int> handles = new List<int>();
613 705
614 // build a list of used keys for this specific itemID... 706 // build a list of used keys for this specific itemID...
615 foreach (KeyValuePair<int,List<ListenerInfo>> lis in m_listeners) 707 foreach (KeyValuePair<int, List<ListenerInfo>> lis in m_listeners)
616 { 708 {
617 foreach (ListenerInfo li in lis.Value) 709 foreach (ListenerInfo li in lis.Value)
618 { 710 {
619 if (li.GetItemID().Equals(itemID)) 711 if (li.GetItemID().Equals(itemID))
620 handles.Add(li.GetHandle()); 712 handles.Add(li.GetHandle());
621 } 713 }
622 } 714 }
623 715
624 // Note: 0 is NOT a valid handle for llListen() to return 716 // Note: 0 is NOT a valid handle for llListen() to return
@@ -631,17 +723,46 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
631 return -1; 723 return -1;
632 } 724 }
633 725
634 // Theres probably a more clever and efficient way to 726 /// These are duplicated from ScriptBaseClass
635 // do this, maybe with regex. 727 /// http://opensimulator.org/mantis/view.php?id=6106#c21945
636 // PM2008: Ha, one could even be smart and define a specialized Enumerator. 728 #region Constants for the bitfield parameter of osListenRegex
637 public List<ListenerInfo> GetListeners(UUID itemID, int channel, string name, UUID id, string msg) 729
730 /// <summary>
731 /// process name parameter as regex
732 /// </summary>
733 public const int OS_LISTEN_REGEX_NAME = 0x1;
734
735 /// <summary>
736 /// process message parameter as regex
737 /// </summary>
738 public const int OS_LISTEN_REGEX_MESSAGE = 0x2;
739
740 #endregion
741
742 /// <summary>
743 /// Get listeners matching the input parameters.
744 /// </summary>
745 /// <remarks>
746 /// Theres probably a more clever and efficient way to do this, maybe
747 /// with regex.
748 /// PM2008: Ha, one could even be smart and define a specialized
749 /// Enumerator.
750 /// </remarks>
751 /// <param name="itemID"></param>
752 /// <param name="channel"></param>
753 /// <param name="name"></param>
754 /// <param name="id"></param>
755 /// <param name="msg"></param>
756 /// <returns></returns>
757 public List<ListenerInfo> GetListeners(UUID itemID, int channel,
758 string name, UUID id, string msg)
638 { 759 {
639 List<ListenerInfo> collection = new List<ListenerInfo>(); 760 List<ListenerInfo> collection = new List<ListenerInfo>();
640 761
641 lock (m_listeners) 762 lock (m_listeners)
642 { 763 {
643 List<ListenerInfo> listeners; 764 List<ListenerInfo> listeners;
644 if (!m_listeners.TryGetValue(channel,out listeners)) 765 if (!m_listeners.TryGetValue(channel, out listeners))
645 { 766 {
646 return collection; 767 return collection;
647 } 768 }
@@ -652,11 +773,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
652 { 773 {
653 continue; 774 continue;
654 } 775 }
655 if (!itemID.Equals(UUID.Zero) && !li.GetItemID().Equals(itemID)) 776 if (!itemID.Equals(UUID.Zero) &&
777 !li.GetItemID().Equals(itemID))
656 { 778 {
657 continue; 779 continue;
658 } 780 }
659 if (li.GetName().Length > 0 && !li.GetName().Equals(name)) 781 if (li.GetName().Length > 0 && (
782 ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) ||
783 ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName()))
784 ))
660 { 785 {
661 continue; 786 continue;
662 } 787 }
@@ -664,7 +789,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
664 { 789 {
665 continue; 790 continue;
666 } 791 }
667 if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg)) 792 if (li.GetMessage().Length > 0 && (
793 ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) ||
794 ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage()))
795 ))
668 { 796 {
669 continue; 797 continue;
670 } 798 }
@@ -697,10 +825,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
697 { 825 {
698 int idx = 0; 826 int idx = 0;
699 Object[] item = new Object[6]; 827 Object[] item = new Object[6];
828 int dataItemLength = 6;
700 829
701 while (idx < data.Length) 830 while (idx < data.Length)
702 { 831 {
703 Array.Copy(data, idx, item, 0, 6); 832 dataItemLength = (idx + 7 == data.Length || (idx + 7 < data.Length && data[idx + 7] is bool)) ? 7 : 6;
833 item = new Object[dataItemLength];
834 Array.Copy(data, idx, item, 0, dataItemLength);
704 835
705 ListenerInfo info = 836 ListenerInfo info =
706 ListenerInfo.FromData(localID, itemID, hostID, item); 837 ListenerInfo.FromData(localID, itemID, hostID, item);
@@ -708,39 +839,98 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
708 lock (m_listeners) 839 lock (m_listeners)
709 { 840 {
710 if (!m_listeners.ContainsKey((int)item[2])) 841 if (!m_listeners.ContainsKey((int)item[2]))
711 m_listeners.Add((int)item[2], new List<ListenerInfo>()); 842 {
843 m_listeners.Add((int)item[2],
844 new List<ListenerInfo>());
845 }
712 m_listeners[(int)item[2]].Add(info); 846 m_listeners[(int)item[2]].Add(info);
713 } 847 }
714 848
715 idx+=6; 849 idx += dataItemLength;
716 } 850 }
717 } 851 }
718 } 852 }
719 853
720 public class ListenerInfo: IWorldCommListenerInfo 854 public class ListenerInfo : IWorldCommListenerInfo
721 { 855 {
722 private bool m_active; // Listener is active or not 856 /// <summary>
723 private int m_handle; // Assigned handle of this listener 857 /// Listener is active or not
724 private uint m_localID; // Local ID from script engine 858 /// </summary>
725 private UUID m_itemID; // ID of the host script engine 859 private bool m_active;
726 private UUID m_hostID; // ID of the host/scene part 860
727 private int m_channel; // Channel 861 /// <summary>
728 private UUID m_id; // ID to filter messages from 862 /// Assigned handle of this listener
729 private string m_name; // Object name to filter messages from 863 /// </summary>
730 private string m_message; // The message 864 private int m_handle;
865
866 /// <summary>
867 /// Local ID from script engine
868 /// </summary>
869 private uint m_localID;
870
871 /// <summary>
872 /// ID of the host script engine
873 /// </summary>
874 private UUID m_itemID;
875
876 /// <summary>
877 /// ID of the host/scene part
878 /// </summary>
879 private UUID m_hostID;
880
881 /// <summary>
882 /// Channel
883 /// </summary>
884 private int m_channel;
885
886 /// <summary>
887 /// ID to filter messages from
888 /// </summary>
889 private UUID m_id;
890
891 /// <summary>
892 /// Object name to filter messages from
893 /// </summary>
894 private string m_name;
895
896 /// <summary>
897 /// The message
898 /// </summary>
899 private string m_message;
900
901 public ListenerInfo(int handle, uint localID, UUID ItemID,
902 UUID hostID, int channel, string name, UUID id,
903 string message)
904 {
905 Initialise(handle, localID, ItemID, hostID, channel, name, id,
906 message, 0);
907 }
731 908
732 public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) 909 public ListenerInfo(int handle, uint localID, UUID ItemID,
910 UUID hostID, int channel, string name, UUID id,
911 string message, int regexBitfield)
733 { 912 {
734 Initialise(handle, localID, ItemID, hostID, channel, name, id, message); 913 Initialise(handle, localID, ItemID, hostID, channel, name, id,
914 message, regexBitfield);
735 } 915 }
736 916
737 public ListenerInfo(ListenerInfo li, string name, UUID id, string message) 917 public ListenerInfo(ListenerInfo li, string name, UUID id,
918 string message)
738 { 919 {
739 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message); 920 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID,
921 li.m_channel, name, id, message, 0);
740 } 922 }
741 923
742 private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, 924 public ListenerInfo(ListenerInfo li, string name, UUID id,
743 UUID id, string message) 925 string message, int regexBitfield)
926 {
927 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID,
928 li.m_channel, name, id, message, regexBitfield);
929 }
930
931 private void Initialise(int handle, uint localID, UUID ItemID,
932 UUID hostID, int channel, string name, UUID id,
933 string message, int regexBitfield)
744 { 934 {
745 m_active = true; 935 m_active = true;
746 m_handle = handle; 936 m_handle = handle;
@@ -751,11 +941,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
751 m_name = name; 941 m_name = name;
752 m_id = id; 942 m_id = id;
753 m_message = message; 943 m_message = message;
944 RegexBitfield = regexBitfield;
754 } 945 }
755 946
756 public Object[] GetSerializationData() 947 public Object[] GetSerializationData()
757 { 948 {
758 Object[] data = new Object[6]; 949 Object[] data = new Object[7];
759 950
760 data[0] = m_active; 951 data[0] = m_active;
761 data[1] = m_handle; 952 data[1] = m_handle;
@@ -763,16 +954,22 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
763 data[3] = m_name; 954 data[3] = m_name;
764 data[4] = m_id; 955 data[4] = m_id;
765 data[5] = m_message; 956 data[5] = m_message;
957 data[6] = RegexBitfield;
766 958
767 return data; 959 return data;
768 } 960 }
769 961
770 public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) 962 public static ListenerInfo FromData(uint localID, UUID ItemID,
963 UUID hostID, Object[] data)
771 { 964 {
772 ListenerInfo linfo = new ListenerInfo((int)data[1], localID, 965 ListenerInfo linfo = new ListenerInfo((int)data[1], localID,
773 ItemID, hostID, (int)data[2], (string)data[3], 966 ItemID, hostID, (int)data[2], (string)data[3],
774 (UUID)data[4], (string)data[5]); 967 (UUID)data[4], (string)data[5]);
775 linfo.m_active=(bool)data[0]; 968 linfo.m_active = (bool)data[0];
969 if (data.Length >= 7)
970 {
971 linfo.RegexBitfield = (int)data[6];
972 }
776 973
777 return linfo; 974 return linfo;
778 } 975 }
@@ -831,5 +1028,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
831 { 1028 {
832 return m_id; 1029 return m_id;
833 } 1030 }
1031
1032 public int RegexBitfield { get; private set; }
834 } 1033 }
835} 1034}
diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
index 0003af2..385f5ad 100644
--- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
@@ -40,6 +40,7 @@ using OpenSim.Framework.Servers;
40using OpenSim.Framework.Servers.HttpServer; 40using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using Mono.Addins;
43 44
44/***************************************************** 45/*****************************************************
45 * 46 *
@@ -76,7 +77,8 @@ using OpenSim.Region.Framework.Scenes;
76 77
77namespace OpenSim.Region.CoreModules.Scripting.XMLRPC 78namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
78{ 79{
79 public class XMLRPCModule : IRegionModule, IXMLRPC 80 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XMLRPCModule")]
81 public class XMLRPCModule : ISharedRegionModule, IXMLRPC
80 { 82 {
81 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 83 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
82 84
@@ -86,6 +88,10 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
86 private Dictionary<UUID, RPCChannelInfo> m_openChannels; 88 private Dictionary<UUID, RPCChannelInfo> m_openChannels;
87 private Dictionary<UUID, SendRemoteDataRequest> m_pendingSRDResponses; 89 private Dictionary<UUID, SendRemoteDataRequest> m_pendingSRDResponses;
88 private int m_remoteDataPort = 0; 90 private int m_remoteDataPort = 0;
91 public int Port
92 {
93 get { return m_remoteDataPort; }
94 }
89 95
90 private Dictionary<UUID, RPCRequestInfo> m_rpcPending; 96 private Dictionary<UUID, RPCRequestInfo> m_rpcPending;
91 private Dictionary<UUID, RPCRequestInfo> m_rpcPendingResponses; 97 private Dictionary<UUID, RPCRequestInfo> m_rpcPendingResponses;
@@ -94,34 +100,24 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
94 private int RemoteReplyScriptWait = 300; 100 private int RemoteReplyScriptWait = 300;
95 private object XMLRPCListLock = new object(); 101 private object XMLRPCListLock = new object();
96 102
97 #region IRegionModule Members 103 #region ISharedRegionModule Members
98 104
99 public void Initialise(Scene scene, IConfigSource config) 105 public void Initialise(IConfigSource config)
100 { 106 {
101 // We need to create these early because the scripts might be calling 107 // We need to create these early because the scripts might be calling
102 // But since this gets called for every region, we need to make sure they 108 // But since this gets called for every region, we need to make sure they
103 // get called only one time (or we lose any open channels) 109 // get called only one time (or we lose any open channels)
104 if (null == m_openChannels) 110 m_openChannels = new Dictionary<UUID, RPCChannelInfo>();
105 { 111 m_rpcPending = new Dictionary<UUID, RPCRequestInfo>();
106 m_openChannels = new Dictionary<UUID, RPCChannelInfo>(); 112 m_rpcPendingResponses = new Dictionary<UUID, RPCRequestInfo>();
107 m_rpcPending = new Dictionary<UUID, RPCRequestInfo>(); 113 m_pendingSRDResponses = new Dictionary<UUID, SendRemoteDataRequest>();
108 m_rpcPendingResponses = new Dictionary<UUID, RPCRequestInfo>();
109 m_pendingSRDResponses = new Dictionary<UUID, SendRemoteDataRequest>();
110 114
111 try 115 try
112 { 116 {
113 m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort); 117 m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort);
114 }
115 catch (Exception)
116 {
117 }
118 } 118 }
119 119 catch (Exception)
120 if (!m_scenes.Contains(scene))
121 { 120 {
122 m_scenes.Add(scene);
123
124 scene.RegisterModuleInterface<IXMLRPC>(this);
125 } 121 }
126 } 122 }
127 123
@@ -131,32 +127,56 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
131 { 127 {
132 // Start http server 128 // Start http server
133 // Attach xmlrpc handlers 129 // Attach xmlrpc handlers
134// m_log.InfoFormat( 130 // m_log.InfoFormat(
135// "[XML RPC MODULE]: Starting up XMLRPC Server on port {0} for llRemoteData commands.", 131 // "[XML RPC MODULE]: Starting up XMLRPC Server on port {0} for llRemoteData commands.",
136// m_remoteDataPort); 132 // m_remoteDataPort);
137 133
138 IHttpServer httpServer = MainServer.GetHttpServer((uint)m_remoteDataPort); 134 IHttpServer httpServer = MainServer.GetHttpServer((uint)m_remoteDataPort);
139 httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData); 135 httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData);
140 } 136 }
141 } 137 }
142 138
143 public void Close() 139 public void AddRegion(Scene scene)
140 {
141 if (!IsEnabled())
142 return;
143
144 if (!m_scenes.Contains(scene))
145 {
146 m_scenes.Add(scene);
147
148 scene.RegisterModuleInterface<IXMLRPC>(this);
149 }
150 }
151
152 public void RegionLoaded(Scene scene)
144 { 153 {
145 } 154 }
146 155
147 public string Name 156 public void RemoveRegion(Scene scene)
148 { 157 {
149 get { return m_name; } 158 if (!IsEnabled())
159 return;
160
161 if (m_scenes.Contains(scene))
162 {
163 scene.UnregisterModuleInterface<IXMLRPC>(this);
164 m_scenes.Remove(scene);
165 }
150 } 166 }
151 167
152 public bool IsSharedModule 168 public void Close()
153 { 169 {
154 get { return true; }
155 } 170 }
156 171
157 public int Port 172 public string Name
158 { 173 {
159 get { return m_remoteDataPort; } 174 get { return m_name; }
175 }
176
177 public Type ReplaceableInterface
178 {
179 get { return null; }
160 } 180 }
161 181
162 #endregion 182 #endregion
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs
index 5541684..7b4668a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Servers; 35using OpenSim.Framework.Servers;
@@ -39,6 +40,7 @@ using OpenSim.Server.Handlers.Base;
39 40
40namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Asset 41namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Asset
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AssetServiceInConnectorModule")]
42 public class AssetServiceInConnectorModule : ISharedRegionModule 44 public class AssetServiceInConnectorModule : ISharedRegionModule
43 { 45 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -47,7 +49,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Asset
47 private IConfigSource m_Config; 49 private IConfigSource m_Config;
48 bool m_Registered = false; 50 bool m_Registered = false;
49 51
50 #region IRegionModule interface 52 #region Region Module interface
51 53
52 public void Initialise(IConfigSource config) 54 public void Initialise(IConfigSource config)
53 { 55 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs
index ccf2275..2cdffe6 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Authentication/AuthenticationServiceInConnectorModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Servers; 35using OpenSim.Framework.Servers;
@@ -41,6 +42,7 @@ using OpenSim.Services.Interfaces;
41 42
42namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication 43namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication
43{ 44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AuthenticationServiceInConnectorModule")]
44 public class AuthenticationServiceInConnectorModule : ISharedRegionModule 46 public class AuthenticationServiceInConnectorModule : ISharedRegionModule
45 { 47 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -49,7 +51,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Authentication
49 private IConfigSource m_Config; 51 private IConfigSource m_Config;
50 bool m_Registered = false; 52 bool m_Registered = false;
51 53
52 #region IRegionModule interface 54 #region Region Module interface
53 55
54 public void Initialise(IConfigSource config) 56 public void Initialise(IConfigSource config)
55 { 57 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs
index 0e16e5a..22857d0 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/GridInfoServiceInConnectorModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Servers; 35using OpenSim.Framework.Servers;
@@ -41,6 +42,7 @@ using OpenSim.Services.Interfaces;
41 42
42namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Grid 43namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Grid
43{ 44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GridInfoServiceInConnectorModule")]
44 public class GridInfoServiceInConnectorModule : ISharedRegionModule 46 public class GridInfoServiceInConnectorModule : ISharedRegionModule
45 { 47 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -49,7 +51,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Grid
49 private IConfigSource m_Config; 51 private IConfigSource m_Config;
50 bool m_Registered = false; 52 bool m_Registered = false;
51 53
52 #region IRegionModule interface 54 #region Region Module interface
53 55
54 public void Initialise(IConfigSource config) 56 public void Initialise(IConfigSource config)
55 { 57 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
index a7dd0dd..f749295 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Servers; 35using OpenSim.Framework.Servers;
@@ -42,6 +43,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
42 43
43namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid 44namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
44{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HypergridServiceInConnectorModule")]
45 public class HypergridServiceInConnectorModule : ISharedRegionModule 47 public class HypergridServiceInConnectorModule : ISharedRegionModule
46 { 48 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -53,7 +55,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
53 private GatekeeperServiceInConnector m_HypergridHandler; 55 private GatekeeperServiceInConnector m_HypergridHandler;
54 private UserAgentServerConnector m_UASHandler; 56 private UserAgentServerConnector m_UASHandler;
55 57
56 #region IRegionModule interface 58 #region Region Module interface
57 59
58 public void Initialise(IConfigSource config) 60 public void Initialise(IConfigSource config)
59 { 61 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs
index 831ea27..0a4e736 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Servers; 35using OpenSim.Framework.Servers;
@@ -39,6 +40,7 @@ using OpenSim.Server.Handlers.Base;
39 40
40namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory 41namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "InventoryServiceInConnectorModule")]
42 public class InventoryServiceInConnectorModule : ISharedRegionModule 44 public class InventoryServiceInConnectorModule : ISharedRegionModule
43 { 45 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -47,7 +49,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory
47 private IConfigSource m_Config; 49 private IConfigSource m_Config;
48 bool m_Registered = false; 50 bool m_Registered = false;
49 51
50 #region IRegionModule interface 52 #region Region Module interface
51 53
52 public void Initialise(IConfigSource config) 54 public void Initialise(IConfigSource config)
53 { 55 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs
index 2f3c350..2fd21be 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Servers; 35using OpenSim.Framework.Servers;
@@ -42,6 +43,7 @@ using OpenMetaverse;
42 43
43namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Land 44namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Land
44{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LandServiceInConnectorModule")]
45 public class LandServiceInConnectorModule : ISharedRegionModule, ILandService 47 public class LandServiceInConnectorModule : ISharedRegionModule, ILandService
46 { 48 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -51,7 +53,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Land
51 private IConfigSource m_Config; 53 private IConfigSource m_Config;
52 private List<Scene> m_Scenes = new List<Scene>(); 54 private List<Scene> m_Scenes = new List<Scene>();
53 55
54 #region IRegionModule interface 56 #region Region Module interface
55 57
56 public void Initialise(IConfigSource config) 58 public void Initialise(IConfigSource config)
57 { 59 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs
index ecdb380..425febd 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Login/LLLoginServiceInConnectorModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Servers; 35using OpenSim.Framework.Servers;
@@ -42,6 +43,7 @@ using OpenSim.Services.Interfaces;
42 43
43namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Login 44namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Login
44{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LLLoginServiceInConnectorModule")]
45 public class LLLoginServiceInConnectorModule : ISharedRegionModule 47 public class LLLoginServiceInConnectorModule : ISharedRegionModule
46 { 48 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -51,7 +53,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Login
51 private IConfigSource m_Config; 53 private IConfigSource m_Config;
52 private List<Scene> m_Scenes = new List<Scene>(); 54 private List<Scene> m_Scenes = new List<Scene>();
53 55
54 #region IRegionModule interface 56 #region Region Module interface
55 57
56 public void Initialise(IConfigSource config) 58 public void Initialise(IConfigSource config)
57 { 59 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs
index d38af23..c14bce7 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/MapImage/MapImageServiceInConnectorModule.cs
@@ -42,7 +42,7 @@ using OpenSim.Services.Interfaces;
42 42
43namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.MapImage 43namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.MapImage
44{ 44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MapImageServiceInConnectorModule")]
46 public class MapImageServiceInConnectorModule : ISharedRegionModule 46 public class MapImageServiceInConnectorModule : ISharedRegionModule
47 { 47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -50,7 +50,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.MapImage
50 50
51 private IConfigSource m_Config; 51 private IConfigSource m_Config;
52 52
53 #region IRegionModule interface 53 #region Region Module interface
54 54
55 public void Initialise(IConfigSource config) 55 public void Initialise(IConfigSource config)
56 { 56 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs
index b544ab3..6bf47cb 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Servers; 35using OpenSim.Framework.Servers;
@@ -41,6 +42,7 @@ using OpenSim.Services.Interfaces;
41 42
42namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Neighbour 43namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Neighbour
43{ 44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "NeighbourServiceInConnectorModule")]
44 public class NeighbourServiceInConnectorModule : ISharedRegionModule, INeighbourService 46 public class NeighbourServiceInConnectorModule : ISharedRegionModule, INeighbourService
45 { 47 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -50,7 +52,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Neighbour
50 private IConfigSource m_Config; 52 private IConfigSource m_Config;
51 private List<Scene> m_Scenes = new List<Scene>(); 53 private List<Scene> m_Scenes = new List<Scene>();
52 54
53 #region IRegionModule interface 55 #region Region Module interface
54 56
55 public void Initialise(IConfigSource config) 57 public void Initialise(IConfigSource config)
56 { 58 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs
index 0a5275d..57d1132 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Servers; 35using OpenSim.Framework.Servers;
@@ -40,7 +41,7 @@ using OpenSim.Server.Handlers.Base;
40 41
41namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Simulation 42namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Simulation
42{ 43{
43 // Under construction 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimulationServiceInConnectorModule")]
44 public class SimulationServiceInConnectorModule : ISharedRegionModule 45 public class SimulationServiceInConnectorModule : ISharedRegionModule
45 { 46 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -49,7 +50,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Simulation
49 private IConfigSource m_Config; 50 private IConfigSource m_Config;
50 bool m_Registered = false; 51 bool m_Registered = false;
51 52
52 #region IRegionModule interface 53 #region Region Module interface
53 54
54 public void Initialise(IConfigSource config) 55 public void Initialise(IConfigSource config)
55 { 56 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
index 008465f..d221d68 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using log4net; 28using log4net;
29using Mono.Addins;
29using Nini.Config; 30using Nini.Config;
30using System; 31using System;
31using System.Collections.Generic; 32using System.Collections.Generic;
@@ -40,8 +41,8 @@ using OpenMetaverse;
40 41
41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset 42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
42{ 43{
43 public class HGAssetBroker : 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGAssetBroker")]
44 ISharedRegionModule, IAssetService 45 public class HGAssetBroker : ISharedRegionModule, IAssetService
45 { 46 {
46 private static readonly ILog m_log = 47 private static readonly ILog m_log =
47 LogManager.GetLogger( 48 LogManager.GetLogger(
@@ -56,6 +57,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
56 57
57 private bool m_Enabled = false; 58 private bool m_Enabled = false;
58 59
60 private AssetPermissions m_AssetPerms;
61
59 public Type ReplaceableInterface 62 public Type ReplaceableInterface
60 { 63 {
61 get { return null; } 64 get { return null; }
@@ -128,6 +131,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
128 if (m_LocalAssetServiceURI != string.Empty) 131 if (m_LocalAssetServiceURI != string.Empty)
129 m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/'); 132 m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/');
130 133
134 IConfig hgConfig = source.Configs["HGAssetService"];
135 m_AssetPerms = new AssetPermissions(hgConfig); // it's ok if arg is null
136
131 m_Enabled = true; 137 m_Enabled = true;
132 m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled"); 138 m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled");
133 } 139 }
@@ -206,14 +212,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
206 asset = m_HGService.Get(id); 212 asset = m_HGService.Get(id);
207 if (asset != null) 213 if (asset != null)
208 { 214 {
209 // Now store it locally 215 // Now store it locally, if allowed
210 // For now, let me just do it for textures and scripts 216 if (m_AssetPerms.AllowedImport(asset.Type))
211 if (((AssetType)asset.Type == AssetType.Texture) ||
212 ((AssetType)asset.Type == AssetType.LSLBytecode) ||
213 ((AssetType)asset.Type == AssetType.LSLText))
214 {
215 m_GridService.Store(asset); 217 m_GridService.Store(asset);
216 } 218 else
219 return null;
217 } 220 }
218 } 221 }
219 else 222 else
@@ -328,7 +331,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
328 331
329 string id = string.Empty; 332 string id = string.Empty;
330 if (IsHG(asset.ID)) 333 if (IsHG(asset.ID))
331 id = m_HGService.Store(asset); 334 {
335 if (m_AssetPerms.AllowedExport(asset.Type))
336 id = m_HGService.Store(asset);
337 else
338 return String.Empty;
339 }
332 else 340 else
333 id = m_GridService.Store(asset); 341 id = m_GridService.Store(asset);
334 342
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
index c78915f..480cd69 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using log4net; 28using log4net;
29using Mono.Addins;
29using Nini.Config; 30using Nini.Config;
30using System; 31using System;
31using System.Collections.Generic; 32using System.Collections.Generic;
@@ -38,6 +39,7 @@ using OpenSim.Services.Interfaces;
38 39
39namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset 40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
40{ 41{
42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalAssetServicesConnector")]
41 public class LocalAssetServicesConnector : ISharedRegionModule, IAssetService 43 public class LocalAssetServicesConnector : ISharedRegionModule, IAssetService
42 { 44 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -204,8 +206,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
204 public byte[] GetData(string id) 206 public byte[] GetData(string id)
205 { 207 {
206// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id); 208// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id);
207 209
208 AssetBase asset = m_Cache.Get(id); 210 AssetBase asset = null;
211
212 if (m_Cache != null)
213 asset = m_Cache.Get(id);
209 214
210 if (asset != null) 215 if (asset != null)
211 return asset.Data; 216 return asset.Data;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs
index 8a22cfc..e6eeacf 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/RemoteAssetServiceConnector.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using log4net; 28using log4net;
29using Mono.Addins;
29using System; 30using System;
30using System.Collections.Generic; 31using System.Collections.Generic;
31using System.Reflection; 32using System.Reflection;
@@ -38,6 +39,7 @@ using OpenSim.Services.Interfaces;
38 39
39namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset 40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
40{ 41{
42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteAssetServicesConnector")]
41 public class RemoteAssetServicesConnector : 43 public class RemoteAssetServicesConnector :
42 AssetServicesConnector, ISharedRegionModule, IAssetService 44 AssetServicesConnector, ISharedRegionModule, IAssetService
43 { 45 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
new file mode 100644
index 0000000..1982473
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
@@ -0,0 +1,136 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Threading;
33using log4net.Config;
34using Nini.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset;
40using OpenSim.Tests.Common;
41
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
43{
44 [TestFixture]
45 public class AssetConnectorsTests : OpenSimTestCase
46 {
47 [Test]
48 public void TestAddAsset()
49 {
50 TestHelpers.InMethod();
51// TestHelpers.EnableLogging();
52
53 IConfigSource config = new IniConfigSource();
54 config.AddConfig("Modules");
55 config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
56 config.AddConfig("AssetService");
57 config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
58 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
59
60 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
61 lasc.Initialise(config);
62
63 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
64 lasc.Store(a1);
65
66 AssetBase retreivedA1 = lasc.Get(a1.ID);
67 Assert.That(retreivedA1.ID, Is.EqualTo(a1.ID));
68 Assert.That(retreivedA1.Metadata.ID, Is.EqualTo(a1.Metadata.ID));
69 Assert.That(retreivedA1.Data.Length, Is.EqualTo(a1.Data.Length));
70
71 AssetMetadata retrievedA1Metadata = lasc.GetMetadata(a1.ID);
72 Assert.That(retrievedA1Metadata.ID, Is.EqualTo(a1.ID));
73
74 byte[] retrievedA1Data = lasc.GetData(a1.ID);
75 Assert.That(retrievedA1Data.Length, Is.EqualTo(a1.Data.Length));
76
77 // TODO: Add cache and check that this does receive a copy of the asset
78 }
79
80 [Test]
81 public void TestAddTemporaryAsset()
82 {
83 TestHelpers.InMethod();
84// TestHelpers.EnableLogging();
85
86 IConfigSource config = new IniConfigSource();
87 config.AddConfig("Modules");
88 config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
89 config.AddConfig("AssetService");
90 config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
91 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
92
93 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
94 lasc.Initialise(config);
95
96 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
97 a1.Temporary = true;
98
99 lasc.Store(a1);
100
101 Assert.That(lasc.Get(a1.ID), Is.Null);
102 Assert.That(lasc.GetData(a1.ID), Is.Null);
103 Assert.That(lasc.GetMetadata(a1.ID), Is.Null);
104
105 // TODO: Add cache and check that this does receive a copy of the asset
106 }
107
108 [Test]
109 public void TestAddLocalAsset()
110 {
111 TestHelpers.InMethod();
112// TestHelpers.EnableLogging();
113
114 IConfigSource config = new IniConfigSource();
115 config.AddConfig("Modules");
116 config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
117 config.AddConfig("AssetService");
118 config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
119 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
120
121 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
122 lasc.Initialise(config);
123
124 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
125 a1.Local = true;
126
127 lasc.Store(a1);
128
129 Assert.That(lasc.Get(a1.ID), Is.Null);
130 Assert.That(lasc.GetData(a1.ID), Is.Null);
131 Assert.That(lasc.GetMetadata(a1.ID), Is.Null);
132
133 // TODO: Add cache and check that this does receive a copy of the asset
134 }
135 }
136} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
index d809ac2..f027810 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
@@ -39,6 +40,7 @@ using OpenMetaverse;
39 40
40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalAuthenticationServicesConnector")]
42 public class LocalAuthenticationServicesConnector : ISharedRegionModule, IAuthenticationService 44 public class LocalAuthenticationServicesConnector : ISharedRegionModule, IAuthenticationService
43 { 45 {
44 private static readonly ILog m_log = 46 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/RemoteAuthenticationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/RemoteAuthenticationServiceConnector.cs
index a053bc2..7cb8b22 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/RemoteAuthenticationServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/RemoteAuthenticationServiceConnector.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using Nini.Config; 29using Nini.Config;
30using log4net; 30using log4net;
31using Mono.Addins;
31using System.Reflection; 32using System.Reflection;
32using OpenSim.Region.Framework.Interfaces; 33using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
@@ -36,6 +37,7 @@ using OpenSim.Services.Connectors;
36 37
37namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication 38namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication
38{ 39{
40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteAuthenticationServicesConnector")]
39 public class RemoteAuthenticationServicesConnector : AuthenticationServicesConnector, 41 public class RemoteAuthenticationServicesConnector : AuthenticationServicesConnector,
40 ISharedRegionModule, IAuthenticationService 42 ISharedRegionModule, IAuthenticationService
41 { 43 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/LocalAuthorizationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/LocalAuthorizationServiceConnector.cs
index 267fb9e..1acb695 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/LocalAuthorizationServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/LocalAuthorizationServiceConnector.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using log4net; 28using log4net;
29using Mono.Addins;
29using Nini.Config; 30using Nini.Config;
30using System; 31using System;
31using System.Collections.Generic; 32using System.Collections.Generic;
@@ -39,6 +40,7 @@ using OpenMetaverse;
39 40
40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalAuthorizationServicesConnector")]
42 public class LocalAuthorizationServicesConnector : INonSharedRegionModule, IAuthorizationService 44 public class LocalAuthorizationServicesConnector : INonSharedRegionModule, IAuthorizationService
43 { 45 {
44 private static readonly ILog m_log = 46 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs
index 86c0099..b8d409d 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using log4net; 28using log4net;
29using Mono.Addins;
29using System; 30using System;
30using System.Collections.Generic; 31using System.Collections.Generic;
31using System.Reflection; 32using System.Reflection;
@@ -39,6 +40,7 @@ using OpenMetaverse;
39 40
40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteAuthorizationServicesConnector")]
42 public class RemoteAuthorizationServicesConnector : 44 public class RemoteAuthorizationServicesConnector :
43 AuthorizationServicesConnector, ISharedRegionModule, IAuthorizationService 45 AuthorizationServicesConnector, ISharedRegionModule, IAuthorizationService
44 { 46 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs
index 9ee19f8..c3ef588 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/LocalAvatarServiceConnector.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
@@ -40,6 +41,7 @@ using OpenMetaverse;
40 41
41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar 42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar
42{ 43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalAvatarServicesConnector")]
43 public class LocalAvatarServicesConnector : ISharedRegionModule, IAvatarService 45 public class LocalAvatarServicesConnector : ISharedRegionModule, IAvatarService
44 { 46 {
45 private static readonly ILog m_log = 47 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/RemoteAvatarServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/RemoteAvatarServiceConnector.cs
index d665a54..a087aea 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/RemoteAvatarServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Avatar/RemoteAvatarServiceConnector.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using Mono.Addins;
29using Nini.Config; 30using Nini.Config;
30using log4net; 31using log4net;
31using System.Reflection; 32using System.Reflection;
@@ -36,6 +37,7 @@ using OpenSim.Services.Connectors;
36 37
37namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar 38namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar
38{ 39{
40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteAvatarServicesConnector")]
39 public class RemoteAvatarServicesConnector : AvatarServicesConnector, 41 public class RemoteAvatarServicesConnector : AvatarServicesConnector,
40 ISharedRegionModule, IAvatarService 42 ISharedRegionModule, IAvatarService
41 { 43 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index 3c6e381..c0c2ca7 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using log4net; 28using log4net;
29using Mono.Addins;
29using Nini.Config; 30using Nini.Config;
30using System; 31using System;
31using System.Collections.Generic; 32using System.Collections.Generic;
@@ -41,6 +42,7 @@ using OpenMetaverse;
41 42
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid 43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
43{ 44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalGridServicesConnector")]
44 public class LocalGridServicesConnector : ISharedRegionModule, IGridService 46 public class LocalGridServicesConnector : ISharedRegionModule, IGridService
45 { 47 {
46 private static readonly ILog m_log = 48 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
index e6c89d7..b2646ba 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using log4net; 28using log4net;
29using Mono.Addins;
29using System; 30using System;
30using System.Collections.Generic; 31using System.Collections.Generic;
31using System.Reflection; 32using System.Reflection;
@@ -42,6 +43,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
42 43
43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid 44namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
44{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteGridServicesConnector")]
45 public class RemoteGridServicesConnector : ISharedRegionModule, IGridService 47 public class RemoteGridServicesConnector : ISharedRegionModule, IGridService
46 { 48 {
47 private static readonly ILog m_log = 49 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
index b286d17..4338133 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
@@ -43,11 +43,15 @@ using OpenSim.Tests.Common;
43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests 43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
44{ 44{
45 [TestFixture] 45 [TestFixture]
46 public class GridConnectorsTests 46 public class GridConnectorsTests : OpenSimTestCase
47 { 47 {
48 LocalGridServicesConnector m_LocalConnector; 48 LocalGridServicesConnector m_LocalConnector;
49 private void SetUp() 49
50 [SetUp]
51 public override void SetUp()
50 { 52 {
53 base.SetUp();
54
51 IConfigSource config = new IniConfigSource(); 55 IConfigSource config = new IniConfigSource();
52 config.AddConfig("Modules"); 56 config.AddConfig("Modules");
53 config.AddConfig("GridService"); 57 config.AddConfig("GridService");
@@ -71,8 +75,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
71 TestHelpers.InMethod(); 75 TestHelpers.InMethod();
72// log4net.Config.XmlConfigurator.Configure(); 76// log4net.Config.XmlConfigurator.Configure();
73 77
74 SetUp();
75
76 // Create 4 regions 78 // Create 4 regions
77 GridRegion r1 = new GridRegion(); 79 GridRegion r1 = new GridRegion();
78 r1.RegionName = "Test Region 1"; 80 r1.RegionName = "Test Region 1";
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
index b0edce7..221f815 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
@@ -65,11 +65,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
65 65
66 public void OnMakeRootAgent(ScenePresence sp) 66 public void OnMakeRootAgent(ScenePresence sp)
67 { 67 {
68// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName);
69
70 if (sp.PresenceType != PresenceType.Npc) 68 if (sp.PresenceType != PresenceType.Npc)
69 {
70 string userid = sp.Scene.UserManagementModule.GetUserUUI(sp.UUID);
71 //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", userid, sp.Scene.RegionInfo.RegionName);
71 m_GridUserService.SetLastPosition( 72 m_GridUserService.SetLastPosition(
72 sp.UUID.ToString(), UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); 73 userid, UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
74 }
73 } 75 }
74 76
75 public void OnNewClient(IClientAPI client) 77 public void OnNewClient(IClientAPI client)
@@ -82,9 +84,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
82 if (client.SceneAgent.IsChildAgent) 84 if (client.SceneAgent.IsChildAgent)
83 return; 85 return;
84 86
85// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); 87 string userId = client.AgentId.ToString();
88 if (client.Scene is Scene)
89 {
90 Scene s = (Scene)client.Scene;
91 userId = s.UserManagementModule.GetUserUUI(client.AgentId);
92 }
93 //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", userId, client.Scene.RegionInfo.RegionName);
94
86 m_GridUserService.LoggedOut( 95 m_GridUserService.LoggedOut(
87 client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID, 96 userId, client.SessionId, client.Scene.RegionInfo.RegionID,
88 client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat); 97 client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat);
89 } 98 }
90 } 99 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs
index 90fe69e..5734334 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
@@ -39,6 +40,7 @@ using OpenMetaverse;
39 40
40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalGridUserServicesConnector")]
42 public class LocalGridUserServicesConnector : ISharedRegionModule, IGridUserService 44 public class LocalGridUserServicesConnector : ISharedRegionModule, IGridUserService
43 { 45 {
44 private static readonly ILog m_log = 46 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
index badb552..f7e6eb8 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
@@ -36,14 +36,19 @@ using OpenSim.Services.Connectors;
36 36
37using OpenMetaverse; 37using OpenMetaverse;
38using log4net; 38using log4net;
39using Mono.Addins;
39using Nini.Config; 40using Nini.Config;
40 41
41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser 42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
42{ 43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteGridUserServicesConnector")]
43 public class RemoteGridUserServicesConnector : ISharedRegionModule, IGridUserService 45 public class RemoteGridUserServicesConnector : ISharedRegionModule, IGridUserService
44 { 46 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 48
49 private const int KEEPTIME = 30; // 30 secs
50 private ExpiringCache<string, GridUserInfo> m_Infos = new ExpiringCache<string, GridUserInfo>();
51
47 #region ISharedRegionModule 52 #region ISharedRegionModule
48 53
49 private bool m_Enabled = false; 54 private bool m_Enabled = false;
@@ -128,23 +133,60 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
128 133
129 public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat) 134 public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat)
130 { 135 {
136 if (m_Infos.Contains(userID))
137 m_Infos.Remove(userID);
138
131 return m_RemoteConnector.LoggedOut(userID, sessionID, region, position, lookat); 139 return m_RemoteConnector.LoggedOut(userID, sessionID, region, position, lookat);
132 } 140 }
133 141
134 142
135 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) 143 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
136 { 144 {
137 return m_RemoteConnector.SetHome(userID, regionID, position, lookAt); 145 if (m_RemoteConnector.SetHome(userID, regionID, position, lookAt))
146 {
147 // Update the cache too
148 GridUserInfo info = null;
149 if (m_Infos.TryGetValue(userID, out info))
150 {
151 info.HomeRegionID = regionID;
152 info.HomePosition = position;
153 info.HomeLookAt = lookAt;
154 }
155 return true;
156 }
157
158 return false;
138 } 159 }
139 160
140 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) 161 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
141 { 162 {
142 return m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt); 163 if (m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt))
164 {
165 // Update the cache too
166 GridUserInfo info = null;
167 if (m_Infos.TryGetValue(userID, out info))
168 {
169 info.LastRegionID = regionID;
170 info.LastPosition = position;
171 info.LastLookAt = lookAt;
172 }
173 return true;
174 }
175
176 return false;
143 } 177 }
144 178
145 public GridUserInfo GetGridUserInfo(string userID) 179 public GridUserInfo GetGridUserInfo(string userID)
146 { 180 {
147 return m_RemoteConnector.GetGridUserInfo(userID); 181 GridUserInfo info = null;
182 if (m_Infos.TryGetValue(userID, out info))
183 return info;
184
185 info = m_RemoteConnector.GetGridUserInfo(userID);
186
187 m_Infos.AddOrUpdate(userID, info, KEEPTIME);
188
189 return info;
148 } 190 }
149 191
150 public GridUserInfo[] GetGridUserInfo(string[] userID) 192 public GridUserInfo[] GetGridUserInfo(string[] userID)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
index cf6d2f7..e474ef6 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using log4net; 28using log4net;
29using Mono.Addins;
29using Nini.Config; 30using Nini.Config;
30using System; 31using System;
31using System.Collections.Generic; 32using System.Collections.Generic;
@@ -42,6 +43,7 @@ using OpenMetaverse;
42 43
43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory 44namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
44{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "HGInventoryBroker")]
45 public class HGInventoryBroker : ISharedRegionModule, IInventoryService 47 public class HGInventoryBroker : ISharedRegionModule, IInventoryService
46 { 48 {
47 private static readonly ILog m_log = 49 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
index 097ff1a..ec5751d 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using log4net; 28using log4net;
29using Mono.Addins;
29using Nini.Config; 30using Nini.Config;
30 31
31using System; 32using System;
@@ -41,6 +42,7 @@ using OpenMetaverse;
41 42
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory 43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
43{ 44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalInventoryServicesConnector")]
44 public class LocalInventoryServicesConnector : ISharedRegionModule, IInventoryService 46 public class LocalInventoryServicesConnector : ISharedRegionModule, IInventoryService
45 { 47 {
46 private static readonly ILog m_log = 48 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
index 11e0150..2d3ba82 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
@@ -29,6 +29,7 @@ using log4net;
29using System; 29using System;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Monitoring; 35using OpenSim.Framework.Monitoring;
@@ -40,6 +41,7 @@ using OpenMetaverse;
40 41
41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory 42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
42{ 43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteXInventoryServicesConnector")]
43 public class RemoteXInventoryServicesConnector : ISharedRegionModule, IInventoryService 45 public class RemoteXInventoryServicesConnector : ISharedRegionModule, IInventoryService
44 { 46 {
45 private static readonly ILog m_log = 47 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs
index 86c0b85..5329933 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using log4net; 28using log4net;
29using Mono.Addins;
29using Nini.Config; 30using Nini.Config;
30using System; 31using System;
31using System.Collections.Generic; 32using System.Collections.Generic;
@@ -39,8 +40,8 @@ using OpenMetaverse;
39 40
40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land
41{ 42{
42 public class LocalLandServicesConnector : 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalLandServicesConnector")]
43 ISharedRegionModule, ILandService 44 public class LocalLandServicesConnector : ISharedRegionModule, ILandService
44 { 45 {
45 private static readonly ILog m_log = 46 private static readonly ILog m_log =
46 LogManager.GetLogger( 47 LogManager.GetLogger(
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs
index 766ef81..77dfa4a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using log4net; 28using log4net;
29using Mono.Addins;
29using System; 30using System;
30using System.Collections.Generic; 31using System.Collections.Generic;
31using System.Reflection; 32using System.Reflection;
@@ -41,6 +42,7 @@ using OpenMetaverse;
41 42
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land 43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land
43{ 44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteLandServicesConnector")]
44 public class RemoteLandServicesConnector : 46 public class RemoteLandServicesConnector :
45 LandServicesConnector, ISharedRegionModule, ILandService 47 LandServicesConnector, ISharedRegionModule, ILandService
46 { 48 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
index e4c6c1a..5836eb9 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
@@ -52,7 +52,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
52 /// <remarks> 52 /// <remarks>
53 /// </remarks> 53 /// </remarks>
54 54
55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MapImageServiceModule")]
56 public class MapImageServiceModule : ISharedRegionModule 56 public class MapImageServiceModule : ISharedRegionModule
57 { 57 {
58 private static readonly ILog m_log = 58 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
index 7a90686..fd89428 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
@@ -39,6 +40,7 @@ using OpenSim.Services.Interfaces;
39 40
40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalNeighbourServicesConnector")]
42 public class LocalNeighbourServicesConnector : 44 public class LocalNeighbourServicesConnector :
43 ISharedRegionModule, INeighbourService 45 ISharedRegionModule, INeighbourService
44 { 46 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/RemoteNeighourServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/RemoteNeighourServiceConnector.cs
index c6fc2a1..e6772f3 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/RemoteNeighourServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/RemoteNeighourServiceConnector.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using log4net; 28using log4net;
29using Mono.Addins;
29using System; 30using System;
30using System.Collections.Generic; 31using System.Collections.Generic;
31using System.Reflection; 32using System.Reflection;
@@ -39,6 +40,7 @@ using OpenSim.Server.Base;
39 40
40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteNeighbourServicesConnector")]
42 public class RemoteNeighbourServicesConnector : 44 public class RemoteNeighbourServicesConnector :
43 NeighbourServicesConnector, ISharedRegionModule, INeighbourService 45 NeighbourServicesConnector, ISharedRegionModule, INeighbourService
44 { 46 {
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs
new file mode 100644
index 0000000..fdbe10a
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.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 copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using OpenMetaverse;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Server.Base;
38using OpenSim.Services.Interfaces;
39using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
40
41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
42{
43 public class BasePresenceServiceConnector : IPresenceService
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 protected bool m_Enabled;
48
49 protected PresenceDetector m_PresenceDetector;
50
51 /// <summary>
52 /// Underlying presence service. Do not use directly.
53 /// </summary>
54 public IPresenceService m_PresenceService;
55
56 public Type ReplaceableInterface
57 {
58 get { return null; }
59 }
60
61 public void AddRegion(Scene scene)
62 {
63 if (!m_Enabled)
64 return;
65
66 // m_log.DebugFormat(
67 // "[LOCAL PRESENCE CONNECTOR]: Registering IPresenceService to scene {0}", scene.RegionInfo.RegionName);
68
69 scene.RegisterModuleInterface<IPresenceService>(this);
70 m_PresenceDetector.AddRegion(scene);
71
72 m_log.InfoFormat("[BASE PRESENCE SERVICE CONNECTOR]: Enabled for region {0}", scene.Name);
73 }
74
75 public void RemoveRegion(Scene scene)
76 {
77 if (!m_Enabled)
78 return;
79
80 m_PresenceDetector.RemoveRegion(scene);
81 }
82
83 public void RegionLoaded(Scene scene)
84 {
85 if (!m_Enabled)
86 return;
87
88 }
89
90 public void PostInitialise()
91 {
92 }
93
94 public void Close()
95 {
96 }
97
98 #region IPresenceService
99
100 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
101 {
102 m_log.Warn("[BASE PRESENCE SERVICE CONNECTOR]: LoginAgent connector not implemented at the simulators");
103 return false;
104 }
105
106 public bool LogoutAgent(UUID sessionID)
107 {
108 return m_PresenceService.LogoutAgent(sessionID);
109 }
110
111 public bool LogoutRegionAgents(UUID regionID)
112 {
113 return m_PresenceService.LogoutRegionAgents(regionID);
114 }
115
116 public bool ReportAgent(UUID sessionID, UUID regionID)
117 {
118 return m_PresenceService.ReportAgent(sessionID, regionID);
119 }
120
121 public PresenceInfo GetAgent(UUID sessionID)
122 {
123 return m_PresenceService.GetAgent(sessionID);
124 }
125
126 public PresenceInfo[] GetAgents(string[] userIDs)
127 {
128 // Don't bother potentially making a useless network call if we not going to ask for any users anyway.
129 if (userIDs.Length == 0)
130 return new PresenceInfo[0];
131
132 return m_PresenceService.GetAgents(userIDs);
133 }
134
135 #endregion
136 }
137} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs
index 49dd633..db5c520 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs
@@ -24,51 +24,29 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27
27using System; 28using System;
28using System.Collections.Generic; 29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
30 31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using OpenMetaverse;
31using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
32using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
33using OpenSim.Server.Base; 37using OpenSim.Server.Base;
34using OpenSim.Services.Interfaces; 38using OpenSim.Services.Interfaces;
35using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; 39using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
36 40
37using OpenMetaverse;
38using log4net;
39using Nini.Config;
40
41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
42{ 42{
43 public class LocalPresenceServicesConnector : ISharedRegionModule, IPresenceService 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalPresenceServicesConnector")]
44 public class LocalPresenceServicesConnector : BasePresenceServiceConnector, ISharedRegionModule, IPresenceService
44 { 45 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 47
47 private bool m_Enabled = false;
48
49 private PresenceDetector m_PresenceDetector;
50
51 /// <summary>
52 /// Underlying presence service. Do not use directly.
53 /// </summary>
54 public IPresenceService m_PresenceService;
55
56 public LocalPresenceServicesConnector()
57 {
58 }
59
60 public LocalPresenceServicesConnector(IConfigSource source)
61 {
62 Initialise(source);
63 }
64
65 #region ISharedRegionModule 48 #region ISharedRegionModule
66 49
67 public Type ReplaceableInterface
68 {
69 get { return null; }
70 }
71
72 public string Name 50 public string Name
73 { 51 {
74 get { return "LocalPresenceServicesConnector"; } 52 get { return "LocalPresenceServicesConnector"; }
@@ -119,81 +97,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
119 } 97 }
120 } 98 }
121 99
122 public void PostInitialise()
123 {
124 }
125
126 public void Close()
127 {
128 }
129
130 public void AddRegion(Scene scene)
131 {
132 if (!m_Enabled)
133 return;
134
135 // m_log.DebugFormat(
136 // "[LOCAL PRESENCE CONNECTOR]: Registering IPresenceService to scene {0}", scene.RegionInfo.RegionName);
137
138 scene.RegisterModuleInterface<IPresenceService>(this);
139 m_PresenceDetector.AddRegion(scene);
140
141 m_log.InfoFormat("[LOCAL PRESENCE CONNECTOR]: Enabled local presence for region {0}", scene.RegionInfo.RegionName);
142
143 }
144
145 public void RemoveRegion(Scene scene)
146 {
147 if (!m_Enabled)
148 return;
149
150 m_PresenceDetector.RemoveRegion(scene);
151 }
152
153 public void RegionLoaded(Scene scene)
154 {
155 if (!m_Enabled)
156 return;
157
158 }
159
160 #endregion
161
162 #region IPresenceService
163
164 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
165 {
166 m_log.Warn("[LOCAL PRESENCE CONNECTOR]: LoginAgent connector not implemented at the simulators");
167 return false;
168 }
169
170 public bool LogoutAgent(UUID sessionID)
171 {
172 return m_PresenceService.LogoutAgent(sessionID);
173 }
174
175
176 public bool LogoutRegionAgents(UUID regionID)
177 {
178 return m_PresenceService.LogoutRegionAgents(regionID);
179 }
180
181 public bool ReportAgent(UUID sessionID, UUID regionID)
182 {
183 return m_PresenceService.ReportAgent(sessionID, regionID);
184 }
185
186 public PresenceInfo GetAgent(UUID sessionID)
187 {
188 return m_PresenceService.GetAgent(sessionID);
189 }
190
191 public PresenceInfo[] GetAgents(string[] userIDs)
192 {
193 return m_PresenceService.GetAgents(userIDs);
194 }
195
196 #endregion 100 #endregion
197
198 } 101 }
199} 102} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs
index bf4e9ab..6ca5c28 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs
@@ -37,26 +37,18 @@ using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
37 37
38using OpenMetaverse; 38using OpenMetaverse;
39using log4net; 39using log4net;
40using Mono.Addins;
40using Nini.Config; 41using Nini.Config;
41 42
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence 43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
43{ 44{
44 public class RemotePresenceServicesConnector : ISharedRegionModule, IPresenceService 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemotePresenceServicesConnector")]
46 public class RemotePresenceServicesConnector : BasePresenceServiceConnector, ISharedRegionModule
45 { 47 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 49
48 #region ISharedRegionModule 50 #region ISharedRegionModule
49 51
50 private bool m_Enabled = false;
51
52 private PresenceDetector m_PresenceDetector;
53 private IPresenceService m_RemoteConnector;
54
55 public Type ReplaceableInterface
56 {
57 get { return null; }
58 }
59
60 public string Name 52 public string Name
61 { 53 {
62 get { return "RemotePresenceServicesConnector"; } 54 get { return "RemotePresenceServicesConnector"; }
@@ -70,7 +62,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
70 string name = moduleConfig.GetString("PresenceServices", ""); 62 string name = moduleConfig.GetString("PresenceServices", "");
71 if (name == Name) 63 if (name == Name)
72 { 64 {
73 m_RemoteConnector = new PresenceServicesConnector(source); 65 m_PresenceService = new PresenceServicesConnector(source);
74 66
75 m_Enabled = true; 67 m_Enabled = true;
76 68
@@ -79,81 +71,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
79 m_log.Info("[REMOTE PRESENCE CONNECTOR]: Remote presence enabled"); 71 m_log.Info("[REMOTE PRESENCE CONNECTOR]: Remote presence enabled");
80 } 72 }
81 } 73 }
82
83 }
84
85 public void PostInitialise()
86 {
87 }
88
89 public void Close()
90 {
91 }
92
93 public void AddRegion(Scene scene)
94 {
95 if (!m_Enabled)
96 return;
97
98 scene.RegisterModuleInterface<IPresenceService>(this);
99 m_PresenceDetector.AddRegion(scene);
100
101 m_log.InfoFormat("[REMOTE PRESENCE CONNECTOR]: Enabled remote presence for region {0}", scene.RegionInfo.RegionName);
102
103 }
104
105 public void RemoveRegion(Scene scene)
106 {
107 if (!m_Enabled)
108 return;
109
110 m_PresenceDetector.RemoveRegion(scene);
111 }
112
113 public void RegionLoaded(Scene scene)
114 {
115 if (!m_Enabled)
116 return;
117
118 }
119
120 #endregion
121
122 #region IPresenceService
123
124 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
125 {
126 m_log.Warn("[REMOTE PRESENCE CONNECTOR]: LoginAgent connector not implemented at the simulators");
127 return false;
128 }
129
130 public bool LogoutAgent(UUID sessionID)
131 {
132 return m_RemoteConnector.LogoutAgent(sessionID);
133 }
134
135
136 public bool LogoutRegionAgents(UUID regionID)
137 {
138 return m_RemoteConnector.LogoutRegionAgents(regionID);
139 }
140
141 public bool ReportAgent(UUID sessionID, UUID regionID)
142 {
143 return m_RemoteConnector.ReportAgent(sessionID, regionID);
144 }
145
146 public PresenceInfo GetAgent(UUID sessionID)
147 {
148 return m_RemoteConnector.GetAgent(sessionID);
149 }
150
151 public PresenceInfo[] GetAgents(string[] userIDs)
152 {
153 return m_RemoteConnector.GetAgents(userIDs);
154 } 74 }
155 75
156 #endregion 76 #endregion
157
158 } 77 }
159} 78} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
index 4556df3..32e47f9 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
@@ -56,7 +56,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests
56 config.Configs["PresenceService"].Set("LocalServiceModule", "OpenSim.Services.PresenceService.dll:PresenceService"); 56 config.Configs["PresenceService"].Set("LocalServiceModule", "OpenSim.Services.PresenceService.dll:PresenceService");
57 config.Configs["PresenceService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); 57 config.Configs["PresenceService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
58 58
59 m_LocalConnector = new LocalPresenceServicesConnector(config); 59 m_LocalConnector = new LocalPresenceServicesConnector();
60 m_LocalConnector.Initialise(config);
60 61
61 // Let's stick in a test presence 62 // Let's stick in a test presence
62 m_LocalConnector.m_PresenceService.LoginAgent(UUID.Zero.ToString(), UUID.Zero, UUID.Zero); 63 m_LocalConnector.m_PresenceService.LoginAgent(UUID.Zero.ToString(), UUID.Zero, UUID.Zero);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 6eb99ea..b485194 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -29,6 +29,7 @@ using System.Collections.Generic;
29using System.Linq; 29using System.Linq;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
@@ -39,6 +40,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39 40
40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalSimulationConnectorModule")]
42 public class LocalSimulationConnectorModule : ISharedRegionModule, ISimulationService 44 public class LocalSimulationConnectorModule : ISharedRegionModule, ISimulationService
43 { 45 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -58,7 +60,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
58 /// </summary> 60 /// </summary>
59 private bool m_ModuleEnabled = false; 61 private bool m_ModuleEnabled = false;
60 62
61 #region IRegionModule 63 #region Region Module interface
62 64
63 public void Initialise(IConfigSource config) 65 public void Initialise(IConfigSource config)
64 { 66 {
@@ -156,7 +158,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
156 } 158 }
157 } 159 }
158 160
159 #endregion /* IRegionModule */ 161 #endregion
160 162
161 #region ISimulation 163 #region ISimulation
162 164
@@ -313,7 +315,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
313 315
314 if (m_scenes.ContainsKey(destination.RegionID)) 316 if (m_scenes.ContainsKey(destination.RegionID))
315 { 317 {
316 Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); }); 318// m_log.DebugFormat(
319// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
320// s.RegionInfo.RegionName, destination.RegionHandle);
321
322 Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); });
317 return true; 323 return true;
318 } 324 }
319 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 325 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index 68be552..c8698ca 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -32,6 +32,7 @@ using System.Net;
32using System.Reflection; 32using System.Reflection;
33using System.Text; 33using System.Text;
34using log4net; 34using log4net;
35using Mono.Addins;
35using Nini.Config; 36using Nini.Config;
36using OpenMetaverse; 37using OpenMetaverse;
37using OpenMetaverse.StructuredData; 38using OpenMetaverse.StructuredData;
@@ -46,6 +47,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
46 47
47namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation 48namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
48{ 49{
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteSimulationConnectorModule")]
49 public class RemoteSimulationConnectorModule : ISharedRegionModule, ISimulationService 51 public class RemoteSimulationConnectorModule : ISharedRegionModule, ISimulationService
50 { 52 {
51 private bool initialized = false; 53 private bool initialized = false;
@@ -60,7 +62,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
60 protected bool m_safemode; 62 protected bool m_safemode;
61 protected IPAddress m_thisIP; 63 protected IPAddress m_thisIP;
62 64
63 #region IRegionModule 65 #region Region Module interface
64 66
65 public virtual void Initialise(IConfigSource config) 67 public virtual void Initialise(IConfigSource config)
66 { 68 {
@@ -147,7 +149,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
147 m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName); 149 m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName);
148 } 150 }
149 151
150 #endregion /* IRegionModule */ 152 #endregion
151 153
152 #region IInterregionComms 154 #region IInterregionComms
153 155
@@ -317,4 +319,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
317 319
318 #endregion /* IInterregionComms */ 320 #endregion /* IInterregionComms */
319 } 321 }
320} \ No newline at end of file 322}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
index 1ffd480..ea4ade5 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
@@ -39,6 +40,7 @@ using OpenMetaverse;
39 40
40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalUserAccountServicesConnector")]
42 public class LocalUserAccountServicesConnector : ISharedRegionModule, IUserAccountService 44 public class LocalUserAccountServicesConnector : ISharedRegionModule, IUserAccountService
43 { 45 {
44 private static readonly ILog m_log = 46 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
index f6b6aeb..afbba30 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using Nini.Config; 29using Nini.Config;
30using log4net; 30using log4net;
31using Mono.Addins;
31using System.Reflection; 32using System.Reflection;
32using OpenSim.Region.Framework.Interfaces; 33using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
@@ -39,6 +40,7 @@ using OpenMetaverse;
39 40
40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteUserAccountServicesConnector")]
42 public class RemoteUserAccountServicesConnector : UserAccountServicesConnector, 44 public class RemoteUserAccountServicesConnector : UserAccountServicesConnector,
43 ISharedRegionModule, IUserAccountService 45 ISharedRegionModule, IUserAccountService
44 { 46 {
diff --git a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
index e7b1454..1599f15 100644
--- a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
+++ b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
@@ -39,6 +40,7 @@ using OpenSim.Services.Interfaces;
39 40
40namespace OpenSim.Region.CoreModules.World 41namespace OpenSim.Region.CoreModules.World
41{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AccessModule")]
42 public class AccessModule : ISharedRegionModule 44 public class AccessModule : ISharedRegionModule
43 { 45 {
44// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index 619550c..ade5e76 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -43,6 +43,7 @@ using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.Framework.Scenes.Serialization; 44using OpenSim.Region.Framework.Scenes.Serialization;
45using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
46using System.Threading;
46 47
47namespace OpenSim.Region.CoreModules.World.Archiver 48namespace OpenSim.Region.CoreModules.World.Archiver
48{ 49{
@@ -52,7 +53,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver
52 public class ArchiveReadRequest 53 public class ArchiveReadRequest
53 { 54 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 /// <summary>
58 /// Contains data used while dearchiving a single scene.
59 /// </summary>
60 private class DearchiveContext
61 {
62 public Scene Scene { get; set; }
63
64 public List<string> SerialisedSceneObjects { get; set; }
65
66 public List<string> SerialisedParcels { get; set; }
67
68 public List<SceneObjectGroup> SceneObjects { get; set; }
69
70 public DearchiveContext(Scene scene)
71 {
72 Scene = scene;
73 SerialisedSceneObjects = new List<string>();
74 SerialisedParcels = new List<string>();
75 SceneObjects = new List<SceneObjectGroup>();
76 }
77 }
55 78
79
56 /// <summary> 80 /// <summary>
57 /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version 81 /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version
58 /// bumps here should be compatible. 82 /// bumps here should be compatible.
@@ -62,9 +86,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
62 /// <summary> 86 /// <summary>
63 /// Has the control file been loaded for this archive? 87 /// Has the control file been loaded for this archive?
64 /// </summary> 88 /// </summary>
65 public bool ControlFileLoaded { get; private set; } 89 public bool ControlFileLoaded { get; private set; }
66 90
67 protected Scene m_scene; 91 protected string m_loadPath;
92 protected Scene m_rootScene;
68 protected Stream m_loadStream; 93 protected Stream m_loadStream;
69 protected Guid m_requestId; 94 protected Guid m_requestId;
70 protected string m_errorMessage; 95 protected string m_errorMessage;
@@ -91,16 +116,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver
91 { 116 {
92 if (m_UserMan == null) 117 if (m_UserMan == null)
93 { 118 {
94 m_UserMan = m_scene.RequestModuleInterface<IUserManagement>(); 119 m_UserMan = m_rootScene.RequestModuleInterface<IUserManagement>();
95 } 120 }
96 return m_UserMan; 121 return m_UserMan;
97 } 122 }
98 } 123 }
99 124
125 /// <summary>
126 /// Used to cache lookups for valid groups.
127 /// </summary>
128 private IDictionary<UUID, bool> m_validGroupUuids = new Dictionary<UUID, bool>();
129
130 private IGroupsModule m_groupsModule;
131
132 private IAssetService m_assetService = null;
133
134
100 public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) 135 public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId)
101 { 136 {
102 m_scene = scene; 137 m_rootScene = scene;
103 138
139 m_loadPath = loadPath;
104 try 140 try
105 { 141 {
106 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress); 142 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress);
@@ -120,11 +156,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
120 156
121 // Zero can never be a valid user id 157 // Zero can never be a valid user id
122 m_validUserUuids[UUID.Zero] = false; 158 m_validUserUuids[UUID.Zero] = false;
159
160 m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
161 m_assetService = m_rootScene.AssetService;
123 } 162 }
124 163
125 public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) 164 public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId)
126 { 165 {
127 m_scene = scene; 166 m_rootScene = scene;
167 m_loadPath = null;
128 m_loadStream = loadStream; 168 m_loadStream = loadStream;
129 m_merge = merge; 169 m_merge = merge;
130 m_skipAssets = skipAssets; 170 m_skipAssets = skipAssets;
@@ -132,6 +172,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
132 172
133 // Zero can never be a valid user id 173 // Zero can never be a valid user id
134 m_validUserUuids[UUID.Zero] = false; 174 m_validUserUuids[UUID.Zero] = false;
175
176 m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
177 m_assetService = m_rootScene.AssetService;
135 } 178 }
136 179
137 /// <summary> 180 /// <summary>
@@ -139,25 +182,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver
139 /// </summary> 182 /// </summary>
140 public void DearchiveRegion() 183 public void DearchiveRegion()
141 { 184 {
142 // The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions
143 DearchiveRegion0DotStar();
144 }
145
146 private void DearchiveRegion0DotStar()
147 {
148 int successfulAssetRestores = 0; 185 int successfulAssetRestores = 0;
149 int failedAssetRestores = 0; 186 int failedAssetRestores = 0;
150 List<string> serialisedSceneObjects = new List<string>();
151 List<string> serialisedParcels = new List<string>();
152 string filePath = "NONE";
153 187
154 TarArchiveReader archive = new TarArchiveReader(m_loadStream); 188 DearchiveScenesInfo dearchivedScenes;
189
190 // We dearchive all the scenes at once, because the files in the TAR archive might be mixed.
191 // Therefore, we have to keep track of the dearchive context of all the scenes.
192 Dictionary<UUID, DearchiveContext> sceneContexts = new Dictionary<UUID, DearchiveContext>();
193
194 string fullPath = "NONE";
195 TarArchiveReader archive = null;
155 byte[] data; 196 byte[] data;
156 TarArchiveReader.TarEntryType entryType; 197 TarArchiveReader.TarEntryType entryType;
157 198
158 try 199 try
159 { 200 {
160 while ((data = archive.ReadEntry(out filePath, out entryType)) != null) 201 FindAndLoadControlFile(out archive, out dearchivedScenes);
202
203 while ((data = archive.ReadEntry(out fullPath, out entryType)) != null)
161 { 204 {
162 //m_log.DebugFormat( 205 //m_log.DebugFormat(
163 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length); 206 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
@@ -165,9 +208,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver
165 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) 208 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
166 continue; 209 continue;
167 210
211
212 // Find the scene that this file belongs to
213
214 Scene scene;
215 string filePath;
216 if (!dearchivedScenes.GetRegionFromPath(fullPath, out scene, out filePath))
217 continue; // this file belongs to a region that we're not loading
218
219 DearchiveContext sceneContext = null;
220 if (scene != null)
221 {
222 if (!sceneContexts.TryGetValue(scene.RegionInfo.RegionID, out sceneContext))
223 {
224 sceneContext = new DearchiveContext(scene);
225 sceneContexts.Add(scene.RegionInfo.RegionID, sceneContext);
226 }
227 }
228
229
230 // Process the file
231
168 if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) 232 if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
169 { 233 {
170 serialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); 234 sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data));
171 } 235 }
172 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) 236 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets)
173 { 237 {
@@ -181,19 +245,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver
181 } 245 }
182 else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) 246 else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH))
183 { 247 {
184 LoadTerrain(filePath, data); 248 LoadTerrain(scene, filePath, data);
185 } 249 }
186 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) 250 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
187 { 251 {
188 LoadRegionSettings(filePath, data); 252 LoadRegionSettings(scene, filePath, data, dearchivedScenes);
189 } 253 }
190 else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) 254 else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH))
191 { 255 {
192 serialisedParcels.Add(Encoding.UTF8.GetString(data)); 256 sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data));
193 } 257 }
194 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) 258 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
195 { 259 {
196 LoadControlFile(filePath, data); 260 // Ignore, because we already read the control file
197 } 261 }
198 } 262 }
199 263
@@ -201,15 +265,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
201 } 265 }
202 catch (Exception e) 266 catch (Exception e)
203 { 267 {
204 m_log.ErrorFormat( 268 m_log.Error(
205 "[ARCHIVER]: Aborting load with error in archive file {0}. {1}", filePath, e); 269 String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e);
206 m_errorMessage += e.ToString(); 270 m_errorMessage += e.ToString();
207 m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); 271 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage);
208 return; 272 return;
209 } 273 }
210 finally 274 finally
211 { 275 {
212 archive.Close(); 276 if (archive != null)
277 archive.Close();
213 } 278 }
214 279
215 if (!m_skipAssets) 280 if (!m_skipAssets)
@@ -223,32 +288,143 @@ namespace OpenSim.Region.CoreModules.World.Archiver
223 } 288 }
224 } 289 }
225 290
226 if (!m_merge) 291 foreach (DearchiveContext sceneContext in sceneContexts.Values)
227 { 292 {
228 m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); 293 m_log.InfoFormat("[ARCHIVER]: Loading region {0}", sceneContext.Scene.RegionInfo.RegionName);
229 m_scene.DeleteAllSceneObjects(); 294
295 if (!m_merge)
296 {
297 m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
298 sceneContext.Scene.DeleteAllSceneObjects();
299 }
300
301 try
302 {
303 LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels);
304 LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects);
305
306 // Inform any interested parties that the region has changed. We waited until now so that all
307 // of the region's objects will be loaded when we send this notification.
308 IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface<IEstateModule>();
309 if (estateModule != null)
310 estateModule.TriggerRegionInfoChange();
311 }
312 catch (Exception e)
313 {
314 m_log.Error("[ARCHIVER]: Error loading parcels or objects ", e);
315 m_errorMessage += e.ToString();
316 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage);
317 return;
318 }
230 } 319 }
231 320
232 LoadParcels(serialisedParcels); 321 // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so
233 LoadObjects(serialisedSceneObjects); 322 // that users can enter the scene. If we allow the scripts to start in the loop above
323 // then they significantly increase the time until the OAR finishes loading.
324 Util.FireAndForget(delegate(object o)
325 {
326 Thread.Sleep(15000);
327 m_log.Info("[ARCHIVER]: Starting scripts in scene objects");
328
329 foreach (DearchiveContext sceneContext in sceneContexts.Values)
330 {
331 foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects)
332 {
333 sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart
334 sceneObject.ResumeScripts();
335 }
336
337 sceneContext.SceneObjects.Clear();
338 }
339 });
234 340
235 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); 341 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");
236 342
237 m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); 343 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage);
344 }
345
346 /// <summary>
347 /// Searches through the files in the archive for the control file, and reads it.
348 /// We must read the control file first, in order to know which regions are available.
349 /// </summary>
350 /// <remarks>
351 /// In most cases the control file *is* first, since that's how we create archives. However,
352 /// it's possible that someone rewrote the archive externally so we can't rely on this fact.
353 /// </remarks>
354 /// <param name="archive"></param>
355 /// <param name="dearchivedScenes"></param>
356 private void FindAndLoadControlFile(out TarArchiveReader archive, out DearchiveScenesInfo dearchivedScenes)
357 {
358 archive = new TarArchiveReader(m_loadStream);
359 dearchivedScenes = new DearchiveScenesInfo();
360
361 string filePath;
362 byte[] data;
363 TarArchiveReader.TarEntryType entryType;
364 bool firstFile = true;
365
366 while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
367 {
368 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
369 continue;
370
371 if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
372 {
373 LoadControlFile(filePath, data, dearchivedScenes);
374
375 // Find which scenes are available in the simulator
376 ArchiveScenesGroup simulatorScenes = new ArchiveScenesGroup();
377 SceneManager.Instance.ForEachScene(delegate(Scene scene2)
378 {
379 simulatorScenes.AddScene(scene2);
380 });
381 simulatorScenes.CalcSceneLocations();
382 dearchivedScenes.SetSimulatorScenes(m_rootScene, simulatorScenes);
383
384 // If the control file wasn't the first file then reset the read pointer
385 if (!firstFile)
386 {
387 m_log.Warn("Control file wasn't the first file in the archive");
388 if (m_loadStream.CanSeek)
389 {
390 m_loadStream.Seek(0, SeekOrigin.Begin);
391 }
392 else if (m_loadPath != null)
393 {
394 archive.Close();
395 archive = null;
396 m_loadStream.Close();
397 m_loadStream = null;
398 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(m_loadPath), CompressionMode.Decompress);
399 archive = new TarArchiveReader(m_loadStream);
400 }
401 else
402 {
403 // There isn't currently a scenario where this happens, but it's best to add a check just in case
404 throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking");
405 }
406 }
407
408 return;
409 }
410
411 firstFile = false;
412 }
413
414 throw new Exception("Control file not found");
238 } 415 }
239 416
240 /// <summary> 417 /// <summary>
241 /// Load serialized scene objects. 418 /// Load serialized scene objects.
242 /// </summary> 419 /// </summary>
243 /// <param name="serialisedSceneObjects"></param> 420 protected void LoadObjects(Scene scene, List<string> serialisedSceneObjects, List<SceneObjectGroup> sceneObjects)
244 protected void LoadObjects(List<string> serialisedSceneObjects)
245 { 421 {
246 // Reload serialized prims 422 // Reload serialized prims
247 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); 423 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
248 424
249 UUID oldTelehubUUID = m_scene.RegionInfo.RegionSettings.TelehubObject; 425 UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject;
250 426
251 IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface<IRegionSerialiserModule>(); 427 IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
252 int sceneObjectsLoadedCount = 0; 428 int sceneObjectsLoadedCount = 0;
253 429
254 foreach (string serialisedSceneObject in serialisedSceneObjects) 430 foreach (string serialisedSceneObject in serialisedSceneObjects)
@@ -269,7 +445,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
269 445
270 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); 446 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
271 447
272 bool isTelehub = (sceneObject.UUID == oldTelehubUUID); 448 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
273 449
274 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned 450 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
275 // on the same region server and multiple examples a single object archive to be imported 451 // on the same region server and multiple examples a single object archive to be imported
@@ -279,8 +455,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
279 if (isTelehub) 455 if (isTelehub)
280 { 456 {
281 // Change the Telehub Object to the new UUID 457 // Change the Telehub Object to the new UUID
282 m_scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; 458 scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID;
283 m_scene.RegionInfo.RegionSettings.Save(); 459 scene.RegionInfo.RegionSettings.Save();
284 oldTelehubUUID = UUID.Zero; 460 oldTelehubUUID = UUID.Zero;
285 } 461 }
286 462
@@ -290,17 +466,20 @@ namespace OpenSim.Region.CoreModules.World.Archiver
290 { 466 {
291 if (part.CreatorData == null || part.CreatorData == string.Empty) 467 if (part.CreatorData == null || part.CreatorData == string.Empty)
292 { 468 {
293 if (!ResolveUserUuid(part.CreatorID)) 469 if (!ResolveUserUuid(scene, part.CreatorID))
294 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; 470 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
295 } 471 }
296 if (UserManager != null) 472 if (UserManager != null)
297 UserManager.AddUser(part.CreatorID, part.CreatorData); 473 UserManager.AddUser(part.CreatorID, part.CreatorData);
298 474
299 if (!ResolveUserUuid(part.OwnerID)) 475 if (!ResolveUserUuid(scene, part.OwnerID))
300 part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 476 part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
477
478 if (!ResolveUserUuid(scene, part.LastOwnerID))
479 part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
301 480
302 if (!ResolveUserUuid(part.LastOwnerID)) 481 if (!ResolveGroupUuid(part.GroupID))
303 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 482 part.GroupID = UUID.Zero;
304 483
305 // And zap any troublesome sit target information 484 // And zap any troublesome sit target information
306// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); 485// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
@@ -311,14 +490,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
311 // being no copy/no mod for everyone 490 // being no copy/no mod for everyone
312 lock (part.TaskInventory) 491 lock (part.TaskInventory)
313 { 492 {
314 if (!ResolveUserUuid(part.CreatorID)) 493 if (!ResolveUserUuid(scene, part.CreatorID))
315 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; 494 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
316 495
317 if (!ResolveUserUuid(part.OwnerID)) 496 if (!ResolveUserUuid(scene, part.OwnerID))
318 part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 497 part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
319 498
320 if (!ResolveUserUuid(part.LastOwnerID)) 499 if (!ResolveUserUuid(scene, part.LastOwnerID))
321 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 500 part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
322 501
323 // And zap any troublesome sit target information 502 // And zap any troublesome sit target information
324 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); 503 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
@@ -331,26 +510,31 @@ namespace OpenSim.Region.CoreModules.World.Archiver
331 TaskInventoryDictionary inv = part.TaskInventory; 510 TaskInventoryDictionary inv = part.TaskInventory;
332 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) 511 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
333 { 512 {
334 if (!ResolveUserUuid(kvp.Value.OwnerID)) 513 if (!ResolveUserUuid(scene, kvp.Value.OwnerID))
335 { 514 {
336 kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 515 kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
337 } 516 }
517
338 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) 518 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty)
339 { 519 {
340 if (!ResolveUserUuid(kvp.Value.CreatorID)) 520 if (!ResolveUserUuid(scene, kvp.Value.CreatorID))
341 kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; 521 kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
342 } 522 }
523
343 if (UserManager != null) 524 if (UserManager != null)
344 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); 525 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
526
527 if (!ResolveGroupUuid(kvp.Value.GroupID))
528 kvp.Value.GroupID = UUID.Zero;
345 } 529 }
346 part.TaskInventory.LockItemsForRead(false); 530 part.TaskInventory.LockItemsForRead(false);
347 } 531 }
348 } 532 }
349 533
350 if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) 534 if (scene.AddRestoredSceneObject(sceneObject, true, false))
351 { 535 {
352 sceneObjectsLoadedCount++; 536 sceneObjectsLoadedCount++;
353 sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0); 537 sceneObject.CreateScriptInstances(0, false, scene.DefaultScriptEngine, 0);
354 sceneObject.ResumeScripts(); 538 sceneObject.ResumeScripts();
355 } 539 }
356 } 540 }
@@ -365,16 +549,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver
365 if (oldTelehubUUID != UUID.Zero) 549 if (oldTelehubUUID != UUID.Zero)
366 { 550 {
367 m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID); 551 m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID);
368 m_scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; 552 scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero;
369 m_scene.RegionInfo.RegionSettings.ClearSpawnPoints(); 553 scene.RegionInfo.RegionSettings.ClearSpawnPoints();
370 } 554 }
371 } 555 }
372 556
373 /// <summary> 557 /// <summary>
374 /// Load serialized parcels. 558 /// Load serialized parcels.
375 /// </summary> 559 /// </summary>
560 /// <param name="scene"></param>
376 /// <param name="serialisedParcels"></param> 561 /// <param name="serialisedParcels"></param>
377 protected void LoadParcels(List<string> serialisedParcels) 562 protected void LoadParcels(Scene scene, List<string> serialisedParcels)
378 { 563 {
379 // Reload serialized parcels 564 // Reload serialized parcels
380 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); 565 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count);
@@ -382,9 +567,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver
382 foreach (string serialisedParcel in serialisedParcels) 567 foreach (string serialisedParcel in serialisedParcels)
383 { 568 {
384 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); 569 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
385 if (!ResolveUserUuid(parcel.OwnerID))
386 parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
387 570
571 // Validate User and Group UUID's
572
573 if (!ResolveUserUuid(scene, parcel.OwnerID))
574 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
575
576 if (!ResolveGroupUuid(parcel.GroupID))
577 {
578 parcel.GroupID = UUID.Zero;
579 parcel.IsGroupOwned = false;
580 }
581
582 List<LandAccessEntry> accessList = new List<LandAccessEntry>();
583 foreach (LandAccessEntry entry in parcel.ParcelAccessList)
584 {
585 if (ResolveUserUuid(scene, entry.AgentID))
586 accessList.Add(entry);
587 // else, drop this access rule
588 }
589 parcel.ParcelAccessList = accessList;
590
388// m_log.DebugFormat( 591// m_log.DebugFormat(
389// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", 592// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}",
390// parcel.Name, parcel.LocalID, parcel.Area); 593// parcel.Name, parcel.LocalID, parcel.Area);
@@ -395,23 +598,24 @@ namespace OpenSim.Region.CoreModules.World.Archiver
395 if (!m_merge) 598 if (!m_merge)
396 { 599 {
397 bool setupDefaultParcel = (landData.Count == 0); 600 bool setupDefaultParcel = (landData.Count == 0);
398 m_scene.LandChannel.Clear(setupDefaultParcel); 601 scene.LandChannel.Clear(setupDefaultParcel);
399 } 602 }
400 603
401 m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData); 604 scene.EventManager.TriggerIncomingLandDataFromStorage(landData);
402 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); 605 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count);
403 } 606 }
404 607
405 /// <summary> 608 /// <summary>
406 /// Look up the given user id to check whether it's one that is valid for this grid. 609 /// Look up the given user id to check whether it's one that is valid for this grid.
407 /// </summary> 610 /// </summary>
611 /// <param name="scene"></param>
408 /// <param name="uuid"></param> 612 /// <param name="uuid"></param>
409 /// <returns></returns> 613 /// <returns></returns>
410 private bool ResolveUserUuid(UUID uuid) 614 private bool ResolveUserUuid(Scene scene, UUID uuid)
411 { 615 {
412 if (!m_validUserUuids.ContainsKey(uuid)) 616 if (!m_validUserUuids.ContainsKey(uuid))
413 { 617 {
414 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); 618 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid);
415 m_validUserUuids.Add(uuid, account != null); 619 m_validUserUuids.Add(uuid, account != null);
416 } 620 }
417 621
@@ -419,6 +623,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver
419 } 623 }
420 624
421 /// <summary> 625 /// <summary>
626 /// Look up the given group id to check whether it's one that is valid for this grid.
627 /// </summary>
628 /// <param name="uuid"></param>
629 /// <returns></returns>
630 private bool ResolveGroupUuid(UUID uuid)
631 {
632 if (uuid == UUID.Zero)
633 return true; // this means the object has no group
634
635 if (!m_validGroupUuids.ContainsKey(uuid))
636 {
637 bool exists;
638
639 if (m_groupsModule == null)
640 exists = false;
641 else
642 exists = (m_groupsModule.GetGroupRecord(uuid) != null);
643
644 m_validGroupUuids.Add(uuid, exists);
645 }
646
647 return m_validGroupUuids[uuid];
648 }
649
422 /// Load an asset 650 /// Load an asset
423 /// </summary> 651 /// </summary>
424 /// <param name="assetFilename"></param> 652 /// <param name="assetFilename"></param>
@@ -442,7 +670,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
442 string extension = filename.Substring(i); 670 string extension = filename.Substring(i);
443 string uuid = filename.Remove(filename.Length - extension.Length); 671 string uuid = filename.Remove(filename.Length - extension.Length);
444 672
445 if (m_scene.AssetService.GetMetadata(uuid) != null) 673 if (m_assetService.GetMetadata(uuid) != null)
446 { 674 {
447 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid); 675 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid);
448 return true; 676 return true;
@@ -462,7 +690,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
462 690
463 // We're relying on the asset service to do the sensible thing and not store the asset if it already 691 // We're relying on the asset service to do the sensible thing and not store the asset if it already
464 // exists. 692 // exists.
465 m_scene.AssetService.Store(asset); 693 m_assetService.Store(asset);
466 694
467 /** 695 /**
468 * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so 696 * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so
@@ -490,12 +718,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
490 /// <summary> 718 /// <summary>
491 /// Load region settings data 719 /// Load region settings data
492 /// </summary> 720 /// </summary>
721 /// <param name="scene"></param>
493 /// <param name="settingsPath"></param> 722 /// <param name="settingsPath"></param>
494 /// <param name="data"></param> 723 /// <param name="data"></param>
724 /// <param name="dearchivedScenes"></param>
495 /// <returns> 725 /// <returns>
496 /// true if settings were loaded successfully, false otherwise 726 /// true if settings were loaded successfully, false otherwise
497 /// </returns> 727 /// </returns>
498 private bool LoadRegionSettings(string settingsPath, byte[] data) 728 private bool LoadRegionSettings(Scene scene, string settingsPath, byte[] data, DearchiveScenesInfo dearchivedScenes)
499 { 729 {
500 RegionSettings loadedRegionSettings; 730 RegionSettings loadedRegionSettings;
501 731
@@ -511,7 +741,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
511 return false; 741 return false;
512 } 742 }
513 743
514 RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; 744 RegionSettings currentRegionSettings = scene.RegionInfo.RegionSettings;
515 745
516 currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit; 746 currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit;
517 currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage; 747 currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage;
@@ -548,12 +778,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
548 foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints()) 778 foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints())
549 currentRegionSettings.AddSpawnPoint(sp); 779 currentRegionSettings.AddSpawnPoint(sp);
550 780
781 currentRegionSettings.LoadedCreationDateTime = dearchivedScenes.LoadedCreationDateTime;
782 currentRegionSettings.LoadedCreationID = dearchivedScenes.GetOriginalRegionID(scene.RegionInfo.RegionID).ToString();
783
551 currentRegionSettings.Save(); 784 currentRegionSettings.Save();
552 785
553 m_scene.TriggerEstateSunUpdate(); 786 scene.TriggerEstateSunUpdate();
554 787
555 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); 788 IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>();
556
557 if (estateModule != null) 789 if (estateModule != null)
558 estateModule.sendRegionHandshakeToAll(); 790 estateModule.sendRegionHandshakeToAll();
559 791
@@ -563,14 +795,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
563 /// <summary> 795 /// <summary>
564 /// Load terrain data 796 /// Load terrain data
565 /// </summary> 797 /// </summary>
798 /// <param name="scene"></param>
566 /// <param name="terrainPath"></param> 799 /// <param name="terrainPath"></param>
567 /// <param name="data"></param> 800 /// <param name="data"></param>
568 /// <returns> 801 /// <returns>
569 /// true if terrain was resolved successfully, false otherwise. 802 /// true if terrain was resolved successfully, false otherwise.
570 /// </returns> 803 /// </returns>
571 private bool LoadTerrain(string terrainPath, byte[] data) 804 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data)
572 { 805 {
573 ITerrainModule terrainModule = m_scene.RequestModuleInterface<ITerrainModule>(); 806 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
574 807
575 MemoryStream ms = new MemoryStream(data); 808 MemoryStream ms = new MemoryStream(data);
576 terrainModule.LoadFromStream(terrainPath, ms); 809 terrainModule.LoadFromStream(terrainPath, ms);
@@ -586,17 +819,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
586 /// </summary> 819 /// </summary>
587 /// <param name="path"></param> 820 /// <param name="path"></param>
588 /// <param name="data"></param> 821 /// <param name="data"></param>
589 public void LoadControlFile(string path, byte[] data) 822 /// <param name="dearchivedScenes"></param>
823 public DearchiveScenesInfo LoadControlFile(string path, byte[] data, DearchiveScenesInfo dearchivedScenes)
590 { 824 {
591 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); 825 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
592 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); 826 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
593 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); 827 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context);
594 828
595 RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; 829 // Loaded metadata will be empty if no information exists in the archive
830 dearchivedScenes.LoadedCreationDateTime = 0;
831 dearchivedScenes.DefaultOriginalID = "";
596 832
597 // Loaded metadata will empty if no information exists in the archive 833 bool multiRegion = false;
598 currentRegionSettings.LoadedCreationDateTime = 0;
599 currentRegionSettings.LoadedCreationID = "";
600 834
601 while (xtr.Read()) 835 while (xtr.Read())
602 { 836 {
@@ -622,18 +856,44 @@ namespace OpenSim.Region.CoreModules.World.Archiver
622 { 856 {
623 int value; 857 int value;
624 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value)) 858 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value))
625 currentRegionSettings.LoadedCreationDateTime = value; 859 dearchivedScenes.LoadedCreationDateTime = value;
626 } 860 }
627 else if (xtr.Name.ToString() == "id") 861 else if (xtr.Name.ToString() == "row")
862 {
863 multiRegion = true;
864 dearchivedScenes.StartRow();
865 }
866 else if (xtr.Name.ToString() == "region")
867 {
868 dearchivedScenes.StartRegion();
869 }
870 else if (xtr.Name.ToString() == "id")
871 {
872 string id = xtr.ReadElementContentAsString();
873 dearchivedScenes.DefaultOriginalID = id;
874 if (multiRegion)
875 dearchivedScenes.SetRegionOriginalID(id);
876 }
877 else if (xtr.Name.ToString() == "dir")
628 { 878 {
629 currentRegionSettings.LoadedCreationID = xtr.ReadElementContentAsString(); 879 dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString());
630 } 880 }
631 } 881 }
632 } 882 }
633 883
634 currentRegionSettings.Save(); 884 dearchivedScenes.MultiRegionFormat = multiRegion;
635 885 if (!multiRegion)
886 {
887 // Add the single scene
888 dearchivedScenes.StartRow();
889 dearchivedScenes.StartRegion();
890 dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID);
891 dearchivedScenes.SetRegionDirectory("");
892 }
893
636 ControlFileLoaded = true; 894 ControlFileLoaded = true;
895
896 return dearchivedScenes;
637 } 897 }
638 } 898 }
639} \ No newline at end of file 899}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
new file mode 100644
index 0000000..d8dace2
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
@@ -0,0 +1,176 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32using OpenSim.Region.Framework.Scenes;
33using OpenMetaverse;
34using System.Drawing;
35
36namespace OpenSim.Region.CoreModules.World.Archiver
37{
38 /// <summary>
39 /// A group of regions arranged in a rectangle, possibly with holes.
40 /// </summary>
41 /// <remarks>
42 /// The regions usually (but not necessarily) belong to an archive file, in which case we
43 /// store additional information used to create the archive (e.g., each region's
44 /// directory within the archive).
45 /// </remarks>
46 public class ArchiveScenesGroup
47 {
48 /// <summary>
49 /// All the regions. The outer dictionary contains rows (key: Y coordinate).
50 /// The inner dictionaries contain each row's regions (key: X coordinate).
51 /// </summary>
52 public SortedDictionary<uint, SortedDictionary<uint, Scene>> Regions { get; set; }
53
54 /// <summary>
55 /// The subdirectory where each region is stored in the archive.
56 /// </summary>
57 protected Dictionary<UUID, string> m_regionDirs;
58
59 /// <summary>
60 /// The grid coordinates of the regions' bounding box.
61 /// </summary>
62 public Rectangle Rect { get; set; }
63
64
65 public ArchiveScenesGroup()
66 {
67 Regions = new SortedDictionary<uint, SortedDictionary<uint, Scene>>();
68 m_regionDirs = new Dictionary<UUID, string>();
69 Rect = new Rectangle(0, 0, 0, 0);
70 }
71
72 public void AddScene(Scene scene)
73 {
74 uint x = scene.RegionInfo.RegionLocX;
75 uint y = scene.RegionInfo.RegionLocY;
76
77 SortedDictionary<uint, Scene> row;
78 if (!Regions.TryGetValue(y, out row))
79 {
80 row = new SortedDictionary<uint, Scene>();
81 Regions[y] = row;
82 }
83
84 row[x] = scene;
85 }
86
87 /// <summary>
88 /// Called after all the scenes have been added. Performs calculations that require
89 /// knowledge of all the scenes.
90 /// </summary>
91 public void CalcSceneLocations()
92 {
93 if (Regions.Count == 0)
94 return;
95
96 // Find the bounding rectangle
97
98 uint firstY = Regions.First().Key;
99 uint lastY = Regions.Last().Key;
100
101 uint? firstX = null;
102 uint? lastX = null;
103
104 foreach (SortedDictionary<uint, Scene> row in Regions.Values)
105 {
106 uint curFirstX = row.First().Key;
107 uint curLastX = row.Last().Key;
108
109 firstX = (firstX == null) ? curFirstX : (firstX < curFirstX) ? firstX : curFirstX;
110 lastX = (lastX == null) ? curLastX : (lastX > curLastX) ? lastX : curLastX;
111 }
112
113 Rect = new Rectangle((int)firstX, (int)firstY, (int)(lastX - firstX + 1), (int)(lastY - firstY + 1));
114
115
116 // Calculate the subdirectory in which each region will be stored in the archive
117
118 m_regionDirs.Clear();
119 ForEachScene(delegate(Scene scene)
120 {
121 // We add the region's coordinates to ensure uniqueness even if multiple regions have the same name
122 string path = string.Format("{0}_{1}_{2}",
123 scene.RegionInfo.RegionLocX - Rect.X + 1,
124 scene.RegionInfo.RegionLocY - Rect.Y + 1,
125 scene.RegionInfo.RegionName.Replace(' ', '_'));
126 m_regionDirs[scene.RegionInfo.RegionID] = path;
127 });
128 }
129
130 /// <summary>
131 /// Returns the subdirectory where the region is stored.
132 /// </summary>
133 /// <param name="regionID"></param>
134 /// <returns></returns>
135 public string GetRegionDir(UUID regionID)
136 {
137 return m_regionDirs[regionID];
138 }
139
140 /// <summary>
141 /// Performs an action on all the scenes in this order: rows from South to North,
142 /// and within each row West to East.
143 /// </summary>
144 /// <param name="action"></param>
145 public void ForEachScene(Action<Scene> action)
146 {
147 foreach (SortedDictionary<uint, Scene> row in Regions.Values)
148 {
149 foreach (Scene scene in row.Values)
150 {
151 action(scene);
152 }
153 }
154 }
155
156 /// <summary>
157 /// Returns the scene at position 'location'.
158 /// </summary>
159 /// <param name="location">A location in the grid</param>
160 /// <param name="scene">The scene at this location</param>
161 /// <returns>Whether the scene was found</returns>
162 public bool TryGetScene(Point location, out Scene scene)
163 {
164 SortedDictionary<uint, Scene> row;
165 if (Regions.TryGetValue((uint)location.Y, out row))
166 {
167 if (row.TryGetValue((uint)location.X, out scene))
168 return true;
169 }
170
171 scene = null;
172 return false;
173 }
174
175 }
176}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
new file mode 100644
index 0000000..d751b1c
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -0,0 +1,634 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.IO.Compression;
32using System.Reflection;
33using System.Text.RegularExpressions;
34using System.Threading;
35using System.Xml;
36using log4net;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Serialization;
40using OpenSim.Region.CoreModules.World.Terrain;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43using Ionic.Zlib;
44using GZipStream = Ionic.Zlib.GZipStream;
45using CompressionMode = Ionic.Zlib.CompressionMode;
46using OpenSim.Framework.Serialization.External;
47
48namespace OpenSim.Region.CoreModules.World.Archiver
49{
50 /// <summary>
51 /// Prepare to write out an archive.
52 /// </summary>
53 public class ArchiveWriteRequest
54 {
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 /// <summary>
58 /// The minimum major version of OAR that we can write.
59 /// </summary>
60 public static int MIN_MAJOR_VERSION = 0;
61
62 /// <summary>
63 /// The maximum major version of OAR that we can write.
64 /// </summary>
65 public static int MAX_MAJOR_VERSION = 1;
66
67 /// <summary>
68 /// Whether we're saving a multi-region archive.
69 /// </summary>
70 public bool MultiRegionFormat { get; set; }
71
72 /// <summary>
73 /// Determine whether this archive will save assets. Default is true.
74 /// </summary>
75 public bool SaveAssets { get; set; }
76
77 /// <summary>
78 /// Determines which objects will be included in the archive, according to their permissions.
79 /// Default is null, meaning no permission checks.
80 /// </summary>
81 public string CheckPermissions { get; set; }
82
83 protected Scene m_rootScene;
84 protected Stream m_saveStream;
85 protected TarArchiveWriter m_archiveWriter;
86 protected Guid m_requestId;
87 protected Dictionary<string, object> m_options;
88
89 /// <summary>
90 /// Constructor
91 /// </summary>
92 /// <param name="module">Calling module</param>
93 /// <param name="savePath">The path to which to save data.</param>
94 /// <param name="requestId">The id associated with this request</param>
95 /// <exception cref="System.IO.IOException">
96 /// If there was a problem opening a stream for the file specified by the savePath
97 /// </exception>
98 public ArchiveWriteRequest(Scene scene, string savePath, Guid requestId) : this(scene, requestId)
99 {
100 try
101 {
102 m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression);
103 }
104 catch (EntryPointNotFoundException e)
105 {
106 m_log.ErrorFormat(
107 "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
108 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
109 m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace);
110 }
111 }
112
113 /// <summary>
114 /// Constructor.
115 /// </summary>
116 /// <param name="scene">The root scene to archive</param>
117 /// <param name="saveStream">The stream to which to save data.</param>
118 /// <param name="requestId">The id associated with this request</param>
119 public ArchiveWriteRequest(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId)
120 {
121 m_saveStream = saveStream;
122 }
123
124 protected ArchiveWriteRequest(Scene scene, Guid requestId)
125 {
126 m_rootScene = scene;
127 m_requestId = requestId;
128 m_archiveWriter = null;
129
130 MultiRegionFormat = false;
131 SaveAssets = true;
132 CheckPermissions = null;
133 }
134
135 /// <summary>
136 /// Archive the region requested.
137 /// </summary>
138 /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception>
139 public void ArchiveRegion(Dictionary<string, object> options)
140 {
141 m_options = options;
142
143 if (options.ContainsKey("all") && (bool)options["all"])
144 MultiRegionFormat = true;
145
146 if (options.ContainsKey("noassets") && (bool)options["noassets"])
147 SaveAssets = false;
148
149 Object temp;
150 if (options.TryGetValue("checkPermissions", out temp))
151 CheckPermissions = (string)temp;
152
153
154 // Find the regions to archive
155 ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
156 if (MultiRegionFormat)
157 {
158 m_log.InfoFormat("[ARCHIVER]: Saving {0} regions", SceneManager.Instance.Scenes.Count);
159 SceneManager.Instance.ForEachScene(delegate(Scene scene)
160 {
161 scenesGroup.AddScene(scene);
162 });
163 }
164 else
165 {
166 scenesGroup.AddScene(m_rootScene);
167 }
168 scenesGroup.CalcSceneLocations();
169
170
171 m_archiveWriter = new TarArchiveWriter(m_saveStream);
172
173 try
174 {
175 // Write out control file. It should be first so that it will be found ASAP when loading the file.
176 m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(scenesGroup));
177 m_log.InfoFormat("[ARCHIVER]: Added control file to archive.");
178
179 // Archive the regions
180
181 Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>();
182
183 scenesGroup.ForEachScene(delegate(Scene scene)
184 {
185 string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : "";
186 ArchiveOneRegion(scene, regionDir, assetUuids);
187 });
188
189 // Archive the assets
190
191 if (SaveAssets)
192 {
193 m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count);
194
195 // Asynchronously request all the assets required to perform this archive operation
196 AssetsRequest ar
197 = new AssetsRequest(
198 new AssetsArchiver(m_archiveWriter), assetUuids,
199 m_rootScene.AssetService, m_rootScene.UserAccountService,
200 m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets);
201
202 Util.FireAndForget(o => ar.Execute());
203
204 // CloseArchive() will be called from ReceivedAllAssets()
205 }
206 else
207 {
208 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
209 CloseArchive(string.Empty);
210 }
211 }
212 catch (Exception e)
213 {
214 CloseArchive(e.Message);
215 throw;
216 }
217 }
218
219
220 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids)
221 {
222 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName);
223
224 EntityBase[] entities = scene.GetEntities();
225 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
226
227 int numObjectsSkippedPermissions = 0;
228
229 // Filter entities so that we only have scene objects.
230 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
231 // end up having to do this
232 IPermissionsModule permissionsModule = scene.RequestModuleInterface<IPermissionsModule>();
233 foreach (EntityBase entity in entities)
234 {
235 if (entity is SceneObjectGroup)
236 {
237 SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
238
239 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
240 {
241 if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, CheckPermissions, permissionsModule))
242 {
243 // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
244 ++numObjectsSkippedPermissions;
245 }
246 else
247 {
248 sceneObjects.Add(sceneObject);
249 }
250 }
251 }
252 }
253
254 if (SaveAssets)
255 {
256 UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService);
257 int prevAssets = assetUuids.Count;
258
259 foreach (SceneObjectGroup sceneObject in sceneObjects)
260 {
261 assetGatherer.GatherAssetUuids(sceneObject, assetUuids);
262 }
263
264 m_log.DebugFormat(
265 "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets",
266 sceneObjects.Count, assetUuids.Count - prevAssets);
267 }
268
269 if (numObjectsSkippedPermissions > 0)
270 {
271 m_log.DebugFormat(
272 "[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
273 numObjectsSkippedPermissions);
274 }
275
276 // Make sure that we also request terrain texture assets
277 RegionSettings regionSettings = scene.RegionInfo.RegionSettings;
278
279 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
280 assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture;
281
282 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
283 assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture;
284
285 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
286 assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture;
287
288 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
289 assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture;
290
291 Save(scene, sceneObjects, regionDir);
292 }
293
294 /// <summary>
295 /// Checks whether the user has permission to export an object group to an OAR.
296 /// </summary>
297 /// <param name="user">The user</param>
298 /// <param name="objGroup">The object group</param>
299 /// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param>
300 /// <param name="permissionsModule">The scene's permissions module</param>
301 /// <returns>Whether the user is allowed to export the object to an OAR</returns>
302 private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions, IPermissionsModule permissionsModule)
303 {
304 if (checkPermissions == null)
305 return true;
306
307 if (permissionsModule == null)
308 return true; // this shouldn't happen
309
310 // Check whether the user is permitted to export all of the parts in the SOG. If any
311 // part can't be exported then the entire SOG can't be exported.
312
313 bool permitted = true;
314 //int primNumber = 1;
315
316 foreach (SceneObjectPart obj in objGroup.Parts)
317 {
318 uint perm;
319 PermissionClass permissionClass = permissionsModule.GetPermissionClass(user, obj);
320 switch (permissionClass)
321 {
322 case PermissionClass.Owner:
323 perm = obj.BaseMask;
324 break;
325 case PermissionClass.Group:
326 perm = obj.GroupMask | obj.EveryoneMask;
327 break;
328 case PermissionClass.Everyone:
329 default:
330 perm = obj.EveryoneMask;
331 break;
332 }
333
334 bool canCopy = (perm & (uint)PermissionMask.Copy) != 0;
335 bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0;
336
337 // Special case: if Everyone can copy the object then this implies it can also be
338 // Transferred.
339 // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask
340 // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer
341 // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied.
342 if (permissionClass != PermissionClass.Owner)
343 canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0;
344
345 bool partPermitted = true;
346 if (checkPermissions.Contains("C") && !canCopy)
347 partPermitted = false;
348 if (checkPermissions.Contains("T") && !canTransfer)
349 partPermitted = false;
350
351 // If the user is the Creator of the object then it can always be included in the OAR
352 bool creator = (obj.CreatorID.Guid == user.Guid);
353 if (creator)
354 partPermitted = true;
355
356 //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount);
357 //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}",
358 // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask,
359 // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted);
360
361 if (!partPermitted)
362 {
363 permitted = false;
364 break;
365 }
366
367 //++primNumber;
368 }
369
370 return permitted;
371 }
372
373 /// <summary>
374 /// Create the control file.
375 /// </summary>
376 /// <returns></returns>
377 public string CreateControlFile(ArchiveScenesGroup scenesGroup)
378 {
379 int majorVersion;
380 int minorVersion;
381
382 if (MultiRegionFormat)
383 {
384 majorVersion = MAX_MAJOR_VERSION;
385 minorVersion = 0;
386 }
387 else
388 {
389 // To support older versions of OpenSim, we continue to create single-region OARs
390 // using the old file format. In the future this format will be discontinued.
391 majorVersion = 0;
392 minorVersion = 8;
393 }
394//
395// if (m_options.ContainsKey("version"))
396// {
397// string[] parts = m_options["version"].ToString().Split('.');
398// if (parts.Length >= 1)
399// {
400// majorVersion = Int32.Parse(parts[0]);
401//
402// if (parts.Length >= 2)
403// minorVersion = Int32.Parse(parts[1]);
404// }
405// }
406//
407// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION)
408// {
409// throw new Exception(
410// string.Format(
411// "OAR version number for save must be between {0} and {1}",
412// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION));
413// }
414// else if (majorVersion == MAX_MAJOR_VERSION)
415// {
416// // Force 1.0
417// minorVersion = 0;
418// }
419// else if (majorVersion == MIN_MAJOR_VERSION)
420// {
421// // Force 0.4
422// minorVersion = 4;
423// }
424
425 m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion);
426 if (majorVersion == 1)
427 {
428 m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim versions prior to 0.7.4. Do not use the --all option if you want to produce a compatible OAR");
429 }
430
431 String s;
432
433 using (StringWriter sw = new StringWriter())
434 {
435 using (XmlTextWriter xtw = new XmlTextWriter(sw))
436 {
437 xtw.Formatting = Formatting.Indented;
438 xtw.WriteStartDocument();
439 xtw.WriteStartElement("archive");
440 xtw.WriteAttributeString("major_version", majorVersion.ToString());
441 xtw.WriteAttributeString("minor_version", minorVersion.ToString());
442
443 xtw.WriteStartElement("creation_info");
444 DateTime now = DateTime.UtcNow;
445 TimeSpan t = now - new DateTime(1970, 1, 1);
446 xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString());
447 if (!MultiRegionFormat)
448 xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString());
449 xtw.WriteEndElement();
450
451 xtw.WriteElementString("assets_included", SaveAssets.ToString());
452
453 if (MultiRegionFormat)
454 {
455 WriteRegionsManifest(scenesGroup, xtw);
456 }
457 else
458 {
459 xtw.WriteStartElement("region_info");
460 WriteRegionInfo(m_rootScene, xtw);
461 xtw.WriteEndElement();
462 }
463
464 xtw.WriteEndElement();
465
466 xtw.Flush();
467 }
468
469 s = sw.ToString();
470 }
471
472 return s;
473 }
474
475 /// <summary>
476 /// Writes the list of regions included in a multi-region OAR.
477 /// </summary>
478 private static void WriteRegionsManifest(ArchiveScenesGroup scenesGroup, XmlTextWriter xtw)
479 {
480 xtw.WriteStartElement("regions");
481
482 // Write the regions in order: rows from South to North, then regions from West to East.
483 // The list of regions can have "holes"; we write empty elements in their position.
484
485 for (uint y = (uint)scenesGroup.Rect.Top; y < scenesGroup.Rect.Bottom; ++y)
486 {
487 SortedDictionary<uint, Scene> row;
488 if (scenesGroup.Regions.TryGetValue(y, out row))
489 {
490 xtw.WriteStartElement("row");
491
492 for (uint x = (uint)scenesGroup.Rect.Left; x < scenesGroup.Rect.Right; ++x)
493 {
494 Scene scene;
495 if (row.TryGetValue(x, out scene))
496 {
497 xtw.WriteStartElement("region");
498 xtw.WriteElementString("id", scene.RegionInfo.RegionID.ToString());
499 xtw.WriteElementString("dir", scenesGroup.GetRegionDir(scene.RegionInfo.RegionID));
500 WriteRegionInfo(scene, xtw);
501 xtw.WriteEndElement();
502 }
503 else
504 {
505 // Write a placeholder for a missing region
506 xtw.WriteElementString("region", "");
507 }
508 }
509
510 xtw.WriteEndElement();
511 }
512 else
513 {
514 // Write a placeholder for a missing row
515 xtw.WriteElementString("row", "");
516 }
517 }
518
519 xtw.WriteEndElement(); // "regions"
520 }
521
522 protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw)
523 {
524 bool isMegaregion;
525 Vector2 size;
526
527 IRegionCombinerModule rcMod = scene.RequestModuleInterface<IRegionCombinerModule>();
528
529 if (rcMod != null)
530 isMegaregion = rcMod.IsRootForMegaregion(scene.RegionInfo.RegionID);
531 else
532 isMegaregion = false;
533
534 if (isMegaregion)
535 size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID);
536 else
537 size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize);
538
539 xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
540 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
541 }
542
543
544 protected void Save(Scene scene, List<SceneObjectGroup> sceneObjects, string regionDir)
545 {
546 if (regionDir != string.Empty)
547 regionDir = ArchiveConstants.REGIONS_PATH + regionDir + "/";
548
549 m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive.");
550
551 // Write out region settings
552 string settingsPath = String.Format("{0}{1}{2}.xml",
553 regionDir, ArchiveConstants.SETTINGS_PATH, scene.RegionInfo.RegionName);
554 m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(scene.RegionInfo.RegionSettings));
555
556 m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive.");
557
558 // Write out land data (aka parcel) settings
559 List<ILandObject> landObjects = scene.LandChannel.AllParcels();
560 foreach (ILandObject lo in landObjects)
561 {
562 LandData landData = lo.LandData;
563 string landDataPath = String.Format("{0}{1}{2}.xml",
564 regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString());
565 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
566 }
567
568 m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive.");
569
570 // Write out terrain
571 string terrainPath = String.Format("{0}{1}{2}.r32",
572 regionDir, ArchiveConstants.TERRAINS_PATH, scene.RegionInfo.RegionName);
573
574 MemoryStream ms = new MemoryStream();
575 scene.RequestModuleInterface<ITerrainModule>().SaveToStream(terrainPath, ms);
576 m_archiveWriter.WriteFile(terrainPath, ms.ToArray());
577 ms.Close();
578
579 m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive.");
580
581 // Write out scene object metadata
582 IRegionSerialiserModule serializer = scene.RequestModuleInterface<IRegionSerialiserModule>();
583 foreach (SceneObjectGroup sceneObject in sceneObjects)
584 {
585 //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType());
586
587 string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options);
588 string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject));
589 m_archiveWriter.WriteFile(objectPath, serializedObject);
590 }
591 }
592
593 protected void ReceivedAllAssets(
594 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids)
595 {
596 foreach (UUID uuid in assetsNotFoundUuids)
597 {
598 m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid);
599 }
600
601 // m_log.InfoFormat(
602 // "[ARCHIVER]: Received {0} of {1} assets requested",
603 // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count);
604
605 CloseArchive(String.Empty);
606 }
607
608
609 /// <summary>
610 /// Closes the archive and notifies that we're done.
611 /// </summary>
612 /// <param name="errorMessage">The error that occurred, or empty for success</param>
613 protected void CloseArchive(string errorMessage)
614 {
615 try
616 {
617 if (m_archiveWriter != null)
618 m_archiveWriter.Close();
619 m_saveStream.Close();
620 }
621 catch (Exception e)
622 {
623 m_log.Error(string.Format("[ARCHIVER]: Error closing archive: {0} ", e.Message), e);
624 if (errorMessage == string.Empty)
625 errorMessage = e.Message;
626 }
627
628 m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName);
629
630 m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage);
631 }
632
633 }
634}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs
deleted file mode 100644
index 0780d86..0000000
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs
+++ /dev/null
@@ -1,153 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Xml;
33using log4net;
34using OpenMetaverse;
35using OpenSim.Framework;
36using OpenSim.Framework.Serialization;
37using OpenSim.Framework.Serialization.External;
38using OpenSim.Region.CoreModules.World.Terrain;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Region.CoreModules.World.Archiver
43{
44 /// <summary>
45 /// Method called when all the necessary assets for an archive request have been received.
46 /// </summary>
47 public delegate void AssetsRequestCallback(
48 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids);
49
50 /// <summary>
51 /// Execute the write of an archive once we have received all the necessary data
52 /// </summary>
53 public class ArchiveWriteRequestExecution
54 {
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 protected ITerrainModule m_terrainModule;
58 protected IRegionSerialiserModule m_serialiser;
59 protected List<SceneObjectGroup> m_sceneObjects;
60 protected Scene m_scene;
61 protected TarArchiveWriter m_archiveWriter;
62 protected Guid m_requestId;
63 protected Dictionary<string, object> m_options;
64
65 public ArchiveWriteRequestExecution(
66 List<SceneObjectGroup> sceneObjects,
67 ITerrainModule terrainModule,
68 IRegionSerialiserModule serialiser,
69 Scene scene,
70 TarArchiveWriter archiveWriter,
71 Guid requestId,
72 Dictionary<string, object> options)
73 {
74 m_sceneObjects = sceneObjects;
75 m_terrainModule = terrainModule;
76 m_serialiser = serialiser;
77 m_scene = scene;
78 m_archiveWriter = archiveWriter;
79 m_requestId = requestId;
80 m_options = options;
81 }
82
83 protected internal void ReceivedAllAssets(
84 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids)
85 {
86 try
87 {
88 Save(assetsFoundUuids, assetsNotFoundUuids);
89 }
90 finally
91 {
92 m_archiveWriter.Close();
93 }
94
95 m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_scene.RegionInfo.RegionName);
96
97 m_scene.EventManager.TriggerOarFileSaved(m_requestId, String.Empty);
98 }
99
100 protected internal void Save(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids)
101 {
102 foreach (UUID uuid in assetsNotFoundUuids)
103 {
104 m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid);
105 }
106
107// m_log.InfoFormat(
108// "[ARCHIVER]: Received {0} of {1} assets requested",
109// assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count);
110
111 m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive.");
112
113 // Write out region settings
114 string settingsPath
115 = String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName);
116 m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings));
117
118 m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive.");
119
120 // Write out land data (aka parcel) settings
121 List<ILandObject>landObjects = m_scene.LandChannel.AllParcels();
122 foreach (ILandObject lo in landObjects)
123 {
124 LandData landData = lo.LandData;
125 string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH,
126 landData.GlobalID.ToString());
127 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
128 }
129
130 m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive.");
131
132 // Write out terrain
133 string terrainPath
134 = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName);
135
136 MemoryStream ms = new MemoryStream();
137 m_terrainModule.SaveToStream(terrainPath, ms);
138 m_archiveWriter.WriteFile(terrainPath, ms.ToArray());
139 ms.Close();
140
141 m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive.");
142
143 // Write out scene object metadata
144 foreach (SceneObjectGroup sceneObject in m_sceneObjects)
145 {
146 //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType());
147
148 string serializedObject = m_serialiser.SerializeGroupToXml2(sceneObject, m_options);
149 m_archiveWriter.WriteFile(ArchiveHelpers.CreateObjectPath(sceneObject), serializedObject);
150 }
151 }
152 }
153} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
deleted file mode 100644
index 4edaaca..0000000
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
+++ /dev/null
@@ -1,438 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.IO.Compression;
32using System.Reflection;
33using System.Text.RegularExpressions;
34using System.Threading;
35using System.Xml;
36using log4net;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Serialization;
40using OpenSim.Region.CoreModules.World.Terrain;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43using Ionic.Zlib;
44using GZipStream = Ionic.Zlib.GZipStream;
45using CompressionMode = Ionic.Zlib.CompressionMode;
46
47namespace OpenSim.Region.CoreModules.World.Archiver
48{
49 /// <summary>
50 /// Prepare to write out an archive.
51 /// </summary>
52 public class ArchiveWriteRequestPreparation
53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 /// <summary>
57 /// The minimum major version of OAR that we can write.
58 /// </summary>
59 public static int MIN_MAJOR_VERSION = 0;
60
61 /// <summary>
62 /// The maximum major version of OAR that we can write.
63 /// </summary>
64 public static int MAX_MAJOR_VERSION = 0;
65
66 /// <summary>
67 /// Determine whether this archive will save assets. Default is true.
68 /// </summary>
69 public bool SaveAssets { get; set; }
70
71 protected ArchiverModule m_module;
72 protected Scene m_scene;
73 protected Stream m_saveStream;
74 protected Guid m_requestId;
75
76 /// <summary>
77 /// Constructor
78 /// </summary>
79 /// <param name="module">Calling module</param>
80 /// <param name="savePath">The path to which to save data.</param>
81 /// <param name="requestId">The id associated with this request</param>
82 /// <exception cref="System.IO.IOException">
83 /// If there was a problem opening a stream for the file specified by the savePath
84 /// </exception>
85 public ArchiveWriteRequestPreparation(ArchiverModule module, string savePath, Guid requestId) : this(module, requestId)
86 {
87 try
88 {
89 m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression);
90 }
91 catch (EntryPointNotFoundException e)
92 {
93 m_log.ErrorFormat(
94 "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
95 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
96 m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace);
97 }
98 }
99
100 /// <summary>
101 /// Constructor.
102 /// </summary>
103 /// <param name="module">Calling module</param>
104 /// <param name="saveStream">The stream to which to save data.</param>
105 /// <param name="requestId">The id associated with this request</param>
106 public ArchiveWriteRequestPreparation(ArchiverModule module, Stream saveStream, Guid requestId) : this(module, requestId)
107 {
108 m_saveStream = saveStream;
109 }
110
111 protected ArchiveWriteRequestPreparation(ArchiverModule module, Guid requestId)
112 {
113 m_module = module;
114
115 // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix
116 // this.
117 if (m_module != null)
118 m_scene = m_module.Scene;
119
120 m_requestId = requestId;
121
122 SaveAssets = true;
123 }
124
125 /// <summary>
126 /// Archive the region requested.
127 /// </summary>
128 /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception>
129 public void ArchiveRegion(Dictionary<string, object> options)
130 {
131 if (options.ContainsKey("noassets") && (bool)options["noassets"])
132 SaveAssets = false;
133
134 try
135 {
136 Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>();
137
138 EntityBase[] entities = m_scene.GetEntities();
139 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
140
141 string checkPermissions = null;
142 int numObjectsSkippedPermissions = 0;
143 Object temp;
144 if (options.TryGetValue("checkPermissions", out temp))
145 checkPermissions = (string)temp;
146
147 // Filter entities so that we only have scene objects.
148 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
149 // end up having to do this
150 foreach (EntityBase entity in entities)
151 {
152 if (entity is SceneObjectGroup)
153 {
154 SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
155
156 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
157 {
158 if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions))
159 {
160 // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
161 ++numObjectsSkippedPermissions;
162 }
163 else
164 {
165 sceneObjects.Add(sceneObject);
166 }
167 }
168 }
169 }
170
171 if (SaveAssets)
172 {
173 UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService);
174
175 foreach (SceneObjectGroup sceneObject in sceneObjects)
176 {
177 assetGatherer.GatherAssetUuids(sceneObject, assetUuids);
178 }
179
180 m_log.DebugFormat(
181 "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets",
182 sceneObjects.Count, assetUuids.Count);
183 }
184 else
185 {
186 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
187 }
188
189 if (numObjectsSkippedPermissions > 0)
190 {
191 m_log.DebugFormat(
192 "[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
193 numObjectsSkippedPermissions);
194 }
195
196 // Make sure that we also request terrain texture assets
197 RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings;
198
199 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
200 assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture;
201
202 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
203 assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture;
204
205 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
206 assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture;
207
208 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
209 assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture;
210
211 TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream);
212
213 // Asynchronously request all the assets required to perform this archive operation
214 ArchiveWriteRequestExecution awre
215 = new ArchiveWriteRequestExecution(
216 sceneObjects,
217 m_scene.RequestModuleInterface<ITerrainModule>(),
218 m_scene.RequestModuleInterface<IRegionSerialiserModule>(),
219 m_scene,
220 archiveWriter,
221 m_requestId,
222 options);
223
224 m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time.");
225
226 // Write out control file. This has to be done first so that subsequent loaders will see this file first
227 // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this
228 archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options));
229 m_log.InfoFormat("[ARCHIVER]: Added control file to archive.");
230
231 if (SaveAssets)
232 {
233 AssetsRequest ar
234 = new AssetsRequest(
235 new AssetsArchiver(archiveWriter), assetUuids,
236 m_scene.AssetService, m_scene.UserAccountService,
237 m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets);
238
239 Util.FireAndForget(o => ar.Execute());
240 }
241 else
242 {
243 awre.ReceivedAllAssets(new List<UUID>(), new List<UUID>());
244 }
245 }
246 catch (Exception)
247 {
248 m_saveStream.Close();
249 throw;
250 }
251 }
252
253 /// <summary>
254 /// Checks whether the user has permission to export an object group to an OAR.
255 /// </summary>
256 /// <param name="user">The user</param>
257 /// <param name="objGroup">The object group</param>
258 /// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param>
259 /// <returns>Whether the user is allowed to export the object to an OAR</returns>
260 private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions)
261 {
262 if (checkPermissions == null)
263 return true;
264
265 IPermissionsModule module = m_scene.RequestModuleInterface<IPermissionsModule>();
266 if (module == null)
267 return true; // this shouldn't happen
268
269 // Check whether the user is permitted to export all of the parts in the SOG. If any
270 // part can't be exported then the entire SOG can't be exported.
271
272 bool permitted = true;
273 //int primNumber = 1;
274
275 foreach (SceneObjectPart obj in objGroup.Parts)
276 {
277 uint perm;
278 PermissionClass permissionClass = module.GetPermissionClass(user, obj);
279 switch (permissionClass)
280 {
281 case PermissionClass.Owner:
282 perm = obj.BaseMask;
283 break;
284 case PermissionClass.Group:
285 perm = obj.GroupMask | obj.EveryoneMask;
286 break;
287 case PermissionClass.Everyone:
288 default:
289 perm = obj.EveryoneMask;
290 break;
291 }
292
293 bool canCopy = (perm & (uint)PermissionMask.Copy) != 0;
294 bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0;
295
296 // Special case: if Everyone can copy the object then this implies it can also be
297 // Transferred.
298 // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask
299 // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer
300 // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied.
301 if (permissionClass != PermissionClass.Owner)
302 canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0;
303
304 bool partPermitted = true;
305 if (checkPermissions.Contains("C") && !canCopy)
306 partPermitted = false;
307 if (checkPermissions.Contains("T") && !canTransfer)
308 partPermitted = false;
309
310 // If the user is the Creator of the object then it can always be included in the OAR
311 bool creator = (obj.CreatorID.Guid == user.Guid);
312 if (creator)
313 partPermitted = true;
314
315 //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount);
316 //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}",
317 // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask,
318 // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted);
319
320 if (!partPermitted)
321 {
322 permitted = false;
323 break;
324 }
325
326 //++primNumber;
327 }
328
329 return permitted;
330 }
331
332 /// <summary>
333 /// Create the control file for the most up to date archive
334 /// </summary>
335 /// <returns></returns>
336 public string CreateControlFile(Dictionary<string, object> options)
337 {
338 int majorVersion = MAX_MAJOR_VERSION, minorVersion = 8;
339//
340// if (options.ContainsKey("version"))
341// {
342// string[] parts = options["version"].ToString().Split('.');
343// if (parts.Length >= 1)
344// {
345// majorVersion = Int32.Parse(parts[0]);
346//
347// if (parts.Length >= 2)
348// minorVersion = Int32.Parse(parts[1]);
349// }
350// }
351//
352// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION)
353// {
354// throw new Exception(
355// string.Format(
356// "OAR version number for save must be between {0} and {1}",
357// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION));
358// }
359// else if (majorVersion == MAX_MAJOR_VERSION)
360// {
361// // Force 1.0
362// minorVersion = 0;
363// }
364// else if (majorVersion == MIN_MAJOR_VERSION)
365// {
366// // Force 0.4
367// minorVersion = 4;
368// }
369
370 m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion);
371 //if (majorVersion == 1)
372 //{
373 // m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR");
374 //}
375
376 String s;
377
378 using (StringWriter sw = new StringWriter())
379 {
380 using (XmlTextWriter xtw = new XmlTextWriter(sw))
381 {
382 xtw.Formatting = Formatting.Indented;
383 xtw.WriteStartDocument();
384 xtw.WriteStartElement("archive");
385 xtw.WriteAttributeString("major_version", majorVersion.ToString());
386 xtw.WriteAttributeString("minor_version", minorVersion.ToString());
387
388 xtw.WriteStartElement("creation_info");
389 DateTime now = DateTime.UtcNow;
390 TimeSpan t = now - new DateTime(1970, 1, 1);
391 xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString());
392 xtw.WriteElementString("id", UUID.Random().ToString());
393 xtw.WriteEndElement();
394
395 xtw.WriteStartElement("region_info");
396
397 bool isMegaregion;
398 Vector2 size;
399 IRegionCombinerModule rcMod = null;
400
401 // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix
402 // this, possibly by doing control file creation somewhere else.
403 if (m_module != null)
404 rcMod = m_module.RegionCombinerModule;
405
406 if (rcMod != null)
407 isMegaregion = rcMod.IsRootForMegaregion(m_scene.RegionInfo.RegionID);
408 else
409 isMegaregion = false;
410
411 if (isMegaregion)
412 size = rcMod.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
413 else
414 size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize);
415
416 xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
417 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
418
419 xtw.WriteEndElement();
420
421 xtw.WriteElementString("assets_included", SaveAssets.ToString());
422
423 xtw.WriteEndElement();
424
425 xtw.Flush();
426 }
427
428 s = sw.ToString();
429 }
430
431// if (m_scene != null)
432// Console.WriteLine(
433// "[ARCHIVE WRITE REQUEST PREPARATION]: Control file for {0} is: {1}", m_scene.RegionInfo.RegionName, s);
434
435 return s;
436 }
437 }
438}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
index bf3b124..1be6386 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
@@ -32,6 +32,9 @@ using System.Reflection;
32using log4net; 32using log4net;
33using NDesk.Options; 33using NDesk.Options;
34using Nini.Config; 34using Nini.Config;
35using Mono.Addins;
36using OpenSim.Framework;
37using OpenSim.Framework.Console;
35using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
37 40
@@ -40,6 +43,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
40 /// <summary> 43 /// <summary>
41 /// This module loads and saves OpenSimulator region archives 44 /// This module loads and saves OpenSimulator region archives
42 /// </summary> 45 /// </summary>
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ArchiverModule")]
43 public class ArchiverModule : INonSharedRegionModule, IRegionArchiverModule 47 public class ArchiverModule : INonSharedRegionModule, IRegionArchiverModule
44 { 48 {
45 private static readonly ILog m_log = 49 private static readonly ILog m_log =
@@ -117,7 +121,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
117// 121//
118// foreach (string param in mainParams) 122// foreach (string param in mainParams)
119// m_log.DebugFormat("GOT PARAM [{0}]", param); 123// m_log.DebugFormat("GOT PARAM [{0}]", param);
120 124
121 if (mainParams.Count > 2) 125 if (mainParams.Count > 2)
122 { 126 {
123 DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty); 127 DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty);
@@ -146,17 +150,22 @@ namespace OpenSim.Region.CoreModules.World.Archiver
146 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); 150 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
147 ops.Add("publish", v => options["wipe-owners"] = v != null); 151 ops.Add("publish", v => options["wipe-owners"] = v != null);
148 ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; }); 152 ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; });
153 ops.Add("all", delegate(string v) { options["all"] = v != null; });
149 154
150 List<string> mainParams = ops.Parse(cmdparams); 155 List<string> mainParams = ops.Parse(cmdparams);
151 156
157 string path;
152 if (mainParams.Count > 2) 158 if (mainParams.Count > 2)
153 { 159 path = mainParams[2];
154 ArchiveRegion(mainParams[2], options);
155 }
156 else 160 else
157 { 161 path = DEFAULT_OAR_BACKUP_FILENAME;
158 ArchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, options); 162
159 } 163 // Not doing this right now as this causes some problems with auto-backup systems. Maybe a force flag is
164 // needed
165// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, path))
166// return;
167
168 ArchiveRegion(path, options);
160 } 169 }
161 170
162 public void ArchiveRegion(string savePath, Dictionary<string, object> options) 171 public void ArchiveRegion(string savePath, Dictionary<string, object> options)
@@ -169,7 +178,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
169 m_log.InfoFormat( 178 m_log.InfoFormat(
170 "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath); 179 "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath);
171 180
172 new ArchiveWriteRequestPreparation(this, savePath, requestId).ArchiveRegion(options); 181 new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options);
173 } 182 }
174 183
175 public void ArchiveRegion(Stream saveStream) 184 public void ArchiveRegion(Stream saveStream)
@@ -184,7 +193,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
184 193
185 public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options) 194 public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options)
186 { 195 {
187 new ArchiveWriteRequestPreparation(this, saveStream, requestId).ArchiveRegion(options); 196 new ArchiveWriteRequest(Scene, saveStream, requestId).ArchiveRegion(options);
188 } 197 }
189 198
190 public void DearchiveRegion(string loadPath) 199 public void DearchiveRegion(string loadPath)
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index 89e9593..e2f8833 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -46,6 +46,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 /// <summary>
50 /// Method called when all the necessary assets for an archive request have been received.
51 /// </summary>
52 public delegate void AssetsRequestCallback(
53 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids);
54
49 enum RequestState 55 enum RequestState
50 { 56 {
51 Initial, 57 Initial,
@@ -123,6 +129,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
123 m_options = options; 129 m_options = options;
124 m_repliesRequired = uuids.Count; 130 m_repliesRequired = uuids.Count;
125 131
132 // FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread
133 // hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received
134 // so we can properly abort that thread. Or request all assets synchronously, though that would be a more
135 // radical change
126 m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT); 136 m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT);
127 m_requestCallbackTimer.AutoReset = false; 137 m_requestCallbackTimer.AutoReset = false;
128 m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout); 138 m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout);
diff --git a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
new file mode 100644
index 0000000..3dcc020
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
@@ -0,0 +1,232 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32using OpenSim.Region.Framework.Scenes;
33using OpenMetaverse;
34using System.Drawing;
35using log4net;
36using System.Reflection;
37using OpenSim.Framework.Serialization;
38
39namespace OpenSim.Region.CoreModules.World.Archiver
40{
41 /// <summary>
42 /// The regions included in an OAR file.
43 /// </summary>
44 public class DearchiveScenesInfo
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 /// <summary>
49 /// One region in the archive.
50 /// </summary>
51 public class RegionInfo
52 {
53 /// <summary>
54 /// The subdirectory in which the region is stored.
55 /// </summary>
56 public string Directory { get; set; }
57
58 /// <summary>
59 /// The region's coordinates (relative to the South-West corner of the block).
60 /// </summary>
61 public Point Location { get; set; }
62
63 /// <summary>
64 /// The UUID of the original scene from which this archived region was saved.
65 /// </summary>
66 public string OriginalID { get; set; }
67
68 /// <summary>
69 /// The scene in the current simulator into which this region is loaded.
70 /// If null then the region doesn't have a corresponding scene, and it won't be loaded.
71 /// </summary>
72 public Scene Scene { get; set; }
73 }
74
75 /// <summary>
76 /// Whether this archive uses the multi-region format.
77 /// </summary>
78 public Boolean MultiRegionFormat { get; set; }
79
80 /// <summary>
81 /// Maps (Region directory -> region)
82 /// </summary>
83 protected Dictionary<string, RegionInfo> m_directory2region = new Dictionary<string, RegionInfo>();
84
85 /// <summary>
86 /// Maps (UUID of the scene in the simulator where the region will be loaded -> region)
87 /// </summary>
88 protected Dictionary<UUID, RegionInfo> m_newId2region = new Dictionary<UUID, RegionInfo>();
89
90 public int LoadedCreationDateTime { get; set; }
91 public string DefaultOriginalID { get; set; }
92
93 // These variables are used while reading the archive control file
94 protected int? m_curY = null;
95 protected int? m_curX = null;
96 protected RegionInfo m_curRegion;
97
98
99 public DearchiveScenesInfo()
100 {
101 MultiRegionFormat = false;
102 }
103
104
105 // The following methods are used while reading the archive control file
106
107 public void StartRow()
108 {
109 m_curY = (m_curY == null) ? 0 : m_curY + 1;
110 m_curX = null;
111 }
112
113 public void StartRegion()
114 {
115 m_curX = (m_curX == null) ? 0 : m_curX + 1;
116 // Note: this doesn't mean we have a real region in this location; this could just be a "hole"
117 }
118
119 public void SetRegionOriginalID(string id)
120 {
121 m_curRegion = new RegionInfo();
122 m_curRegion.Location = new Point((int)m_curX, (int)m_curY);
123 m_curRegion.OriginalID = id;
124 // 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called
125 }
126
127 public void SetRegionDirectory(string directory)
128 {
129 m_curRegion.Directory = directory;
130 m_directory2region[directory] = m_curRegion;
131 }
132
133
134 /// <summary>
135 /// Sets all the scenes present in the simulator.
136 /// </summary>
137 /// <remarks>
138 /// This method matches regions in the archive to scenes in the simulator according to
139 /// their relative position. We only load regions if there's an existing Scene in the
140 /// grid location where the region should be loaded.
141 /// </remarks>
142 /// <param name="rootScene">The scene where the Load OAR operation was run</param>
143 /// <param name="simulatorScenes">All the scenes in the simulator</param>
144 public void SetSimulatorScenes(Scene rootScene, ArchiveScenesGroup simulatorScenes)
145 {
146 foreach (RegionInfo archivedRegion in m_directory2region.Values)
147 {
148 Point location = new Point((int)rootScene.RegionInfo.RegionLocX, (int)rootScene.RegionInfo.RegionLocY);
149 location.Offset(archivedRegion.Location);
150
151 Scene scene;
152 if (simulatorScenes.TryGetScene(location, out scene))
153 {
154 archivedRegion.Scene = scene;
155 m_newId2region[scene.RegionInfo.RegionID] = archivedRegion;
156 }
157 else
158 {
159 m_log.WarnFormat("[ARCHIVER]: Not loading archived region {0} because there's no existing region at location {1},{2}",
160 archivedRegion.Directory, location.X, location.Y);
161 }
162 }
163 }
164
165 /// <summary>
166 /// Returns the archived region according to the path of a file in the archive.
167 /// Also, converts the full path into a path that is relative to the region's directory.
168 /// </summary>
169 /// <param name="fullPath">The path of a file in the archive</param>
170 /// <param name="scene">The corresponding Scene, or null if none</param>
171 /// <param name="relativePath">The path relative to the region's directory. (Or the original
172 /// path, if this file doesn't belong to a region.)</param>
173 /// <returns>True: use this file; False: skip it</returns>
174 public bool GetRegionFromPath(string fullPath, out Scene scene, out string relativePath)
175 {
176 scene = null;
177 relativePath = fullPath;
178
179 if (!MultiRegionFormat)
180 {
181 if (m_newId2region.Count > 0)
182 scene = m_newId2region.First().Value.Scene;
183 return true;
184 }
185
186 if (!fullPath.StartsWith(ArchiveConstants.REGIONS_PATH))
187 return true; // this file doesn't belong to a region
188
189 string[] parts = fullPath.Split(new Char[] { '/' }, 3);
190 if (parts.Length != 3)
191 return false;
192 string regionDirectory = parts[1];
193 relativePath = parts[2];
194
195 RegionInfo region;
196 if (m_directory2region.TryGetValue(regionDirectory, out region))
197 {
198 scene = region.Scene;
199 return (scene != null);
200 }
201 else
202 {
203 return false;
204 }
205 }
206
207 /// <summary>
208 /// Returns the original UUID of a region (from the simulator where the OAR was saved),
209 /// given the UUID of the scene it was loaded into in the current simulator.
210 /// </summary>
211 /// <param name="newID"></param>
212 /// <returns></returns>
213 public string GetOriginalRegionID(UUID newID)
214 {
215 RegionInfo region;
216 if (m_newId2region.TryGetValue(newID, out region))
217 return region.OriginalID;
218 else
219 return DefaultOriginalID;
220 }
221
222 /// <summary>
223 /// Returns the scenes that have been (or will be) loaded.
224 /// </summary>
225 /// <returns></returns>
226 public List<UUID> GetLoadedScenes()
227 {
228 return m_newId2region.Keys.ToList();
229 }
230
231 }
232}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index 5deaf52..82f49b0 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -47,32 +47,41 @@ using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants;
47using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader; 47using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader;
48using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter; 48using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter;
49using RegionSettings = OpenSim.Framework.RegionSettings; 49using RegionSettings = OpenSim.Framework.RegionSettings;
50using OpenSim.Region.Framework.Interfaces;
50 51
51namespace OpenSim.Region.CoreModules.World.Archiver.Tests 52namespace OpenSim.Region.CoreModules.World.Archiver.Tests
52{ 53{
53 [TestFixture] 54 [TestFixture]
54 public class ArchiverTests 55 public class ArchiverTests : OpenSimTestCase
55 { 56 {
56 private Guid m_lastRequestId; 57 private Guid m_lastRequestId;
57 private string m_lastErrorMessage; 58 private string m_lastErrorMessage;
58 59
60 protected SceneHelpers m_sceneHelpers;
59 protected TestScene m_scene; 61 protected TestScene m_scene;
60 protected ArchiverModule m_archiverModule; 62 protected ArchiverModule m_archiverModule;
63 protected SerialiserModule m_serialiserModule;
61 64
62 protected TaskInventoryItem m_soundItem; 65 protected TaskInventoryItem m_soundItem;
63 66
64 [SetUp] 67 [SetUp]
65 public void SetUp() 68 public override void SetUp()
66 { 69 {
70 base.SetUp();
71
72 // FIXME: Do something about this - relying on statics in unit tests causes trouble sooner or later
73 new SceneManager();
74
67 m_archiverModule = new ArchiverModule(); 75 m_archiverModule = new ArchiverModule();
68 SerialiserModule serialiserModule = new SerialiserModule(); 76 m_serialiserModule = new SerialiserModule();
69 TerrainModule terrainModule = new TerrainModule(); 77 TerrainModule terrainModule = new TerrainModule();
70 78
71 m_scene = new SceneHelpers().SetupScene(); 79 m_sceneHelpers = new SceneHelpers();
72 SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule); 80 m_scene = m_sceneHelpers.SetupScene();
81 SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, m_serialiserModule, terrainModule);
73 } 82 }
74 83
75 private void LoadCompleted(Guid requestId, string errorMessage) 84 private void LoadCompleted(Guid requestId, List<UUID> loadedScenes, string errorMessage)
76 { 85 {
77 lock (this) 86 lock (this)
78 { 87 {
@@ -128,26 +137,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
128 TestHelpers.InMethod(); 137 TestHelpers.InMethod();
129// log4net.Config.XmlConfigurator.Configure(); 138// log4net.Config.XmlConfigurator.Configure();
130 139
131 SceneObjectPart part1 = CreateSceneObjectPart1(); 140 SceneObjectGroup sog1;
132 SceneObjectGroup sog1 = new SceneObjectGroup(part1); 141 SceneObjectGroup sog2;
133 m_scene.AddNewSceneObject(sog1, false); 142 UUID ncAssetUuid;
134 143 CreateTestObjects(m_scene, out sog1, out sog2, out ncAssetUuid);
135 SceneObjectPart part2 = CreateSceneObjectPart2();
136
137 AssetNotecard nc = new AssetNotecard();
138 nc.BodyText = "Hello World!";
139 nc.Encode();
140 UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000");
141 UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000");
142 AssetBase ncAsset
143 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
144 m_scene.AssetService.Store(ncAsset);
145 SceneObjectGroup sog2 = new SceneObjectGroup(part2);
146 TaskInventoryItem ncItem
147 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
148 part2.Inventory.AddInventoryItem(ncItem, true);
149
150 m_scene.AddNewSceneObject(sog2, false);
151 144
152 MemoryStream archiveWriteStream = new MemoryStream(); 145 MemoryStream archiveWriteStream = new MemoryStream();
153 m_scene.EventManager.OnOarFileSaved += SaveCompleted; 146 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
@@ -186,7 +179,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
186 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 179 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
187 180
188 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); 181 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
189 arr.LoadControlFile(filePath, data); 182 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
190 183
191 Assert.That(arr.ControlFileLoaded, Is.True); 184 Assert.That(arr.ControlFileLoaded, Is.True);
192 185
@@ -211,6 +204,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
211 // TODO: Test presence of more files and contents of files. 204 // TODO: Test presence of more files and contents of files.
212 } 205 }
213 206
207 private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid)
208 {
209 SceneObjectPart part1 = CreateSceneObjectPart1();
210 sog1 = new SceneObjectGroup(part1);
211 scene.AddNewSceneObject(sog1, false);
212
213 AssetNotecard nc = new AssetNotecard();
214 nc.BodyText = "Hello World!";
215 nc.Encode();
216 ncAssetUuid = UUID.Random();
217 UUID ncItemUuid = UUID.Random();
218 AssetBase ncAsset
219 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
220 m_scene.AssetService.Store(ncAsset);
221
222 TaskInventoryItem ncItem
223 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
224 SceneObjectPart part2 = CreateSceneObjectPart2();
225 sog2 = new SceneObjectGroup(part2);
226 part2.Inventory.AddInventoryItem(ncItem, true);
227
228 scene.AddNewSceneObject(sog2, false);
229 }
230
214 /// <summary> 231 /// <summary>
215 /// Test saving an OpenSim Region Archive with the no assets option 232 /// Test saving an OpenSim Region Archive with the no assets option
216 /// </summary> 233 /// </summary>
@@ -270,7 +287,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
270 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 287 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
271 288
272 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); 289 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
273 arr.LoadControlFile(filePath, data); 290 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
274 291
275 Assert.That(arr.ControlFileLoaded, Is.True); 292 Assert.That(arr.ControlFileLoaded, Is.True);
276 293
@@ -307,7 +324,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
307 324
308 tar.WriteFile( 325 tar.WriteFile(
309 ArchiveConstants.CONTROL_FILE_PATH, 326 ArchiveConstants.CONTROL_FILE_PATH,
310 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); 327 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
311 328
312 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); 329 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
313 SceneObjectPart sop2 330 SceneObjectPart sop2
@@ -362,11 +379,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
362 // Also check that direct entries which will also have a file entry containing that directory doesn't 379 // Also check that direct entries which will also have a file entry containing that directory doesn't
363 // upset load 380 // upset load
364 tar.WriteDir(ArchiveConstants.TERRAINS_PATH); 381 tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
365 382
366 tar.WriteFile( 383 tar.WriteFile(
367 ArchiveConstants.CONTROL_FILE_PATH, 384 ArchiveConstants.CONTROL_FILE_PATH,
368 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); 385 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
369
370 SceneObjectPart part1 = CreateSceneObjectPart1(); 386 SceneObjectPart part1 = CreateSceneObjectPart1();
371 387
372 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); 388 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
@@ -389,31 +405,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
389 Assert.That(soundDataResourceName, Is.Not.Null); 405 Assert.That(soundDataResourceName, Is.Not.Null);
390 406
391 byte[] soundData; 407 byte[] soundData;
392 Console.WriteLine("Loading " + soundDataResourceName); 408 UUID soundUuid;
393 using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) 409 CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid);
394 { 410
395 using (BinaryReader br = new BinaryReader(resource)) 411 TaskInventoryItem item1
396 { 412 = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
397 // FIXME: Use the inspector instead 413 part1.Inventory.AddInventoryItem(item1, true);
398 soundData = br.ReadBytes(99999999);
399 UUID soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
400 string soundAssetFileName
401 = ArchiveConstants.ASSETS_PATH + soundUuid
402 + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
403 tar.WriteFile(soundAssetFileName, soundData);
404
405 /*
406 AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
407 scene.AssetService.Store(soundAsset);
408 asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
409 */
410
411 TaskInventoryItem item1
412 = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
413 part1.Inventory.AddInventoryItem(item1, true);
414 }
415 }
416
417 m_scene.AddNewSceneObject(object1, false); 414 m_scene.AddNewSceneObject(object1, false);
418 415
419 string object1FileName = string.Format( 416 string object1FileName = string.Format(
@@ -435,6 +432,34 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
435 432
436 Assert.That(m_lastErrorMessage, Is.Null); 433 Assert.That(m_lastErrorMessage, Is.Null);
437 434
435 TestLoadedRegion(part1, soundItemName, soundData);
436 }
437
438 private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid)
439 {
440 using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName))
441 {
442 using (BinaryReader br = new BinaryReader(resource))
443 {
444 // FIXME: Use the inspector instead
445 soundData = br.ReadBytes(99999999);
446 soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
447 string soundAssetFileName
448 = ArchiveConstants.ASSETS_PATH + soundUuid
449 + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
450 tar.WriteFile(soundAssetFileName, soundData);
451
452 /*
453 AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
454 scene.AssetService.Store(soundAsset);
455 asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
456 */
457 }
458 }
459 }
460
461 private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData)
462 {
438 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); 463 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
439 464
440 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); 465 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded");
@@ -454,9 +479,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
454 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); 479 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match");
455 480
456 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); 481 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels");
457
458 // Temporary
459 Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod());
460 } 482 }
461 483
462 /// <summary> 484 /// <summary>
@@ -516,7 +538,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
516 SerialiserModule serialiserModule = new SerialiserModule(); 538 SerialiserModule serialiserModule = new SerialiserModule();
517 TerrainModule terrainModule = new TerrainModule(); 539 TerrainModule terrainModule = new TerrainModule();
518 540
519 TestScene scene2 = new SceneHelpers().SetupScene(); 541 m_sceneHelpers = new SceneHelpers();
542 TestScene scene2 = m_sceneHelpers.SetupScene();
520 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); 543 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule);
521 544
522 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is 545 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is
@@ -554,7 +577,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
554 tar.WriteDir(ArchiveConstants.TERRAINS_PATH); 577 tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
555 tar.WriteFile( 578 tar.WriteFile(
556 ArchiveConstants.CONTROL_FILE_PATH, 579 ArchiveConstants.CONTROL_FILE_PATH,
557 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); 580 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
558 581
559 RegionSettings rs = new RegionSettings(); 582 RegionSettings rs = new RegionSettings();
560 rs.AgentLimit = 17; 583 rs.AgentLimit = 17;
@@ -664,7 +687,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
664 SerialiserModule serialiserModule = new SerialiserModule(); 687 SerialiserModule serialiserModule = new SerialiserModule();
665 TerrainModule terrainModule = new TerrainModule(); 688 TerrainModule terrainModule = new TerrainModule();
666 689
667 Scene scene = new SceneHelpers().SetupScene(); 690 Scene scene = m_sceneHelpers.SetupScene();
668 SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); 691 SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule);
669 692
670 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false); 693 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
@@ -700,5 +723,258 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
700 Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge"); 723 Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge");
701 } 724 }
702 } 725 }
726
727 /// <summary>
728 /// Test saving a multi-region OAR.
729 /// </summary>
730 [Test]
731 public void TestSaveMultiRegionOar()
732 {
733 TestHelpers.InMethod();
734
735 // Create test regions
736
737 int WIDTH = 2;
738 int HEIGHT = 2;
739
740 List<Scene> scenes = new List<Scene>();
741
742 // Maps (Directory in OAR file -> scene)
743 Dictionary<string, Scene> regionPaths = new Dictionary<string, Scene>();
744
745 // Maps (Scene -> expected object paths)
746 Dictionary<UUID, List<string>> expectedPaths = new Dictionary<UUID, List<string>>();
747
748 // List of expected assets
749 List<UUID> expectedAssets = new List<UUID>();
750
751 for (uint y = 0; y < HEIGHT; y++)
752 {
753 for (uint x = 0; x < WIDTH; x++)
754 {
755 Scene scene;
756 if (x == 0 && y == 0)
757 {
758 scene = m_scene; // this scene was already created in SetUp()
759 }
760 else
761 {
762 scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y);
763 SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule());
764 }
765 scenes.Add(scene);
766
767 string dir = String.Format("{0}_{1}_{2}", x + 1, y + 1, scene.RegionInfo.RegionName.Replace(" ", "_"));
768 regionPaths[dir] = scene;
769
770 SceneObjectGroup sog1;
771 SceneObjectGroup sog2;
772 UUID ncAssetUuid;
773
774 CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid);
775
776 expectedPaths[scene.RegionInfo.RegionID] = new List<string>();
777 expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog1));
778 expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog2));
779
780 expectedAssets.Add(ncAssetUuid);
781 }
782 }
783
784
785 // Save OAR
786
787 MemoryStream archiveWriteStream = new MemoryStream();
788 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
789
790 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
791
792 Dictionary<string, Object> options = new Dictionary<string, Object>();
793 options.Add("all", true);
794
795 lock (this)
796 {
797 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options);
798 Monitor.Wait(this, 60000);
799 }
800
801
802 // Check that the OAR contains the expected data
803
804 Assert.That(m_lastRequestId, Is.EqualTo(requestId));
805
806 byte[] archive = archiveWriteStream.ToArray();
807 MemoryStream archiveReadStream = new MemoryStream(archive);
808 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
809
810 Dictionary<UUID, List<string>> foundPaths = new Dictionary<UUID, List<string>>();
811 List<UUID> foundAssets = new List<UUID>();
812
813 foreach (Scene scene in scenes)
814 {
815 foundPaths[scene.RegionInfo.RegionID] = new List<string>();
816 }
817
818 string filePath;
819 TarArchiveReader.TarEntryType tarEntryType;
820
821 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
822 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
823
824 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
825 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
826
827 Assert.That(arr.ControlFileLoaded, Is.True);
828
829 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
830 {
831 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
832 {
833 // Assets are shared, so this file doesn't belong to any specific region.
834 string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
835 if (fileName.EndsWith("_notecard.txt"))
836 foundAssets.Add(UUID.Parse(fileName.Substring(0, fileName.Length - "_notecard.txt".Length)));
837 }
838 else
839 {
840 // This file belongs to one of the regions. Find out which one.
841 Assert.IsTrue(filePath.StartsWith(ArchiveConstants.REGIONS_PATH));
842 string[] parts = filePath.Split(new Char[] { '/' }, 3);
843 Assert.AreEqual(3, parts.Length);
844 string regionDirectory = parts[1];
845 string relativePath = parts[2];
846 Scene scene = regionPaths[regionDirectory];
847
848 if (relativePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
849 {
850 foundPaths[scene.RegionInfo.RegionID].Add(relativePath);
851 }
852 }
853 }
854
855 Assert.AreEqual(scenes.Count, foundPaths.Count);
856 foreach (Scene scene in scenes)
857 {
858 Assert.That(foundPaths[scene.RegionInfo.RegionID], Is.EquivalentTo(expectedPaths[scene.RegionInfo.RegionID]));
859 }
860
861 Assert.That(foundAssets, Is.EquivalentTo(expectedAssets));
862 }
863
864 /// <summary>
865 /// Test loading a multi-region OAR.
866 /// </summary>
867 [Test]
868 public void TestLoadMultiRegionOar()
869 {
870 TestHelpers.InMethod();
871
872 // Create an ArchiveScenesGroup with the regions in the OAR. This is needed to generate the control file.
873
874 int WIDTH = 2;
875 int HEIGHT = 2;
876
877 for (uint y = 0; y < HEIGHT; y++)
878 {
879 for (uint x = 0; x < WIDTH; x++)
880 {
881 Scene scene;
882 if (x == 0 && y == 0)
883 {
884 scene = m_scene; // this scene was already created in SetUp()
885 }
886 else
887 {
888 scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y);
889 SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule());
890 }
891 }
892 }
893
894 ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
895 SceneManager.Instance.ForEachScene(delegate(Scene scene)
896 {
897 scenesGroup.AddScene(scene);
898 });
899 scenesGroup.CalcSceneLocations();
900
901 // Generate the OAR file
902
903 MemoryStream archiveWriteStream = new MemoryStream();
904 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
905
906 ArchiveWriteRequest writeRequest = new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty);
907 writeRequest.MultiRegionFormat = true;
908 tar.WriteFile(
909 ArchiveConstants.CONTROL_FILE_PATH, writeRequest.CreateControlFile(scenesGroup));
910
911 SceneObjectPart part1 = CreateSceneObjectPart1();
912 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
913 part1.SitTargetPosition = new Vector3(1, 2, 3);
914
915 SceneObjectGroup object1 = new SceneObjectGroup(part1);
916
917 // Let's put some inventory items into our object
918 string soundItemName = "sound-item1";
919 UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
920 Type type = GetType();
921 Assembly assembly = type.Assembly;
922 string soundDataResourceName = null;
923 string[] names = assembly.GetManifestResourceNames();
924 foreach (string name in names)
925 {
926 if (name.EndsWith(".Resources.test-sound.wav"))
927 soundDataResourceName = name;
928 }
929 Assert.That(soundDataResourceName, Is.Not.Null);
930
931 byte[] soundData;
932 UUID soundUuid;
933 CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid);
934
935 TaskInventoryItem item1
936 = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
937 part1.Inventory.AddInventoryItem(item1, true);
938 m_scene.AddNewSceneObject(object1, false);
939
940 string object1FileName = string.Format(
941 "{0}_{1:000}-{2:000}-{3:000}__{4}.xml",
942 part1.Name,
943 Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z),
944 part1.UUID);
945 string path = "regions/1_1_Unit_test_region/" + ArchiveConstants.OBJECTS_PATH + object1FileName;
946 tar.WriteFile(path, SceneObjectSerializer.ToXml2Format(object1));
947
948 tar.Close();
949
950
951 // Delete the current objects, to test that they're loaded from the OAR and didn't
952 // just remain in the scene.
953 SceneManager.Instance.ForEachScene(delegate(Scene scene)
954 {
955 scene.DeleteAllSceneObjects();
956 });
957
958 // Create a "hole", to test that that the corresponding region isn't loaded from the OAR
959 SceneManager.Instance.CloseScene(SceneManager.Instance.Scenes[1]);
960
961
962 // Check thay the OAR file contains the expected data
963
964 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
965
966 lock (this)
967 {
968 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
969 m_archiverModule.DearchiveRegion(archiveReadStream);
970 }
971
972 Assert.That(m_lastErrorMessage, Is.Null);
973
974 Assert.AreEqual(3, SceneManager.Instance.Scenes.Count);
975
976 TestLoadedRegion(part1, soundItemName, soundData);
977 }
978
703 } 979 }
704} 980}
diff --git a/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs b/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs
index 5fa3dc2..d217f36 100644
--- a/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs
+++ b/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs
@@ -27,15 +27,17 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using Mono.Addins;
30using Nini.Config; 31using Nini.Config;
31using OpenMetaverse; 32using OpenMetaverse;
32using OpenSim.Framework; 33using OpenSim.Framework;
33using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
35 36
36namespace OpenSim.Region.CoreModules 37namespace OpenSim.Region.CoreModules.World
37{ 38{
38 public class CloudModule : ICloudModule 39 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "CloudModule")]
40 public class CloudModule : ICloudModule, INonSharedRegionModule
39 { 41 {
40// private static readonly log4net.ILog m_log 42// private static readonly log4net.ILog m_log
41// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 43// = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
@@ -48,7 +50,7 @@ namespace OpenSim.Region.CoreModules
48 private float m_cloudDensity = 1.0F; 50 private float m_cloudDensity = 1.0F;
49 private float[] cloudCover = new float[16 * 16]; 51 private float[] cloudCover = new float[16 * 16];
50 52
51 public void Initialise(Scene scene, IConfigSource config) 53 public void Initialise(IConfigSource config)
52 { 54 {
53 IConfig cloudConfig = config.Configs["Cloud"]; 55 IConfig cloudConfig = config.Configs["Cloud"];
54 56
@@ -59,21 +61,40 @@ namespace OpenSim.Region.CoreModules
59 m_frameUpdateRate = cloudConfig.GetInt("cloud_update_rate", 1000); 61 m_frameUpdateRate = cloudConfig.GetInt("cloud_update_rate", 1000);
60 } 62 }
61 63
62 if (m_enabled) 64 }
63 {
64 65
65 m_scene = scene; 66 public void AddRegion(Scene scene)
67 {
68 if (!m_enabled)
69 return;
66 70
67 scene.EventManager.OnNewClient += CloudsToClient; 71 m_scene = scene;
68 scene.RegisterModuleInterface<ICloudModule>(this);
69 scene.EventManager.OnFrame += CloudUpdate;
70 72
71 GenerateCloudCover(); 73 scene.EventManager.OnNewClient += CloudsToClient;
74 scene.RegisterModuleInterface<ICloudModule>(this);
75 scene.EventManager.OnFrame += CloudUpdate;
72 76
73 m_ready = true; 77 GenerateCloudCover();
74 78
75 } 79 m_ready = true;
80 }
81
82 public void RemoveRegion(Scene scene)
83 {
84 if (!m_enabled)
85 return;
76 86
87 m_ready = false;
88 // Remove our hooks
89 m_scene.EventManager.OnNewClient -= CloudsToClient;
90 m_scene.EventManager.OnFrame -= CloudUpdate;
91 m_scene.UnregisterModuleInterface<ICloudModule>(this);
92
93 m_scene = null;
94 }
95
96 public void RegionLoaded(Scene scene)
97 {
77 } 98 }
78 99
79 public void PostInitialise() 100 public void PostInitialise()
@@ -82,13 +103,6 @@ namespace OpenSim.Region.CoreModules
82 103
83 public void Close() 104 public void Close()
84 { 105 {
85 if (m_enabled)
86 {
87 m_ready = false;
88 // Remove our hooks
89 m_scene.EventManager.OnNewClient -= CloudsToClient;
90 m_scene.EventManager.OnFrame -= CloudUpdate;
91 }
92 } 106 }
93 107
94 public string Name 108 public string Name
@@ -96,12 +110,11 @@ namespace OpenSim.Region.CoreModules
96 get { return "CloudModule"; } 110 get { return "CloudModule"; }
97 } 111 }
98 112
99 public bool IsSharedModule 113 public Type ReplaceableInterface
100 { 114 {
101 get { return false; } 115 get { return null; }
102 } 116 }
103 117
104
105 public float CloudCover(int x, int y, int z) 118 public float CloudCover(int x, int y, int z)
106 { 119 {
107 float cover = 0f; 120 float cover = 0f;
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index fdef9d8..dc062b6 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -40,6 +40,7 @@ using OpenMetaverse;
40using OpenSim.Framework; 40using OpenSim.Framework;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using RegionFlags = OpenMetaverse.RegionFlags;
43 44
44namespace OpenSim.Region.CoreModules.World.Estate 45namespace OpenSim.Region.CoreModules.World.Estate
45{ 46{
@@ -293,6 +294,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
293 } 294 }
294 295
295 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), false); 296 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), false);
297
298 m_log.InfoFormat(
299 "User {0} requested restart of region {1} in {2} seconds",
300 remoteClient.Name, Scene.Name, times.Count != 0 ? times[0] : 0);
296 } 301 }
297 } 302 }
298 303
@@ -317,7 +322,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
317 322
318 if ((estateAccessType & 4) != 0) // User add 323 if ((estateAccessType & 4) != 0) // User add
319 { 324 {
320 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 325 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
321 { 326 {
322 if ((estateAccessType & 1) != 0) // All estates 327 if ((estateAccessType & 1) != 0) // All estates
323 { 328 {
@@ -349,7 +354,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
349 } 354 }
350 if ((estateAccessType & 8) != 0) // User remove 355 if ((estateAccessType & 8) != 0) // User remove
351 { 356 {
352 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 357 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
353 { 358 {
354 if ((estateAccessType & 1) != 0) // All estates 359 if ((estateAccessType & 1) != 0) // All estates
355 { 360 {
@@ -380,7 +385,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
380 } 385 }
381 if ((estateAccessType & 16) != 0) // Group add 386 if ((estateAccessType & 16) != 0) // Group add
382 { 387 {
383 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 388 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
384 { 389 {
385 if ((estateAccessType & 1) != 0) // All estates 390 if ((estateAccessType & 1) != 0) // All estates
386 { 391 {
@@ -409,9 +414,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
409 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 414 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
410 } 415 }
411 } 416 }
417
412 if ((estateAccessType & 32) != 0) // Group remove 418 if ((estateAccessType & 32) != 0) // Group remove
413 { 419 {
414 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 420 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
415 { 421 {
416 if ((estateAccessType & 1) != 0) // All estates 422 if ((estateAccessType & 1) != 0) // All estates
417 { 423 {
@@ -440,9 +446,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
440 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 446 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
441 } 447 }
442 } 448 }
449
443 if ((estateAccessType & 64) != 0) // Ban add 450 if ((estateAccessType & 64) != 0) // Ban add
444 { 451 {
445 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || Scene.Permissions.BypassPermissions()) 452 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false))
446 { 453 {
447 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans; 454 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans;
448 455
@@ -521,9 +528,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
521 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 528 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
522 } 529 }
523 } 530 }
531
524 if ((estateAccessType & 128) != 0) // Ban remove 532 if ((estateAccessType & 128) != 0) // Ban remove
525 { 533 {
526 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || Scene.Permissions.BypassPermissions()) 534 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false))
527 { 535 {
528 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans; 536 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans;
529 537
@@ -576,9 +584,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
576 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 584 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
577 } 585 }
578 } 586 }
587
579 if ((estateAccessType & 256) != 0) // Manager add 588 if ((estateAccessType & 256) != 0) // Manager add
580 { 589 {
581 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 590 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
582 { 591 {
583 if ((estateAccessType & 1) != 0) // All estates 592 if ((estateAccessType & 1) != 0) // All estates
584 { 593 {
@@ -607,9 +616,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
607 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 616 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
608 } 617 }
609 } 618 }
619
610 if ((estateAccessType & 512) != 0) // Manager remove 620 if ((estateAccessType & 512) != 0) // Manager remove
611 { 621 {
612 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 622 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
613 { 623 {
614 if ((estateAccessType & 1) != 0) // All estates 624 if ((estateAccessType & 1) != 0) // All estates
615 { 625 {
@@ -1108,7 +1118,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1108 1118
1109 #endregion 1119 #endregion
1110 1120
1111 #region IRegionModule Members 1121 #region Region Module interface
1112 1122
1113 public string Name { get { return "EstateManagementModule"; } } 1123 public string Name { get { return "EstateManagementModule"; } }
1114 1124
diff --git a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
new file mode 100644
index 0000000..bd22155
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
@@ -0,0 +1,112 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Diagnostics;
32using System.Reflection;
33using System.Text;
34using log4net;
35using Nini.Config;
36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38using OpenMetaverse.Messages.Linden;
39using Mono.Addins;
40using OpenSim.Framework;
41using OpenSim.Framework.Capabilities;
42using OpenSim.Framework.Console;
43using OpenSim.Framework.Servers;
44using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
46using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Physics.Manager;
49using OpenSim.Services.Interfaces;
50using Caps = OpenSim.Framework.Capabilities.Caps;
51using GridRegion = OpenSim.Services.Interfaces.GridRegion;
52
53namespace OpenSim.Region.CoreModules.World.Land
54{
55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DwellModule")]
56 public class DwellModule : IDwellModule, INonSharedRegionModule
57 {
58 private Scene m_scene;
59
60 public Type ReplaceableInterface
61 {
62 get { return typeof(IDwellModule); }
63 }
64
65 public string Name
66 {
67 get { return "DwellModule"; }
68 }
69
70 public void Initialise(IConfigSource source)
71 {
72 }
73
74 public void AddRegion(Scene scene)
75 {
76 m_scene = scene;
77
78 m_scene.EventManager.OnNewClient += OnNewClient;
79 }
80
81 public void RegionLoaded(Scene scene)
82 {
83 }
84
85 public void RemoveRegion(Scene scene)
86 {
87 }
88
89 public void Close()
90 {
91 }
92
93 public void OnNewClient(IClientAPI client)
94 {
95 client.OnParcelDwellRequest += ClientOnParcelDwellRequest;
96 }
97
98 private void ClientOnParcelDwellRequest(int localID, IClientAPI client)
99 {
100 ILandObject parcel = m_scene.LandChannel.GetLandObject(localID);
101 if (parcel == null)
102 return;
103
104 client.SendParcelDwellReply(localID, parcel.LandData.GlobalID, parcel.LandData.Dwell);
105 }
106
107 public int GetDwell(UUID parcelID)
108 {
109 return 0;
110 }
111 }
112}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index aae6603..1193057 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -36,6 +36,7 @@ using Nini.Config;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenMetaverse.StructuredData; 37using OpenMetaverse.StructuredData;
38using OpenMetaverse.Messages.Linden; 38using OpenMetaverse.Messages.Linden;
39using Mono.Addins;
39using OpenSim.Framework; 40using OpenSim.Framework;
40using OpenSim.Framework.Capabilities; 41using OpenSim.Framework.Capabilities;
41using OpenSim.Framework.Console; 42using OpenSim.Framework.Console;
@@ -60,6 +61,7 @@ namespace OpenSim.Region.CoreModules.World.Land
60 public byte RegionAccess; 61 public byte RegionAccess;
61 } 62 }
62 63
64 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LandManagementModule")]
63 public class LandManagementModule : INonSharedRegionModule 65 public class LandManagementModule : INonSharedRegionModule
64 { 66 {
65 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 67 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -927,6 +929,7 @@ namespace OpenSim.Region.CoreModules.World.Land
927 ILandObject newLand = startLandObject.Copy(); 929 ILandObject newLand = startLandObject.Copy();
928 newLand.LandData.Name = newLand.LandData.Name; 930 newLand.LandData.Name = newLand.LandData.Name;
929 newLand.LandData.GlobalID = UUID.Random(); 931 newLand.LandData.GlobalID = UUID.Random();
932 newLand.LandData.Dwell = 0;
930 933
931 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); 934 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y));
932 935
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 4f06737..d5b2adb 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -33,6 +33,7 @@ using OpenMetaverse;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
36using RegionFlags = OpenMetaverse.RegionFlags;
36 37
37namespace OpenSim.Region.CoreModules.World.Land 38namespace OpenSim.Region.CoreModules.World.Land
38{ 39{
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
index 102b4d7..55b8227 100644
--- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
@@ -34,6 +34,7 @@ using log4net;
34using Nini.Config; 34using Nini.Config;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using Mono.Addins;
37using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
@@ -49,6 +50,7 @@ namespace OpenSim.Region.CoreModules.World.Land
49 public Dictionary <UUID, int> Users = new Dictionary <UUID, int>(); 50 public Dictionary <UUID, int> Users = new Dictionary <UUID, int>();
50 } 51 }
51 52
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PrimCountModule")]
52 public class PrimCountModule : IPrimCountModule, INonSharedRegionModule 54 public class PrimCountModule : IPrimCountModule, INonSharedRegionModule
53 { 55 {
54// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 56// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -69,7 +71,7 @@ namespace OpenSim.Region.CoreModules.World.Land
69 /// without recounting the whole sim. 71 /// without recounting the whole sim.
70 /// 72 ///
71 /// We start out tainted so that the first get call resets the various prim counts. 73 /// We start out tainted so that the first get call resets the various prim counts.
72 /// <value> 74 /// </value>
73 private bool m_Tainted = true; 75 private bool m_Tainted = true;
74 76
75 private Object m_TaintLock = new Object(); 77 private Object m_TaintLock = new Object();
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index aa306c7..8a422b0 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.Drawing; 30using System.Drawing;
31using System.Reflection; 31using System.Reflection;
32using log4net; 32using log4net;
33using Mono.Addins;
33using Nini.Config; 34using Nini.Config;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenMetaverse.Imaging; 36using OpenMetaverse.Imaging;
@@ -59,6 +60,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
59 public face[] trns; 60 public face[] trns;
60 } 61 }
61 62
63 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MapImageModule")]
62 public class MapImageModule : IMapImageGenerator, INonSharedRegionModule 64 public class MapImageModule : IMapImageGenerator, INonSharedRegionModule
63 { 65 {
64 private static readonly ILog m_log = 66 private static readonly ILog m_log =
@@ -131,7 +133,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
131 133
132 #endregion 134 #endregion
133 135
134 #region IRegionModule Members 136 #region Region Module interface
135 137
136 public void Initialise(IConfigSource source) 138 public void Initialise(IConfigSource source)
137 { 139 {
diff --git a/OpenSim/Region/CoreModules/LightShare/EnvironmentModule.cs b/OpenSim/Region/CoreModules/World/LightShare/EnvironmentModule.cs
index 1526886..c3cea7a 100644
--- a/OpenSim/Region/CoreModules/LightShare/EnvironmentModule.cs
+++ b/OpenSim/Region/CoreModules/World/LightShare/EnvironmentModule.cs
@@ -51,10 +51,10 @@ namespace OpenSim.Region.CoreModules.World.LightShare
51 private Scene m_scene = null; 51 private Scene m_scene = null;
52 private UUID regionID = UUID.Zero; 52 private UUID regionID = UUID.Zero;
53 private static bool Enabled = false; 53 private static bool Enabled = false;
54 54
55 private static readonly string capsName = "EnvironmentSettings"; 55 private static readonly string capsName = "EnvironmentSettings";
56 private static readonly string capsBase = "/CAPS/0020/"; 56 private static readonly string capsBase = "/CAPS/0020/";
57 57
58 private LLSDEnvironmentSetResponse setResponse = null; 58 private LLSDEnvironmentSetResponse setResponse = null;
59 59
60 #region INonSharedRegionModule 60 #region INonSharedRegionModule
@@ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.World.LightShare
72 } 72 }
73 73
74 Enabled = true; 74 Enabled = true;
75 75
76 m_log.InfoFormat("[{0}]: Module is enabled.", Name); 76 m_log.InfoFormat("[{0}]: Module is enabled.", Name);
77 } 77 }
78 78
@@ -132,8 +132,8 @@ namespace OpenSim.Region.CoreModules.World.LightShare
132 #region Events 132 #region Events
133 private void OnRegisterCaps(UUID agentID, Caps caps) 133 private void OnRegisterCaps(UUID agentID, Caps caps)
134 { 134 {
135// m_log.DebugFormat("[{0}]: Register capability for agentID {1} in region {2}", 135 // m_log.DebugFormat("[{0}]: Register capability for agentID {1} in region {2}",
136// Name, agentID, caps.RegionName); 136 // Name, agentID, caps.RegionName);
137 137
138 string capsPath = capsBase + UUID.Random(); 138 string capsPath = capsBase + UUID.Random();
139 139
@@ -163,8 +163,8 @@ namespace OpenSim.Region.CoreModules.World.LightShare
163 private string GetEnvironmentSettings(string request, string path, string param, 163 private string GetEnvironmentSettings(string request, string path, string param,
164 UUID agentID, Caps caps) 164 UUID agentID, Caps caps)
165 { 165 {
166// m_log.DebugFormat("[{0}]: Environment GET handle for agentID {1} in region {2}", 166 // m_log.DebugFormat("[{0}]: Environment GET handle for agentID {1} in region {2}",
167// Name, agentID, caps.RegionName); 167 // Name, agentID, caps.RegionName);
168 168
169 string env = String.Empty; 169 string env = String.Empty;
170 170
@@ -188,8 +188,8 @@ namespace OpenSim.Region.CoreModules.World.LightShare
188 UUID agentID, Caps caps) 188 UUID agentID, Caps caps)
189 { 189 {
190 190
191// m_log.DebugFormat("[{0}]: Environment SET handle from agentID {1} in region {2}", 191 // m_log.DebugFormat("[{0}]: Environment SET handle from agentID {1} in region {2}",
192// Name, agentID, caps.RegionName); 192 // Name, agentID, caps.RegionName);
193 193
194 setResponse.regionID = regionID; 194 setResponse.regionID = regionID;
195 setResponse.success = false; 195 setResponse.success = false;
@@ -204,7 +204,7 @@ namespace OpenSim.Region.CoreModules.World.LightShare
204 { 204 {
205 m_scene.SimulationDataService.StoreRegionEnvironmentSettings(regionID, request); 205 m_scene.SimulationDataService.StoreRegionEnvironmentSettings(regionID, request);
206 setResponse.success = true; 206 setResponse.success = true;
207 207
208 m_log.InfoFormat("[{0}]: New Environment settings has been saved from agentID {1} in region {2}", 208 m_log.InfoFormat("[{0}]: New Environment settings has been saved from agentID {1} in region {2}",
209 Name, agentID, caps.RegionName); 209 Name, agentID, caps.RegionName);
210 } 210 }
diff --git a/OpenSim/Region/CoreModules/LightShare/LightShareModule.cs b/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs
index f49641f..6f92ef6 100644
--- a/OpenSim/Region/CoreModules/LightShare/LightShareModule.cs
+++ b/OpenSim/Region/CoreModules/World/LightShare/LightShareModule.cs
@@ -27,21 +27,20 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO;
31using System.Reflection; 30using System.Reflection;
32using OpenMetaverse; 31using OpenMetaverse;
33using log4net;
34using Nini.Config;
35using OpenSim.Data;
36using OpenSim.Framework; 32using OpenSim.Framework;
37using OpenSim.Region.CoreModules.Framework.InterfaceCommander; 33using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
38using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
40 36using log4net;
37using Nini.Config;
38using Mono.Addins;
41 39
42namespace OpenSim.Region.CoreModules.World.LightShare 40namespace OpenSim.Region.CoreModules.World.LightShare
43{ 41{
44 public class LightShareModule : IRegionModule, ICommandableModule 42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LightShareModule")]
43 public class LightShareModule : INonSharedRegionModule, ILightShareModule, ICommandableModule
45 { 44 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 private readonly Commander m_commander = new Commander("windlight"); 46 private readonly Commander m_commander = new Commander("windlight");
@@ -57,48 +56,86 @@ namespace OpenSim.Region.CoreModules.World.LightShare
57 56
58 #endregion 57 #endregion
59 58
60 #region IRegionModule Members 59 #region INonSharedRegionModule Members
61 60
62 public static bool EnableWindlight 61 public void Initialise(IConfigSource config)
63 { 62 {
64 get 63 try
65 { 64 {
66 return m_enableWindlight; 65 m_enableWindlight = config.Configs["LightShare"].GetBoolean("enable_windlight", false);
67 } 66 }
68 set 67 catch (Exception)
69 { 68 {
69 m_log.Debug("[WINDLIGHT]: ini failure for enable_windlight - using default");
70 } 70 }
71
72 m_log.DebugFormat("[WINDLIGHT]: windlight module {0}", (m_enableWindlight ? "enabled" : "disabled"));
71 } 73 }
72 74
73 public void Initialise(Scene scene, IConfigSource config) 75 public void AddRegion(Scene scene)
74 { 76 {
77 if (!m_enableWindlight)
78 return;
79
75 m_scene = scene; 80 m_scene = scene;
76 m_scene.RegisterModuleInterface<IRegionModule>(this); 81 m_scene.RegisterModuleInterface<ILightShareModule>(this);
77 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; 82 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
78 83
79 // ini file settings 84 m_scene.EventManager.OnMakeRootAgent += EventManager_OnMakeRootAgent;
80 try 85 m_scene.EventManager.OnSaveNewWindlightProfile += EventManager_OnSaveNewWindlightProfile;
81 { 86 m_scene.EventManager.OnSendNewWindlightProfileTargeted += EventManager_OnSendNewWindlightProfileTargeted;
82 m_enableWindlight = config.Configs["LightShare"].GetBoolean("enable_windlight", false); 87 m_scene.LoadWindlightProfile();
83 } 88
84 catch (Exception) 89 InstallCommands();
90 }
91
92 public void RemoveRegion(Scene scene)
93 {
94 if (!m_enableWindlight)
95 return;
96
97 m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole;
98
99 m_scene.EventManager.OnMakeRootAgent -= EventManager_OnMakeRootAgent;
100 m_scene.EventManager.OnSaveNewWindlightProfile -= EventManager_OnSaveNewWindlightProfile;
101 m_scene.EventManager.OnSendNewWindlightProfileTargeted -= EventManager_OnSendNewWindlightProfileTargeted;
102
103 m_scene = null;
104 }
105
106 public void Close()
107 {
108 }
109
110 public string Name
111 {
112 get { return "LightShareModule"; }
113 }
114
115 public void RegionLoaded(Scene scene)
116 {
117 }
118
119 public Type ReplaceableInterface
120 {
121 get { return null; }
122 }
123
124 #endregion
125
126 public static bool EnableWindlight
127 {
128 get
85 { 129 {
86 m_log.Debug("[WINDLIGHT]: ini failure for enable_windlight - using default"); 130 return m_enableWindlight;
87 } 131 }
88 132 set
89 if (m_enableWindlight)
90 { 133 {
91 m_scene.EventManager.OnMakeRootAgent += EventManager_OnMakeRootAgent;
92 m_scene.EventManager.OnSaveNewWindlightProfile += EventManager_OnSaveNewWindlightProfile;
93 m_scene.EventManager.OnSendNewWindlightProfileTargeted += EventManager_OnSendNewWindlightProfileTargeted;
94 m_scene.LoadWindlightProfile();
95 } 134 }
96
97 InstallCommands();
98
99 m_log.Debug("[WINDLIGHT]: Initialised windlight module");
100 } 135 }
101 136
137 #region events
138
102 private List<byte[]> compileWindlightSettings(RegionLightShareData wl) 139 private List<byte[]> compileWindlightSettings(RegionLightShareData wl)
103 { 140 {
104 byte[] mBlock = new Byte[249]; 141 byte[] mBlock = new Byte[249];
@@ -153,6 +190,9 @@ namespace OpenSim.Region.CoreModules.World.LightShare
153 190
154 public void SendProfileToClient(IClientAPI client, RegionLightShareData wl) 191 public void SendProfileToClient(IClientAPI client, RegionLightShareData wl)
155 { 192 {
193 if (client == null)
194 return;
195
156 if (m_enableWindlight) 196 if (m_enableWindlight)
157 { 197 {
158 if (m_scene.RegionInfo.WindlightSettings.valid) 198 if (m_scene.RegionInfo.WindlightSettings.valid)
@@ -187,29 +227,6 @@ namespace OpenSim.Region.CoreModules.World.LightShare
187 m_scene.ForEachRootClient(SendProfileToClient); 227 m_scene.ForEachRootClient(SendProfileToClient);
188 } 228 }
189 229
190 public void PostInitialise()
191 {
192
193 }
194
195 public void Close()
196 {
197 }
198
199 public string Name
200 {
201 get { return "LightShareModule"; }
202 }
203
204 public bool IsSharedModule
205 {
206 get { return false; }
207 }
208
209 #endregion
210
211 #region events
212
213 #endregion 230 #endregion
214 231
215 #region ICommandableModule Members 232 #region ICommandableModule Members
@@ -244,7 +261,7 @@ namespace OpenSim.Region.CoreModules.World.LightShare
244 private void HandleDisable(Object[] args) 261 private void HandleDisable(Object[] args)
245 { 262 {
246 m_log.InfoFormat("[WINDLIGHT]: Plugin now disabled"); 263 m_log.InfoFormat("[WINDLIGHT]: Plugin now disabled");
247 m_enableWindlight=false; 264 m_enableWindlight = false;
248 } 265 }
249 266
250 private void HandleEnable(Object[] args) 267 private void HandleEnable(Object[] args)
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index 09f6758..ab8f143 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -27,9 +27,12 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO;
31using System.Linq;
30using System.Reflection; 32using System.Reflection;
31using System.Text; 33using System.Text;
32using System.Text.RegularExpressions; 34using System.Text.RegularExpressions;
35using System.Xml;
33using log4net; 36using log4net;
34using Mono.Addins; 37using Mono.Addins;
35using NDesk.Options; 38using NDesk.Options;
@@ -40,6 +43,7 @@ using OpenSim.Framework.Console;
40using OpenSim.Framework.Monitoring; 43using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Interfaces; 44using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 45using OpenSim.Region.Framework.Scenes;
46using OpenSim.Region.Framework.Scenes.Serialization;
43 47
44namespace OpenSim.Region.CoreModules.World.Objects.Commands 48namespace OpenSim.Region.CoreModules.World.Objects.Commands
45{ 49{
@@ -83,52 +87,85 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
83 m_console.Commands.AddCommand( 87 m_console.Commands.AddCommand(
84 "Objects", false, "delete object owner", 88 "Objects", false, "delete object owner",
85 "delete object owner <UUID>", 89 "delete object owner <UUID>",
86 "Delete a scene object by owner", HandleDeleteObject); 90 "Delete scene objects by owner",
91 "Command will ask for confirmation before proceeding.",
92 HandleDeleteObject);
87 93
88 m_console.Commands.AddCommand( 94 m_console.Commands.AddCommand(
89 "Objects", false, "delete object creator", 95 "Objects", false, "delete object creator",
90 "delete object creator <UUID>", 96 "delete object creator <UUID>",
91 "Delete a scene object by creator", HandleDeleteObject); 97 "Delete scene objects by creator",
98 "Command will ask for confirmation before proceeding.",
99 HandleDeleteObject);
92 100
93 m_console.Commands.AddCommand( 101 m_console.Commands.AddCommand(
94 "Objects", false, "delete object uuid", 102 "Objects", false, "delete object id",
95 "delete object uuid <UUID>", 103 "delete object id <UUID-or-localID>",
96 "Delete a scene object by uuid", HandleDeleteObject); 104 "Delete a scene object by uuid or localID",
105 HandleDeleteObject);
97 106
98 m_console.Commands.AddCommand( 107 m_console.Commands.AddCommand(
99 "Objects", false, "delete object name", 108 "Objects", false, "delete object name",
100 "delete object name [--regex] <name>", 109 "delete object name [--regex] <name>",
101 "Delete a scene object by name.", 110 "Delete a scene object by name.",
102 "If --regex is specified then the name is treatead as a regular expression", 111 "Command will ask for confirmation before proceeding.\n"
112 + "If --regex is specified then the name is treatead as a regular expression",
103 HandleDeleteObject); 113 HandleDeleteObject);
104 114
105 m_console.Commands.AddCommand( 115 m_console.Commands.AddCommand(
106 "Objects", false, "delete object outside", 116 "Objects", false, "delete object outside",
107 "delete object outside", 117 "delete object outside",
108 "Delete all scene objects outside region boundaries", HandleDeleteObject); 118 "Delete all scene objects outside region boundaries",
119 "Command will ask for confirmation before proceeding.",
120 HandleDeleteObject);
109 121
110 m_console.Commands.AddCommand( 122 m_console.Commands.AddCommand(
111 "Objects", 123 "Objects",
112 false, 124 false,
113 "show object uuid", 125 "delete object pos",
114 "show object uuid <UUID>", 126 "delete object pos <start-coord> to <end-coord>",
115 "Show details of a scene object with the given UUID", HandleShowObjectByUuid); 127 "Delete scene objects within the given area.",
128 ConsoleUtil.CoordHelp,
129 HandleDeleteObject);
130
131 m_console.Commands.AddCommand(
132 "Objects",
133 false,
134 "show object id",
135 "show object id [--full] <UUID-or-localID>",
136 "Show details of a scene object with the given UUID or localID",
137 "The --full option will print out information on all the parts of the object.\n"
138 + "For yet more detailed part information, use the \"show part\" commands.",
139 HandleShowObjectById);
116 140
117 m_console.Commands.AddCommand( 141 m_console.Commands.AddCommand(
118 "Objects", 142 "Objects",
119 false, 143 false,
120 "show object name", 144 "show object name",
121 "show object name [--regex] <name>", 145 "show object name [--full] [--regex] <name>",
122 "Show details of scene objects with the given name.", 146 "Show details of scene objects with the given name.",
123 "If --regex is specified then the name is treatead as a regular expression", 147 "The --full option will print out information on all the parts of the object.\n"
148 + "For yet more detailed part information, use the \"show part\" commands.\n"
149 + "If --regex is specified then the name is treatead as a regular expression.",
124 HandleShowObjectByName); 150 HandleShowObjectByName);
125 151
126 m_console.Commands.AddCommand( 152 m_console.Commands.AddCommand(
127 "Objects", 153 "Objects",
128 false, 154 false,
129 "show part uuid", 155 "show object pos",
130 "show part uuid <UUID>", 156 "show object pos [--full] <start-coord> to <end-coord>",
131 "Show details of a scene object parts with the given UUID", HandleShowPartByUuid); 157 "Show details of scene objects within the given area.",
158 "The --full option will print out information on all the parts of the object.\n"
159 + "For yet more detailed part information, use the \"show part\" commands.\n"
160 + ConsoleUtil.CoordHelp,
161 HandleShowObjectByPos);
162
163 m_console.Commands.AddCommand(
164 "Objects",
165 false,
166 "show part id",
167 "show part id <UUID-or-localID>",
168 "Show details of a scene object part with the given UUID or localID", HandleShowPartById);
132 169
133 m_console.Commands.AddCommand( 170 m_console.Commands.AddCommand(
134 "Objects", 171 "Objects",
@@ -136,8 +173,28 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
136 "show part name", 173 "show part name",
137 "show part name [--regex] <name>", 174 "show part name [--regex] <name>",
138 "Show details of scene object parts with the given name.", 175 "Show details of scene object parts with the given name.",
139 "If --regex is specified then the name is treatead as a regular expression", 176 "If --regex is specified then the name is treated as a regular expression",
140 HandleShowPartByName); 177 HandleShowPartByName);
178
179 m_console.Commands.AddCommand(
180 "Objects",
181 false,
182 "show part pos",
183 "show part pos <start-coord> to <end-coord>",
184 "Show details of scene object parts within the given area.",
185 ConsoleUtil.CoordHelp,
186 HandleShowPartByPos);
187
188 m_console.Commands.AddCommand(
189 "Objects",
190 false,
191 "dump object id",
192 "dump object id <UUID-or-localID>",
193 "Dump the formatted serialization of the given object to the file <UUID>.xml",
194 "e.g. dump object uuid c1ed6809-cc24-4061-a4c2-93082a2d1f1d will dump serialization to c1ed6809-cc24-4061-a4c2-93082a2d1f1d.xml\n"
195 + "To locate the UUID or localID in the first place, you need to use the other show object commands.\n"
196 + "If a local ID is given then the filename used is still that for the UUID",
197 HandleDumpObjectById);
141 } 198 }
142 199
143 public void RemoveRegion(Scene scene) 200 public void RemoveRegion(Scene scene)
@@ -150,25 +207,75 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
150// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); 207// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
151 } 208 }
152 209
153 private void HandleShowObjectByUuid(string module, string[] cmd) 210 /// <summary>
211 /// Outputs the sogs to console.
212 /// </summary>
213 /// <param name='searchPredicate'></param>
214 /// <param name='showFull'>If true then output all part details. If false then output summary.</param>
215 private void OutputSogsToConsole(Predicate<SceneObjectGroup> searchPredicate, bool showFull)
216 {
217 List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups().FindAll(searchPredicate);
218
219 StringBuilder sb = new StringBuilder();
220
221 foreach (SceneObjectGroup so in sceneObjects)
222 {
223 AddSceneObjectReport(sb, so, showFull);
224 sb.Append("\n");
225 }
226
227 sb.AppendFormat("{0} object(s) found in {1}\n", sceneObjects.Count, m_scene.Name);
228
229 m_console.OutputFormat(sb.ToString());
230 }
231
232 private void OutputSopsToConsole(Predicate<SceneObjectPart> searchPredicate, bool showFull)
233 {
234 List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups();
235 List<SceneObjectPart> parts = new List<SceneObjectPart>();
236
237 sceneObjects.ForEach(so => parts.AddRange(Array.FindAll<SceneObjectPart>(so.Parts, searchPredicate)));
238
239 StringBuilder sb = new StringBuilder();
240
241 foreach (SceneObjectPart part in parts)
242 {
243 AddScenePartReport(sb, part, showFull);
244 sb.Append("\n");
245 }
246
247 sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name);
248
249 m_console.OutputFormat(sb.ToString());
250 }
251
252 private void HandleShowObjectById(string module, string[] cmdparams)
154 { 253 {
155 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 254 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
156 return; 255 return;
157 256
158 if (cmd.Length < 4) 257 bool showFull = false;
258 OptionSet options = new OptionSet().Add("full", v => showFull = v != null );
259
260 List<string> mainParams = options.Parse(cmdparams);
261
262 if (mainParams.Count < 4)
159 { 263 {
160 m_console.OutputFormat("Usage: show object uuid <uuid>"); 264 m_console.OutputFormat("Usage: show object uuid <uuid>");
161 return; 265 return;
162 } 266 }
163 267
164 UUID objectUuid; 268 UUID uuid;
165 if (!UUID.TryParse(cmd[3], out objectUuid)) 269 uint localId;
166 { 270 if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out uuid, out localId))
167 m_console.OutputFormat("{0} is not a valid uuid", cmd[3]);
168 return; 271 return;
169 }
170 272
171 SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid); 273 SceneObjectGroup so;
274
275 if (localId != ConsoleUtil.LocalIdNotFound)
276 so = m_scene.GetSceneObjectGroup(localId);
277 else
278 so = m_scene.GetSceneObjectGroup(uuid);
172 279
173 if (so == null) 280 if (so == null)
174 { 281 {
@@ -177,7 +284,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
177 } 284 }
178 285
179 StringBuilder sb = new StringBuilder(); 286 StringBuilder sb = new StringBuilder();
180 AddSceneObjectReport(sb, so); 287 AddSceneObjectReport(sb, so, showFull);
181 288
182 m_console.OutputFormat(sb.ToString()); 289 m_console.OutputFormat(sb.ToString());
183 } 290 }
@@ -187,70 +294,91 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
187 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 294 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
188 return; 295 return;
189 296
297 bool showFull = false;
190 bool useRegex = false; 298 bool useRegex = false;
191 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); 299 OptionSet options = new OptionSet();
300 options.Add("full", v => showFull = v != null );
301 options.Add("regex", v => useRegex = v != null );
192 302
193 List<string> mainParams = options.Parse(cmdparams); 303 List<string> mainParams = options.Parse(cmdparams);
194 304
195 if (mainParams.Count < 4) 305 if (mainParams.Count < 4)
196 { 306 {
197 m_console.OutputFormat("Usage: show object name [--regex] <name>"); 307 m_console.OutputFormat("Usage: show object name [--full] [--regex] <name>");
198 return; 308 return;
199 } 309 }
200 310
201 string name = mainParams[3]; 311 string name = mainParams[3];
202 312
203 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); 313 Predicate<SceneObjectGroup> searchPredicate;
204 Action<SceneObjectGroup> searchAction;
205 314
206 if (useRegex) 315 if (useRegex)
207 { 316 {
208 Regex nameRegex = new Regex(name); 317 Regex nameRegex = new Regex(name);
209 searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }}; 318 searchPredicate = so => nameRegex.IsMatch(so.Name);
210 } 319 }
211 else 320 else
212 { 321 {
213 searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }}; 322 searchPredicate = so => so.Name == name;
214 } 323 }
215 324
216 m_scene.ForEachSOG(searchAction); 325 OutputSogsToConsole(searchPredicate, showFull);
326 }
217 327
218 if (sceneObjects.Count == 0) 328 private void HandleShowObjectByPos(string module, string[] cmdparams)
219 { 329 {
220 m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); 330 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
221 return; 331 return;
222 }
223 332
224 StringBuilder sb = new StringBuilder(); 333 bool showFull = false;
334 OptionSet options = new OptionSet().Add("full", v => showFull = v != null );
225 335
226 foreach (SceneObjectGroup so in sceneObjects) 336 List<string> mainParams = options.Parse(cmdparams);
337
338 if (mainParams.Count < 5)
227 { 339 {
228 AddSceneObjectReport(sb, so); 340 m_console.OutputFormat("Usage: show object pos [--full] <start-coord> to <end-coord>");
229 sb.Append("\n"); 341 return;
230 } 342 }
231 343
232 m_console.OutputFormat(sb.ToString()); 344 Vector3 startVector, endVector;
345
346 if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector))
347 return;
348
349 Predicate<SceneObjectGroup> searchPredicate
350 = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector);
351
352 OutputSogsToConsole(searchPredicate, showFull);
233 } 353 }
234 354
235 private void HandleShowPartByUuid(string module, string[] cmd) 355 private void HandleShowPartById(string module, string[] cmdparams)
236 { 356 {
237 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 357 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
238 return; 358 return;
239 359
240 if (cmd.Length < 4) 360// bool showFull = false;
361 OptionSet options = new OptionSet();
362// options.Add("full", v => showFull = v != null );
363
364 List<string> mainParams = options.Parse(cmdparams);
365
366 if (mainParams.Count < 4)
241 { 367 {
242 m_console.OutputFormat("Usage: show part uuid <uuid>"); 368 m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>");
243 return; 369 return;
244 } 370 }
245 371
246 UUID objectUuid; 372 UUID objectUuid;
247 if (!UUID.TryParse(cmd[3], out objectUuid)) 373 uint localId;
248 { 374 if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out objectUuid, out localId))
249 m_console.OutputFormat("{0} is not a valid uuid", cmd[3]);
250 return; 375 return;
251 }
252 376
253 SceneObjectPart sop = m_scene.GetSceneObjectPart(objectUuid); 377 SceneObjectPart sop;
378 if (localId == ConsoleUtil.LocalIdNotFound)
379 sop = m_scene.GetSceneObjectPart(objectUuid);
380 else
381 sop = m_scene.GetSceneObjectPart(localId);
254 382
255 if (sop == null) 383 if (sop == null)
256 { 384 {
@@ -259,84 +387,239 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
259 } 387 }
260 388
261 StringBuilder sb = new StringBuilder(); 389 StringBuilder sb = new StringBuilder();
262 AddScenePartReport(sb, sop); 390 AddScenePartReport(sb, sop, true);
263 391
264 m_console.OutputFormat(sb.ToString()); 392 m_console.OutputFormat(sb.ToString());
265 } 393 }
266 394
395 private void HandleShowPartByPos(string module, string[] cmdparams)
396 {
397 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
398 return;
399
400// bool showFull = false;
401 OptionSet options = new OptionSet();
402// options.Add("full", v => showFull = v != null );
403
404 List<string> mainParams = options.Parse(cmdparams);
405
406 if (mainParams.Count < 5)
407 {
408 m_console.OutputFormat("Usage: show part pos [--full] <start-coord> to <end-coord>");
409 return;
410 }
411
412 string rawConsoleStartVector = mainParams[3];
413 Vector3 startVector;
414
415 if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
416 {
417 m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector);
418 return;
419 }
420
421 string rawConsoleEndVector = mainParams[5];
422 Vector3 endVector;
423
424 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
425 {
426 m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector);
427 return;
428 }
429
430 OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector), true);
431 }
432
267 private void HandleShowPartByName(string module, string[] cmdparams) 433 private void HandleShowPartByName(string module, string[] cmdparams)
268 { 434 {
269 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 435 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
270 return; 436 return;
271 437
438// bool showFull = false;
272 bool useRegex = false; 439 bool useRegex = false;
273 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); 440 OptionSet options = new OptionSet();
441// options.Add("full", v => showFull = v != null );
442 options.Add("regex", v => useRegex = v != null );
274 443
275 List<string> mainParams = options.Parse(cmdparams); 444 List<string> mainParams = options.Parse(cmdparams);
276 445
277 if (mainParams.Count < 4) 446 if (mainParams.Count < 4)
278 { 447 {
279 m_console.OutputFormat("Usage: show part name [--regex] <name>"); 448 m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>");
280 return; 449 return;
281 } 450 }
282 451
283 string name = mainParams[3]; 452 string name = mainParams[3];
284 453
285 List<SceneObjectPart> parts = new List<SceneObjectPart>(); 454 Predicate<SceneObjectPart> searchPredicate;
286
287 Action<SceneObjectGroup> searchAction;
288 455
289 if (useRegex) 456 if (useRegex)
290 { 457 {
291 Regex nameRegex = new Regex(name); 458 Regex nameRegex = new Regex(name);
292 searchAction = so => so.ForEachPart(sop => { if (nameRegex.IsMatch(sop.Name)) { parts.Add(sop); } }); 459 searchPredicate = sop => nameRegex.IsMatch(sop.Name);
293 } 460 }
294 else 461 else
295 { 462 {
296 searchAction = so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } }); 463 searchPredicate = sop => sop.Name == name;
297 } 464 }
298 465
299 m_scene.ForEachSOG(searchAction); 466 OutputSopsToConsole(searchPredicate, true);
467 }
468
469 private void HandleDumpObjectById(string module, string[] cmdparams)
470 {
471 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
472 return;
300 473
301 if (parts.Count == 0) 474 if (cmdparams.Length < 4)
302 { 475 {
303 m_console.OutputFormat("No parts with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); 476 m_console.OutputFormat("Usage: dump object id <UUID-or-localID>");
304 return; 477 return;
305 } 478 }
306 479
307 StringBuilder sb = new StringBuilder(); 480 UUID objectUuid;
481 uint localId;
482 if (!ConsoleUtil.TryParseConsoleId(m_console, cmdparams[3], out objectUuid, out localId))
483 return;
308 484
309 foreach (SceneObjectPart part in parts) 485 SceneObjectGroup so;
486 if (localId == ConsoleUtil.LocalIdNotFound)
487 so = m_scene.GetSceneObjectGroup(objectUuid);
488 else
489 so = m_scene.GetSceneObjectGroup(localId);
490
491 if (so == null)
310 { 492 {
311 AddScenePartReport(sb, part); 493// m_console.OutputFormat("No part found with uuid {0}", objectUuid);
312 sb.Append("\n"); 494 return;
313 } 495 }
314 496
315 m_console.OutputFormat(sb.ToString()); 497 // In case we found it via local ID.
498 objectUuid = so.UUID;
499
500 string fileName = string.Format("{0}.xml", objectUuid);
501
502 if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName))
503 return;
504
505 using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8))
506 {
507 xtw.Formatting = Formatting.Indented;
508 SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true);
509 }
510
511 m_console.OutputFormat("Object dumped to file {0}", fileName);
316 } 512 }
317 513
318 private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so) 514 /// <summary>
515 /// Append a scene object report to an input StringBuilder
516 /// </summary>
517 /// <returns></returns>
518 /// <param name='sb'></param>
519 /// <param name='so'</param>
520 /// <param name='showFull'>
521 /// If true then information on all parts of an object is appended.
522 /// If false then only summary information about an object is appended.
523 /// </param>
524 private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so, bool showFull)
319 { 525 {
320 sb.AppendFormat("Name: {0}\n", so.Name); 526 if (showFull)
321 sb.AppendFormat("Description: {0}\n", so.Description); 527 {
322 sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName); 528 foreach (SceneObjectPart sop in so.Parts)
323 sb.AppendFormat("Parts: {0}\n", so.PrimCount); 529 {
324 sb.AppendFormat("Flags: {0}\n", so.RootPart.Flags); 530 AddScenePartReport(sb, sop, false);
531 sb.Append("\n");
532 }
533 }
534 else
535 {
536 AddSummarySceneObjectReport(sb, so);
537 }
325 538
326 return sb; 539 return sb;
327 } 540 }
328 541
329 private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop) 542 private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so)
330 { 543 {
331 sb.AppendFormat("Name: {0}\n", sop.Name); 544 ConsoleDisplayList cdl = new ConsoleDisplayList();
332 sb.AppendFormat("Description: {0}\n", sop.Description); 545 cdl.AddRow("Name", so.Name);
333 sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName); 546 cdl.AddRow("Descrition", so.Description);
334 sb.AppendFormat("Parent: {0}", 547 cdl.AddRow("Local ID", so.LocalId);
335 sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); 548 cdl.AddRow("UUID", so.UUID);
336 sb.AppendFormat("Link number: {0}\n", sop.LinkNum); 549 cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name));
337 sb.AppendFormat("Flags: {0}\n", sop.Flags); 550 cdl.AddRow("Parts", so.PrimCount);
551 cdl.AddRow("Flags", so.RootPart.Flags);
552
553 return sb.Append(cdl.ToString());
554 }
338 555
339 return sb; 556 /// <summary>
557 /// Append a scene object part report to an input StringBuilder
558 /// </summary>
559 /// <returns></returns>
560 /// <param name='sb'></param>
561 /// <param name='sop'</param>
562 /// <param name='showFull'>
563 /// If true then information on each inventory item will be shown.
564 /// If false then only summary inventory information is shown.
565 /// </param>
566 private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop, bool showFull)
567 {
568 ConsoleDisplayList cdl = new ConsoleDisplayList();
569 cdl.AddRow("Name", sop.Name);
570 cdl.AddRow("Description", sop.Description);
571 cdl.AddRow("Local ID", sop.LocalId);
572 cdl.AddRow("UUID", sop.UUID);
573 cdl.AddRow("Location", string.Format("{0} @ {1}", sop.AbsolutePosition, sop.ParentGroup.Scene.Name));
574 cdl.AddRow(
575 "Parent",
576 sop.IsRoot ? "Is Root" : string.Format("{0} {1}", sop.ParentGroup.Name, sop.ParentGroup.UUID));
577 cdl.AddRow("Link number", sop.LinkNum);
578 cdl.AddRow("Flags", sop.Flags);
579
580 object itemsOutput;
581 if (showFull)
582 {
583 StringBuilder itemsSb = new StringBuilder("\n");
584 itemsOutput = AddScenePartItemsReport(itemsSb, sop.Inventory).ToString();
585 }
586 else
587 {
588 itemsOutput = sop.Inventory.Count;
589 }
590
591
592 cdl.AddRow("Items", itemsOutput);
593
594 return sb.Append(cdl.ToString());
595 }
596
597 private StringBuilder AddScenePartItemsReport(StringBuilder sb, IEntityInventory inv)
598 {
599 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
600 cdt.Indent = 2;
601
602 cdt.AddColumn("Name", 50);
603 cdt.AddColumn("Type", 12);
604 cdt.AddColumn("Running", 7);
605 cdt.AddColumn("Item UUID", 36);
606 cdt.AddColumn("Asset UUID", 36);
607
608 foreach (TaskInventoryItem item in inv.GetInventoryItems())
609 {
610 bool foundScriptInstance, scriptRunning;
611 foundScriptInstance
612 = SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, item, out scriptRunning);
613
614 cdt.AddRow(
615 item.Name,
616 ((InventoryType)item.InvType).ToString(),
617 foundScriptInstance ? scriptRunning.ToString() : "n/a",
618 item.ItemID.ToString(),
619 item.AssetID.ToString());
620 }
621
622 return sb.Append(cdt.ToString());
340 } 623 }
341 624
342 private void HandleDeleteObject(string module, string[] cmd) 625 private void HandleDeleteObject(string module, string[] cmd)
@@ -398,19 +681,24 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
398 681
399 break; 682 break;
400 683
401 case "uuid": 684 case "id":
402 if (!UUID.TryParse(o, out match)) 685 UUID uuid;
686 uint localId;
687 if (!ConsoleUtil.TryParseConsoleId(m_console, o, out uuid, out localId))
403 return; 688 return;
404 689
405 requireConfirmation = false; 690 requireConfirmation = false;
406 deletes = new List<SceneObjectGroup>(); 691 deletes = new List<SceneObjectGroup>();
407 692
408 m_scene.ForEachSOG(delegate (SceneObjectGroup g) 693 SceneObjectGroup so;
409 { 694 if (localId == ConsoleUtil.LocalIdNotFound)
410 if (g.UUID == match && !g.IsAttachment) 695 so = m_scene.GetSceneObjectGroup(uuid);
411 deletes.Add(g); 696 else
412 }); 697 so = m_scene.GetSceneObjectGroup(localId);
413 698
699 if (!so.IsAttachment)
700 deletes.Add(so);
701
414 // if (deletes.Count == 0) 702 // if (deletes.Count == 0)
415 // m_console.OutputFormat("No objects were found with uuid {0}", match); 703 // m_console.OutputFormat("No objects were found with uuid {0}", match);
416 704
@@ -450,6 +738,10 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
450 738
451 break; 739 break;
452 740
741 case "pos":
742 deletes = GetDeleteCandidatesByPos(module, cmd);
743 break;
744
453 default: 745 default:
454 m_console.OutputFormat("Unrecognized mode {0}", mode); 746 m_console.OutputFormat("Unrecognized mode {0}", mode);
455 return; 747 return;
@@ -464,7 +756,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
464 string.Format( 756 string.Format(
465 "Are you sure that you want to delete {0} objects from {1}", 757 "Are you sure that you want to delete {0} objects from {1}",
466 deletes.Count, m_scene.RegionInfo.RegionName), 758 deletes.Count, m_scene.RegionInfo.RegionName),
467 "n"); 759 "y/N");
468 760
469 if (response.ToLower() != "y") 761 if (response.ToLower() != "y")
470 { 762 {
@@ -486,9 +778,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
486 778
487 private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams) 779 private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams)
488 { 780 {
489 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
490 return null;
491
492 bool useRegex = false; 781 bool useRegex = false;
493 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); 782 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
494 783
@@ -522,5 +811,52 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
522 811
523 return sceneObjects; 812 return sceneObjects;
524 } 813 }
814
815 /// <summary>
816 /// Get scene object delete candidates by position
817 /// </summary>
818 /// <param name='module'></param>
819 /// <param name='cmdparams'></param>
820 /// <returns>null if parsing failed on one of the arguments, otherwise a list of objects to delete. If there
821 /// are no objects to delete then the list will be empty./returns>
822 private List<SceneObjectGroup> GetDeleteCandidatesByPos(string module, string[] cmdparams)
823 {
824 if (cmdparams.Length < 5)
825 {
826 m_console.OutputFormat("Usage: delete object pos <start-coord> to <end-coord>");
827 return null;
828 }
829
830 Vector3 startVector, endVector;
831
832 if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector))
833 return null;
834
835 return m_scene.GetSceneObjectGroups().FindAll(
836 so => !so.IsAttachment && Util.IsInsideBox(so.AbsolutePosition, startVector, endVector));
837 }
838
839 private bool TryParseVectorRange(IEnumerable<string> rawComponents, out Vector3 startVector, out Vector3 endVector)
840 {
841 string rawConsoleStartVector = rawComponents.Take(1).Single();
842
843 if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
844 {
845 m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector);
846 endVector = Vector3.Zero;
847
848 return false;
849 }
850
851 string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single();
852
853 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
854 {
855 m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector);
856 return false;
857 }
858
859 return true;
860 }
525 } 861 }
526} \ No newline at end of file 862} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index f3d38bc..ddaa227 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -37,13 +37,17 @@ using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces; 38using OpenSim.Services.Interfaces;
39 39
40using Mono.Addins;
41
40namespace OpenSim.Region.CoreModules.World.Permissions 42namespace OpenSim.Region.CoreModules.World.Permissions
41{ 43{
42 public class PermissionsModule : IRegionModule, IPermissionsModule 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PermissionsModule")]
45 public class PermissionsModule : INonSharedRegionModule, IPermissionsModule
43 { 46 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 48
46 protected Scene m_scene; 49 protected Scene m_scene;
50 protected bool m_Enabled;
47 51
48 private InventoryFolderImpl m_libraryRootFolder; 52 private InventoryFolderImpl m_libraryRootFolder;
49 protected InventoryFolderImpl LibraryRootFolder 53 protected InventoryFolderImpl LibraryRootFolder
@@ -114,18 +118,44 @@ namespace OpenSim.Region.CoreModules.World.Permissions
114 private Dictionary<string, bool> GrantVB = new Dictionary<string, bool>(); 118 private Dictionary<string, bool> GrantVB = new Dictionary<string, bool>();
115 private Dictionary<string, bool> GrantJS = new Dictionary<string, bool>(); 119 private Dictionary<string, bool> GrantJS = new Dictionary<string, bool>();
116 private Dictionary<string, bool> GrantYP = new Dictionary<string, bool>(); 120 private Dictionary<string, bool> GrantYP = new Dictionary<string, bool>();
121
117 private IFriendsModule m_friendsModule; 122 private IFriendsModule m_friendsModule;
123 private IFriendsModule FriendsModule
124 {
125 get
126 {
127 if (m_friendsModule == null)
128 m_friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
129 return m_friendsModule;
130 }
131 }
118 private IGroupsModule m_groupsModule; 132 private IGroupsModule m_groupsModule;
119 private IMoapModule m_moapModule; 133 private IGroupsModule GroupsModule
134 {
135 get
136 {
137 if (m_groupsModule == null)
138 m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
139 return m_groupsModule;
140 }
141 }
120 142
143 private IMoapModule m_moapModule;
144 private IMoapModule MoapModule
145 {
146 get
147 {
148 if (m_moapModule == null)
149 m_moapModule = m_scene.RequestModuleInterface<IMoapModule>();
150 return m_moapModule;
151 }
152 }
121 #endregion 153 #endregion
122 154
123 #region IRegionModule Members 155 #region INonSharedRegionModule Members
124 156
125 public void Initialise(Scene scene, IConfigSource config) 157 public void Initialise(IConfigSource config)
126 { 158 {
127 m_scene = scene;
128
129 IConfig myConfig = config.Configs["Startup"]; 159 IConfig myConfig = config.Configs["Startup"];
130 160
131 string permissionModules = myConfig.GetString("permissionmodules", "DefaultPermissionsModule"); 161 string permissionModules = myConfig.GetString("permissionmodules", "DefaultPermissionsModule");
@@ -135,6 +165,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
135 if (!modules.Contains("DefaultPermissionsModule")) 165 if (!modules.Contains("DefaultPermissionsModule"))
136 return; 166 return;
137 167
168 m_Enabled = true;
169
138 m_allowGridGods = myConfig.GetBoolean("allow_grid_gods", false); 170 m_allowGridGods = myConfig.GetBoolean("allow_grid_gods", false);
139 m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", true); 171 m_bypassPermissions = !myConfig.GetBoolean("serverside_object_permissions", true);
140 m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true); 172 m_propagatePermissions = myConfig.GetBoolean("propagate_permissions", true);
@@ -144,7 +176,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
144 176
145 m_SimpleBuildPermissions = myConfig.GetBoolean("simple_build_permissions", false); 177 m_SimpleBuildPermissions = myConfig.GetBoolean("simple_build_permissions", false);
146 178
147 m_allowedScriptCreators 179 m_allowedScriptCreators
148 = ParseUserSetConfigSetting(myConfig, "allowed_script_creators", m_allowedScriptCreators); 180 = ParseUserSetConfigSetting(myConfig, "allowed_script_creators", m_allowedScriptCreators);
149 m_allowedScriptEditors 181 m_allowedScriptEditors
150 = ParseUserSetConfigSetting(myConfig, "allowed_script_editors", m_allowedScriptEditors); 182 = ParseUserSetConfigSetting(myConfig, "allowed_script_editors", m_allowedScriptEditors);
@@ -154,6 +186,64 @@ namespace OpenSim.Region.CoreModules.World.Permissions
154 else 186 else
155 m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks"); 187 m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks");
156 188
189 string grant = myConfig.GetString("GrantLSL", "");
190 if (grant.Length > 0)
191 {
192 foreach (string uuidl in grant.Split(','))
193 {
194 string uuid = uuidl.Trim(" \t".ToCharArray());
195 GrantLSL.Add(uuid, true);
196 }
197 }
198
199 grant = myConfig.GetString("GrantCS", "");
200 if (grant.Length > 0)
201 {
202 foreach (string uuidl in grant.Split(','))
203 {
204 string uuid = uuidl.Trim(" \t".ToCharArray());
205 GrantCS.Add(uuid, true);
206 }
207 }
208
209 grant = myConfig.GetString("GrantVB", "");
210 if (grant.Length > 0)
211 {
212 foreach (string uuidl in grant.Split(','))
213 {
214 string uuid = uuidl.Trim(" \t".ToCharArray());
215 GrantVB.Add(uuid, true);
216 }
217 }
218
219 grant = myConfig.GetString("GrantJS", "");
220 if (grant.Length > 0)
221 {
222 foreach (string uuidl in grant.Split(','))
223 {
224 string uuid = uuidl.Trim(" \t".ToCharArray());
225 GrantJS.Add(uuid, true);
226 }
227 }
228
229 grant = myConfig.GetString("GrantYP", "");
230 if (grant.Length > 0)
231 {
232 foreach (string uuidl in grant.Split(','))
233 {
234 string uuid = uuidl.Trim(" \t".ToCharArray());
235 GrantYP.Add(uuid, true);
236 }
237 }
238 }
239
240 public void AddRegion(Scene scene)
241 {
242 if (!m_Enabled)
243 return;
244
245 m_scene = scene;
246
157 scene.RegisterModuleInterface<IPermissionsModule>(this); 247 scene.RegisterModuleInterface<IPermissionsModule>(this);
158 248
159 //Register functions with Scene External Checks! 249 //Register functions with Scene External Checks!
@@ -169,44 +259,44 @@ namespace OpenSim.Region.CoreModules.World.Permissions
169 m_scene.Permissions.OnIsGridGod += IsGridGod; 259 m_scene.Permissions.OnIsGridGod += IsGridGod;
170 m_scene.Permissions.OnIsAdministrator += IsAdministrator; 260 m_scene.Permissions.OnIsAdministrator += IsAdministrator;
171 m_scene.Permissions.OnDuplicateObject += CanDuplicateObject; 261 m_scene.Permissions.OnDuplicateObject += CanDuplicateObject;
172 m_scene.Permissions.OnDeleteObject += CanDeleteObject; //MAYBE FULLY IMPLEMENTED 262 m_scene.Permissions.OnDeleteObject += CanDeleteObject;
173 m_scene.Permissions.OnEditObject += CanEditObject; //MAYBE FULLY IMPLEMENTED 263 m_scene.Permissions.OnEditObject += CanEditObject;
174 m_scene.Permissions.OnEditParcelProperties += CanEditParcelProperties; //MAYBE FULLY IMPLEMENTED 264 m_scene.Permissions.OnEditParcelProperties += CanEditParcelProperties;
175 m_scene.Permissions.OnInstantMessage += CanInstantMessage; 265 m_scene.Permissions.OnInstantMessage += CanInstantMessage;
176 m_scene.Permissions.OnInventoryTransfer += CanInventoryTransfer; //NOT YET IMPLEMENTED 266 m_scene.Permissions.OnInventoryTransfer += CanInventoryTransfer;
177 m_scene.Permissions.OnIssueEstateCommand += CanIssueEstateCommand; //FULLY IMPLEMENTED 267 m_scene.Permissions.OnIssueEstateCommand += CanIssueEstateCommand;
178 m_scene.Permissions.OnMoveObject += CanMoveObject; //MAYBE FULLY IMPLEMENTED 268 m_scene.Permissions.OnMoveObject += CanMoveObject;
179 m_scene.Permissions.OnObjectEntry += CanObjectEntry; 269 m_scene.Permissions.OnObjectEntry += CanObjectEntry;
180 m_scene.Permissions.OnReturnObjects += CanReturnObjects; //NOT YET IMPLEMENTED 270 m_scene.Permissions.OnReturnObjects += CanReturnObjects;
181 m_scene.Permissions.OnRezObject += CanRezObject; //MAYBE FULLY IMPLEMENTED 271 m_scene.Permissions.OnRezObject += CanRezObject;
182 m_scene.Permissions.OnRunConsoleCommand += CanRunConsoleCommand; 272 m_scene.Permissions.OnRunConsoleCommand += CanRunConsoleCommand;
183 m_scene.Permissions.OnRunScript += CanRunScript; //NOT YET IMPLEMENTED 273 m_scene.Permissions.OnRunScript += CanRunScript;
184 m_scene.Permissions.OnCompileScript += CanCompileScript; 274 m_scene.Permissions.OnCompileScript += CanCompileScript;
185 m_scene.Permissions.OnSellParcel += CanSellParcel; 275 m_scene.Permissions.OnSellParcel += CanSellParcel;
186 m_scene.Permissions.OnTakeObject += CanTakeObject; 276 m_scene.Permissions.OnTakeObject += CanTakeObject;
187 m_scene.Permissions.OnTakeCopyObject += CanTakeCopyObject; 277 m_scene.Permissions.OnTakeCopyObject += CanTakeCopyObject;
188 m_scene.Permissions.OnTerraformLand += CanTerraformLand; 278 m_scene.Permissions.OnTerraformLand += CanTerraformLand;
189 m_scene.Permissions.OnLinkObject += CanLinkObject; //NOT YET IMPLEMENTED 279 m_scene.Permissions.OnLinkObject += CanLinkObject;
190 m_scene.Permissions.OnDelinkObject += CanDelinkObject; //NOT YET IMPLEMENTED 280 m_scene.Permissions.OnDelinkObject += CanDelinkObject;
191 m_scene.Permissions.OnBuyLand += CanBuyLand; //NOT YET IMPLEMENTED 281 m_scene.Permissions.OnBuyLand += CanBuyLand;
192 282
193 m_scene.Permissions.OnViewNotecard += CanViewNotecard; //NOT YET IMPLEMENTED 283 m_scene.Permissions.OnViewNotecard += CanViewNotecard;
194 m_scene.Permissions.OnViewScript += CanViewScript; //NOT YET IMPLEMENTED 284 m_scene.Permissions.OnViewScript += CanViewScript;
195 m_scene.Permissions.OnEditNotecard += CanEditNotecard; //NOT YET IMPLEMENTED 285 m_scene.Permissions.OnEditNotecard += CanEditNotecard;
196 m_scene.Permissions.OnEditScript += CanEditScript; //NOT YET IMPLEMENTED 286 m_scene.Permissions.OnEditScript += CanEditScript;
197 287
198 m_scene.Permissions.OnCreateObjectInventory += CanCreateObjectInventory; 288 m_scene.Permissions.OnCreateObjectInventory += CanCreateObjectInventory;
199 m_scene.Permissions.OnEditObjectInventory += CanEditObjectInventory;//MAYBE FULLY IMPLEMENTED 289 m_scene.Permissions.OnEditObjectInventory += CanEditObjectInventory;
200 m_scene.Permissions.OnCopyObjectInventory += CanCopyObjectInventory; //NOT YET IMPLEMENTED 290 m_scene.Permissions.OnCopyObjectInventory += CanCopyObjectInventory;
201 m_scene.Permissions.OnDeleteObjectInventory += CanDeleteObjectInventory; //NOT YET IMPLEMENTED 291 m_scene.Permissions.OnDeleteObjectInventory += CanDeleteObjectInventory;
202 m_scene.Permissions.OnResetScript += CanResetScript; 292 m_scene.Permissions.OnResetScript += CanResetScript;
203 293
204 m_scene.Permissions.OnCreateUserInventory += CanCreateUserInventory; //NOT YET IMPLEMENTED 294 m_scene.Permissions.OnCreateUserInventory += CanCreateUserInventory;
205 m_scene.Permissions.OnCopyUserInventory += CanCopyUserInventory; //NOT YET IMPLEMENTED 295 m_scene.Permissions.OnCopyUserInventory += CanCopyUserInventory;
206 m_scene.Permissions.OnEditUserInventory += CanEditUserInventory; //NOT YET IMPLEMENTED 296 m_scene.Permissions.OnEditUserInventory += CanEditUserInventory;
207 m_scene.Permissions.OnDeleteUserInventory += CanDeleteUserInventory; //NOT YET IMPLEMENTED 297 m_scene.Permissions.OnDeleteUserInventory += CanDeleteUserInventory;
208 298
209 m_scene.Permissions.OnTeleport += CanTeleport; //NOT YET IMPLEMENTED 299 m_scene.Permissions.OnTeleport += CanTeleport;
210 300
211 m_scene.Permissions.OnControlPrimMedia += CanControlPrimMedia; 301 m_scene.Permissions.OnControlPrimMedia += CanControlPrimMedia;
212 m_scene.Permissions.OnInteractWithPrimMedia += CanInteractWithPrimMedia; 302 m_scene.Permissions.OnInteractWithPrimMedia += CanInteractWithPrimMedia;
@@ -226,52 +316,38 @@ namespace OpenSim.Region.CoreModules.World.Permissions
226 "Turn on permissions debugging", 316 "Turn on permissions debugging",
227 HandleDebugPermissions); 317 HandleDebugPermissions);
228 318
229 string grant = myConfig.GetString("GrantLSL",""); 319 }
230 if (grant.Length > 0) {
231 foreach (string uuidl in grant.Split(',')) {
232 string uuid = uuidl.Trim(" \t".ToCharArray());
233 GrantLSL.Add(uuid, true);
234 }
235 }
236 320
237 grant = myConfig.GetString("GrantCS",""); 321 public void RegionLoaded(Scene scene)
238 if (grant.Length > 0) { 322 {
239 foreach (string uuidl in grant.Split(',')) { 323 }
240 string uuid = uuidl.Trim(" \t".ToCharArray());
241 GrantCS.Add(uuid, true);
242 }
243 }
244 324
245 grant = myConfig.GetString("GrantVB",""); 325 public void RemoveRegion(Scene scene)
246 if (grant.Length > 0) { 326 {
247 foreach (string uuidl in grant.Split(',')) { 327 if (!m_Enabled)
248 string uuid = uuidl.Trim(" \t".ToCharArray()); 328 return;
249 GrantVB.Add(uuid, true);
250 }
251 }
252 329
253 grant = myConfig.GetString("GrantJS", ""); 330 m_scene.UnregisterModuleInterface<IPermissionsModule>(this);
254 if (grant.Length > 0) 331 }
255 {
256 foreach (string uuidl in grant.Split(','))
257 {
258 string uuid = uuidl.Trim(" \t".ToCharArray());
259 GrantJS.Add(uuid, true);
260 }
261 }
262 332
263 grant = myConfig.GetString("GrantYP", ""); 333 public void Close()
264 if (grant.Length > 0) 334 {
265 { 335 }
266 foreach (string uuidl in grant.Split(',')) 336
267 { 337 public string Name
268 string uuid = uuidl.Trim(" \t".ToCharArray()); 338 {
269 GrantYP.Add(uuid, true); 339 get { return "PermissionsModule"; }
270 } 340 }
271 }
272 341
342 public Type ReplaceableInterface
343 {
344 get { return null; }
273 } 345 }
274 346
347 #endregion
348
349 #region Console command handlers
350
275 public void HandleBypassPermissions(string module, string[] args) 351 public void HandleBypassPermissions(string module, string[] args)
276 { 352 {
277 if (m_scene.ConsoleScene() != null && 353 if (m_scene.ConsoleScene() != null &&
@@ -290,7 +366,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
290 m_bypassPermissions = val; 366 m_bypassPermissions = val;
291 367
292 m_log.InfoFormat( 368 m_log.InfoFormat(
293 "[PERMISSIONS]: Set permissions bypass to {0} for {1}", 369 "[PERMISSIONS]: Set permissions bypass to {0} for {1}",
294 m_bypassPermissions, m_scene.RegionInfo.RegionName); 370 m_bypassPermissions, m_scene.RegionInfo.RegionName);
295 } 371 }
296 } 372 }
@@ -343,39 +419,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions
343 } 419 }
344 } 420 }
345 421
346 public void PostInitialise()
347 {
348 m_friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
349
350 if (m_friendsModule == null)
351 m_log.Debug("[PERMISSIONS]: Friends module not found, friend permissions will not work");
352
353 m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
354
355 if (m_groupsModule == null)
356 m_log.Debug("[PERMISSIONS]: Groups module not found, group permissions will not work");
357
358 m_moapModule = m_scene.RequestModuleInterface<IMoapModule>();
359
360 // This log line will be commented out when no longer required for debugging
361// if (m_moapModule == null)
362// m_log.Warn("[PERMISSIONS]: Media on a prim module not found, media on a prim permissions will not work");
363 }
364
365 public void Close()
366 {
367 }
368
369 public string Name
370 {
371 get { return "DefaultPermissionsModule"; }
372 }
373
374 public bool IsSharedModule
375 {
376 get { return false; }
377 }
378
379 #endregion 422 #endregion
380 423
381 #region Helper Functions 424 #region Helper Functions
@@ -400,10 +443,10 @@ namespace OpenSim.Region.CoreModules.World.Permissions
400 /// <returns></returns> 443 /// <returns></returns>
401 protected bool IsGroupMember(UUID groupID, UUID userID, ulong powers) 444 protected bool IsGroupMember(UUID groupID, UUID userID, ulong powers)
402 { 445 {
403 if (null == m_groupsModule) 446 if (null == GroupsModule)
404 return false; 447 return false;
405 448
406 GroupMembershipData gmd = m_groupsModule.GetMembershipData(groupID, userID); 449 GroupMembershipData gmd = GroupsModule.GetMembershipData(groupID, userID);
407 450
408 if (gmd != null) 451 if (gmd != null)
409 { 452 {
@@ -503,10 +546,10 @@ namespace OpenSim.Region.CoreModules.World.Permissions
503 if (user == UUID.Zero) 546 if (user == UUID.Zero)
504 return false; 547 return false;
505 548
506 if (m_friendsModule == null) 549 if (FriendsModule == null)
507 return false; 550 return false;
508 551
509 int friendPerms = m_friendsModule.GetRightsGrantedByFriend(user, objectOwner); 552 int friendPerms = FriendsModule.GetRightsGrantedByFriend(user, objectOwner);
510 return (friendPerms & (int)FriendRights.CanModifyObjects) != 0; 553 return (friendPerms & (int)FriendRights.CanModifyObjects) != 0;
511 } 554 }
512 555
@@ -1915,14 +1958,14 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1915// "[PERMISSONS]: Performing CanControlPrimMedia check with agentID {0}, primID {1}, face {2}", 1958// "[PERMISSONS]: Performing CanControlPrimMedia check with agentID {0}, primID {1}, face {2}",
1916// agentID, primID, face); 1959// agentID, primID, face);
1917 1960
1918 if (null == m_moapModule) 1961 if (null == MoapModule)
1919 return false; 1962 return false;
1920 1963
1921 SceneObjectPart part = m_scene.GetSceneObjectPart(primID); 1964 SceneObjectPart part = m_scene.GetSceneObjectPart(primID);
1922 if (null == part) 1965 if (null == part)
1923 return false; 1966 return false;
1924 1967
1925 MediaEntry me = m_moapModule.GetMediaEntry(part, face); 1968 MediaEntry me = MoapModule.GetMediaEntry(part, face);
1926 1969
1927 // If there is no existing media entry then it can be controlled (in this context, created). 1970 // If there is no existing media entry then it can be controlled (in this context, created).
1928 if (null == me) 1971 if (null == me)
@@ -1941,14 +1984,14 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1941// "[PERMISSONS]: Performing CanInteractWithPrimMedia check with agentID {0}, primID {1}, face {2}", 1984// "[PERMISSONS]: Performing CanInteractWithPrimMedia check with agentID {0}, primID {1}, face {2}",
1942// agentID, primID, face); 1985// agentID, primID, face);
1943 1986
1944 if (null == m_moapModule) 1987 if (null == MoapModule)
1945 return false; 1988 return false;
1946 1989
1947 SceneObjectPart part = m_scene.GetSceneObjectPart(primID); 1990 SceneObjectPart part = m_scene.GetSceneObjectPart(primID);
1948 if (null == part) 1991 if (null == part)
1949 return false; 1992 return false;
1950 1993
1951 MediaEntry me = m_moapModule.GetMediaEntry(part, face); 1994 MediaEntry me = MoapModule.GetMediaEntry(part, face);
1952 1995
1953 // If there is no existing media entry then it can be controlled (in this context, created). 1996 // If there is no existing media entry then it can be controlled (in this context, created).
1954 if (null == me) 1997 if (null == me)
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index 287738a..9c441ed 100644
--- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Linq;
29using System.Reflection; 30using System.Reflection;
30using System.Timers; 31using System.Timers;
31using System.IO; 32using System.IO;
@@ -305,6 +306,9 @@ namespace OpenSim.Region.CoreModules.World.Region
305 for (int i = 4 ; i < args.Length ; i++) 306 for (int i = 4 ; i < args.Length ; i++)
306 times.Add(Convert.ToInt32(args[i])); 307 times.Add(Convert.ToInt32(args[i]));
307 308
309 MainConsole.Instance.OutputFormat(
310 "Region {0} scheduled for restart in {1} seconds", m_Scene.Name, times.Sum());
311
308 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice); 312 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice);
309 } 313 }
310 314
@@ -328,4 +332,4 @@ namespace OpenSim.Region.CoreModules.World.Region
328 } 332 }
329 } 333 }
330 } 334 }
331} 335} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs b/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs
index 0e861a1..e0247d9 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/SerialiserModule.cs
@@ -32,6 +32,7 @@ using System.Reflection;
32 32
33using log4net; 33using log4net;
34using Nini.Config; 34using Nini.Config;
35using Mono.Addins;
35 36
36using OpenMetaverse; 37using OpenMetaverse;
37using OpenSim.Region.CoreModules.Framework.InterfaceCommander; 38using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
@@ -41,6 +42,7 @@ using OpenSim.Region.Framework.Scenes.Serialization;
41 42
42namespace OpenSim.Region.CoreModules.World.Serialiser 43namespace OpenSim.Region.CoreModules.World.Serialiser
43{ 44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SerialiserModule")]
44 public class SerialiserModule : ISharedRegionModule, IRegionSerialiserModule 46 public class SerialiserModule : ISharedRegionModule, IRegionSerialiserModule
45 { 47 {
46 private static readonly ILog m_log = 48 private static readonly ILog m_log =
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index 14c1a39..513a8f5 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -24,56 +24,110 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27
28using System; 27using System;
28using System.IO;
29using System.Collections.Generic;
30using System.Reflection;
31
29using Nini.Config; 32using Nini.Config;
30using OpenMetaverse; 33using OpenMetaverse;
34using log4net;
35using Mono.Addins;
36
31using OpenSim.Framework; 37using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
34using System.Reflection;
35using log4net;
36 40
37namespace OpenSim.Region.CoreModules.World.Sound 41namespace OpenSim.Region.CoreModules.World.Sound
38{ 42{
39 public class SoundModule : IRegionModule, ISoundModule 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")]
44 public class SoundModule : INonSharedRegionModule, ISoundModule
40 { 45 {
41// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(
42 47 MethodBase.GetCurrentMethod().DeclaringType);
43 protected Scene m_scene; 48
44 49 private Scene m_scene;
45 public void Initialise(Scene scene, IConfigSource source) 50
51 public bool Enabled { get; private set; }
52
53 public float MaxDistance { get; private set; }
54
55 #region INonSharedRegionModule
56
57 public void Initialise(IConfigSource configSource)
58 {
59 IConfig config = configSource.Configs["Sounds"];
60
61 if (config == null)
62 {
63 Enabled = true;
64 MaxDistance = 100.0f;
65 }
66 else
67 {
68 Enabled = config.GetString("Module", "OpenSim.Region.CoreModules.dll:SoundModule") ==
69 Path.GetFileName(Assembly.GetExecutingAssembly().Location)
70 + ":" + MethodBase.GetCurrentMethod().DeclaringType.Name;
71 MaxDistance = config.GetFloat("MaxDistance", 100.0f);
72 }
73 }
74
75 public void AddRegion(Scene scene) { }
76
77 public void RemoveRegion(Scene scene)
46 { 78 {
79 m_scene.EventManager.OnClientLogin -= OnNewClient;
80 }
81
82 public void RegionLoaded(Scene scene)
83 {
84 if (!Enabled)
85 return;
86
47 m_scene = scene; 87 m_scene = scene;
48 88 m_scene.EventManager.OnClientLogin += OnNewClient;
49 m_scene.EventManager.OnNewClient += OnNewClient; 89
50
51 m_scene.RegisterModuleInterface<ISoundModule>(this); 90 m_scene.RegisterModuleInterface<ISoundModule>(this);
52 } 91 }
53 92
54 public void PostInitialise() {} 93 public void Close() { }
55 public void Close() {} 94
95 public Type ReplaceableInterface
96 {
97 get { return typeof(ISoundModule); }
98 }
99
56 public string Name { get { return "Sound Module"; } } 100 public string Name { get { return "Sound Module"; } }
57 public bool IsSharedModule { get { return false; } } 101
58 102 #endregion
103
104 #region Event Handlers
105
59 private void OnNewClient(IClientAPI client) 106 private void OnNewClient(IClientAPI client)
60 { 107 {
61 client.OnSoundTrigger += TriggerSound; 108 client.OnSoundTrigger += TriggerSound;
62 } 109 }
63 110
111 #endregion
112
113 #region ISoundModule
114
64 public virtual void PlayAttachedSound( 115 public virtual void PlayAttachedSound(
65 UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) 116 UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius)
66 { 117 {
67 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); 118 SceneObjectPart part;
68 if (part == null) 119 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
69 return; 120 return;
70 121
71 SceneObjectGroup grp = part.ParentGroup; 122 SceneObjectGroup grp = part.ParentGroup;
72 123
124 if (radius == 0)
125 radius = MaxDistance;
126
73 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 127 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
74 { 128 {
75 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 129 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
76 if (dis > 100.0) // Max audio distance 130 if (dis > MaxDistance) // Max audio distance
77 return; 131 return;
78 132
79 if (grp.IsAttachment) 133 if (grp.IsAttachment)
@@ -86,23 +140,21 @@ namespace OpenSim.Region.CoreModules.World.Sound
86 } 140 }
87 141
88 // Scale by distance 142 // Scale by distance
89 if (radius == 0) 143 double thisSpGain = gain * ((radius - dis) / radius);
90 gain = (float)((double)gain * ((100.0 - dis) / 100.0));
91 else
92 gain = (float)((double)gain * ((radius - dis) / radius));
93 144
94 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags); 145 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
146 ownerID, (float)thisSpGain, flags);
95 }); 147 });
96 } 148 }
97 149
98 public virtual void TriggerSound( 150 public virtual void TriggerSound(
99 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) 151 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius)
100 { 152 {
101 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); 153 SceneObjectPart part;
102 if (part == null) 154 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
103 { 155 {
104 ScenePresence sp; 156 ScenePresence sp;
105 if (!m_scene.TryGetScenePresence(objectID, out sp)) 157 if (!m_scene.TryGetScenePresence(ownerID, out sp))
106 return; 158 return;
107 } 159 }
108 else 160 else
@@ -116,24 +168,207 @@ namespace OpenSim.Region.CoreModules.World.Sound
116 } 168 }
117 } 169 }
118 170
171 if (radius == 0)
172 radius = MaxDistance;
173
119 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 174 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
120 { 175 {
121 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 176 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
122 177
123 if (dis > 100.0) // Max audio distance 178 if (dis > MaxDistance) // Max audio distance
124 return; 179 return;
125 180
126 float thisSpGain;
127
128 // Scale by distance 181 // Scale by distance
129 if (radius == 0) 182 double thisSpGain = gain * ((radius - dis) / radius);
130 thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); 183
184 sp.ControllingClient.SendTriggeredSound(soundId, ownerID,
185 objectID, parentID, handle, position,
186 (float)thisSpGain);
187 });
188 }
189
190 public virtual void StopSound(UUID objectID)
191 {
192 SceneObjectPart m_host;
193 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
194 return;
195
196 StopSound(m_host);
197 }
198
199 private static void StopSound(SceneObjectPart m_host)
200 {
201 m_host.AdjustSoundGain(0);
202 // Xantor 20080528: Clear prim data of sound instead
203 if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host))
204 {
205 if (m_host.ParentGroup.LoopSoundMasterPrim == m_host)
206 {
207 foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims)
208 {
209 part.Sound = UUID.Zero;
210 part.SoundFlags = 1 << 5;
211 part.SoundRadius = 0;
212 part.ScheduleFullUpdate();
213 part.SendFullUpdateToAllClients();
214 }
215 m_host.ParentGroup.LoopSoundMasterPrim = null;
216 m_host.ParentGroup.LoopSoundSlavePrims.Clear();
217 }
218 else
219 {
220 m_host.Sound = UUID.Zero;
221 m_host.SoundFlags = 1 << 5;
222 m_host.SoundRadius = 0;
223 m_host.ScheduleFullUpdate();
224 m_host.SendFullUpdateToAllClients();
225 }
226 }
227 else
228 {
229 m_host.Sound = UUID.Zero;
230 m_host.SoundFlags = 1 << 5;
231 m_host.SoundRadius = 0;
232 m_host.ScheduleFullUpdate();
233 m_host.SendFullUpdateToAllClients();
234 }
235 }
236
237 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius)
238 {
239 SceneObjectPart part;
240 if (soundID == UUID.Zero
241 || !m_scene.TryGetSceneObjectPart(objectID, out part))
242 {
243 return;
244 }
245
246 if (radius == 0)
247 radius = MaxDistance;
248
249 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
250 {
251 if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance))
252 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
253 });
254 }
255
256 // Xantor 20080528 we should do this differently.
257 // 1) apply the sound to the object
258 // 2) schedule full update
259 // just sending the sound out once doesn't work so well when other avatars come in view later on
260 // or when the prim gets moved, changed, sat on, whatever
261 // see large number of mantises (mantes?)
262 // 20080530 Updated to remove code duplication
263 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
264 public void LoopSound(UUID objectID, UUID soundID,
265 double volume, double radius, bool isMaster)
266 {
267 SceneObjectPart m_host;
268 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
269 return;
270
271 if (isMaster)
272 m_host.ParentGroup.LoopSoundMasterPrim = m_host;
273
274 if (m_host.Sound != UUID.Zero)
275 StopSound(m_host);
276
277 m_host.Sound = soundID;
278 m_host.SoundGain = volume;
279 m_host.SoundFlags = 1; // looping
280 m_host.SoundRadius = radius;
281
282 m_host.ScheduleFullUpdate();
283 m_host.SendFullUpdateToAllClients();
284 }
285
286 public void SendSound(UUID objectID, UUID soundID, double volume,
287 bool triggered, byte flags, float radius, bool useMaster,
288 bool isMaster)
289 {
290 if (soundID == UUID.Zero)
291 return;
292
293 SceneObjectPart part;
294 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
295 return;
296
297 volume = Util.Clip((float)volume, 0, 1);
298
299 UUID parentID = part.ParentGroup.UUID;
300
301 Vector3 position = part.AbsolutePosition; // region local
302 ulong regionHandle = m_scene.RegionInfo.RegionHandle;
303
304 if (useMaster)
305 {
306 if (isMaster)
307 {
308 if (triggered)
309 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
310 else
311 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
312 part.ParentGroup.PlaySoundMasterPrim = part;
313 if (triggered)
314 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
315 else
316 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
317 foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims)
318 {
319 position = prim.AbsolutePosition; // region local
320 if (triggered)
321 TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius);
322 else
323 PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius);
324 }
325 part.ParentGroup.PlaySoundSlavePrims.Clear();
326 part.ParentGroup.PlaySoundMasterPrim = null;
327 }
131 else 328 else
132 thisSpGain = (float)((double)gain * ((radius - dis) / radius)); 329 {
330 part.ParentGroup.PlaySoundSlavePrims.Add(part);
331 }
332 }
333 else
334 {
335 if (triggered)
336 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
337 else
338 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
339 }
340 }
133 341
134 sp.ControllingClient.SendTriggeredSound( 342 public void TriggerSoundLimited(UUID objectID, UUID sound,
135 soundId, ownerID, objectID, parentID, handle, position, thisSpGain); 343 double volume, Vector3 min, Vector3 max)
344 {
345 if (sound == UUID.Zero)
346 return;
347
348 SceneObjectPart part;
349 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
350 return;
351
352 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
353 {
354 double dis = Util.GetDistanceTo(sp.AbsolutePosition,
355 part.AbsolutePosition);
356
357 if (dis > MaxDistance) // Max audio distance
358 return;
359 else if (!Util.IsInsideBox(sp.AbsolutePosition, min, max))
360 return;
361
362 // Scale by distance
363 double thisSpGain = volume * ((MaxDistance - dis) / MaxDistance);
364
365 sp.ControllingClient.SendTriggeredSound(sound, part.OwnerID,
366 part.UUID, part.ParentGroup.UUID,
367 m_scene.RegionInfo.RegionHandle,
368 part.AbsolutePosition, (float)thisSpGain);
136 }); 369 });
137 } 370 }
371
372 #endregion
138 } 373 }
139} 374}
diff --git a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs
index 9a954b8..a321c09 100644
--- a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using log4net; 31using log4net;
32using Mono.Addins;
32using Nini.Config; 33using Nini.Config;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
@@ -37,6 +38,7 @@ using OpenSim.Region.Framework.Scenes;
37 38
38namespace OpenSim.Region.CoreModules 39namespace OpenSim.Region.CoreModules
39{ 40{
41 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SunModule")]
40 public class SunModule : ISunModule 42 public class SunModule : ISunModule
41 { 43 {
42 /// <summary> 44 /// <summary>
@@ -267,26 +269,17 @@ namespace OpenSim.Region.CoreModules
267 return GetCurrentSunHour() + 6.0f; 269 return GetCurrentSunHour() + 6.0f;
268 } 270 }
269 271
270 #region IRegion Methods 272 #region INonSharedRegion Methods
271 273
272 // Called immediately after the module is loaded for a given region 274 // Called immediately after the module is loaded for a given region
273 // i.e. Immediately after instance creation. 275 // i.e. Immediately after instance creation.
274 public void Initialise(Scene scene, IConfigSource config) 276 public void Initialise(IConfigSource config)
275 { 277 {
276 m_scene = scene;
277 m_frame = 0; 278 m_frame = 0;
278 279
279 // This one puts an entry in the main help screen 280 // This one puts an entry in the main help screen
280// m_scene.AddCommand("Regions", this, "sun", "sun", "Usage: sun [param] [value] - Get or Update Sun module paramater", null); 281// m_scene.AddCommand("Regions", this, "sun", "sun", "Usage: sun [param] [value] - Get or Update Sun module paramater", null);
281 282
282 // This one enables the ability to type just "sun" without any parameters
283// m_scene.AddCommand("Regions", this, "sun", "", "", HandleSunConsoleCommand);
284 foreach (KeyValuePair<string, string> kvp in GetParamList())
285 {
286 string sunCommand = string.Format("sun {0}", kvp.Key);
287 m_scene.AddCommand("Regions", this, sunCommand, string.Format("{0} [<value>]", sunCommand), kvp.Value, "", HandleSunConsoleCommand);
288 }
289
290 TimeZone local = TimeZone.CurrentTimeZone; 283 TimeZone local = TimeZone.CurrentTimeZone;
291 TicksUTCOffset = local.GetUtcOffset(local.ToLocalTime(DateTime.Now)).Ticks; 284 TicksUTCOffset = local.GetUtcOffset(local.ToLocalTime(DateTime.Now)).Ticks;
292 m_log.DebugFormat("[SUN]: localtime offset is {0}", TicksUTCOffset); 285 m_log.DebugFormat("[SUN]: localtime offset is {0}", TicksUTCOffset);
@@ -358,15 +351,6 @@ namespace OpenSim.Region.CoreModules
358 HorizonShift = m_HorizonShift; // Z axis translation 351 HorizonShift = m_HorizonShift; // Z axis translation
359 // HoursToRadians = (SunCycle/24)*VWTimeRatio; 352 // HoursToRadians = (SunCycle/24)*VWTimeRatio;
360 353
361 // Insert our event handling hooks
362
363 scene.EventManager.OnFrame += SunUpdate;
364 scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
365 scene.EventManager.OnEstateToolsSunUpdate += EstateToolsSunUpdate;
366 scene.EventManager.OnGetCurrentTimeAsLindenSunHour += GetCurrentTimeAsLindenSunHour;
367
368 ready = true;
369
370 m_log.Debug("[SUN]: Mode is " + m_RegionMode); 354 m_log.Debug("[SUN]: Mode is " + m_RegionMode);
371 m_log.Debug("[SUN]: Initialization completed. Day is " + SecondsPerSunCycle + " seconds, and year is " + m_YearLengthDays + " days"); 355 m_log.Debug("[SUN]: Initialization completed. Day is " + SecondsPerSunCycle + " seconds, and year is " + m_YearLengthDays + " days");
372 m_log.Debug("[SUN]: Axis offset is " + m_HorizonShift); 356 m_log.Debug("[SUN]: Axis offset is " + m_HorizonShift);
@@ -376,14 +360,37 @@ namespace OpenSim.Region.CoreModules
376 break; 360 break;
377 } 361 }
378 362
379 scene.RegisterModuleInterface<ISunModule>(this);
380 } 363 }
381 364
382 public void PostInitialise() 365 public Type ReplaceableInterface
383 { 366 {
367 get { return null; }
384 } 368 }
385 369
386 public void Close() 370 public void AddRegion(Scene scene)
371 {
372 m_scene = scene;
373 // Insert our event handling hooks
374
375 scene.EventManager.OnFrame += SunUpdate;
376 scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
377 scene.EventManager.OnEstateToolsSunUpdate += EstateToolsSunUpdate;
378 scene.EventManager.OnGetCurrentTimeAsLindenSunHour += GetCurrentTimeAsLindenSunHour;
379
380 scene.RegisterModuleInterface<ISunModule>(this);
381
382 // This one enables the ability to type just "sun" without any parameters
383 // m_scene.AddCommand("Regions", this, "sun", "", "", HandleSunConsoleCommand);
384 foreach (KeyValuePair<string, string> kvp in GetParamList())
385 {
386 string sunCommand = string.Format("sun {0}", kvp.Key);
387 m_scene.AddCommand("Regions", this, sunCommand, string.Format("{0} [<value>]", sunCommand), kvp.Value, "", HandleSunConsoleCommand);
388 }
389
390 ready = true;
391 }
392
393 public void RemoveRegion(Scene scene)
387 { 394 {
388 ready = false; 395 ready = false;
389 396
@@ -394,14 +401,17 @@ namespace OpenSim.Region.CoreModules
394 m_scene.EventManager.OnGetCurrentTimeAsLindenSunHour -= GetCurrentTimeAsLindenSunHour; 401 m_scene.EventManager.OnGetCurrentTimeAsLindenSunHour -= GetCurrentTimeAsLindenSunHour;
395 } 402 }
396 403
397 public string Name 404 public void RegionLoaded(Scene scene)
398 { 405 {
399 get { return "SunModule"; }
400 } 406 }
401 407
402 public bool IsSharedModule 408 public void Close()
403 { 409 {
404 get { return false; } 410 }
411
412 public string Name
413 {
414 get { return "SunModule"; }
405 } 415 }
406 416
407 #endregion 417 #endregion
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 402b9fb..33aabe4 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -33,6 +33,7 @@ using System.Net;
33using log4net; 33using log4net;
34using Nini.Config; 34using Nini.Config;
35using OpenMetaverse; 35using OpenMetaverse;
36using Mono.Addins;
36using OpenSim.Framework; 37using OpenSim.Framework;
37using OpenSim.Region.CoreModules.Framework.InterfaceCommander; 38using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
38using OpenSim.Region.CoreModules.World.Terrain.FileLoaders; 39using OpenSim.Region.CoreModules.World.Terrain.FileLoaders;
@@ -43,6 +44,7 @@ using OpenSim.Region.Framework.Scenes;
43 44
44namespace OpenSim.Region.CoreModules.World.Terrain 45namespace OpenSim.Region.CoreModules.World.Terrain
45{ 46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TerrainModule")]
46 public class TerrainModule : INonSharedRegionModule, ICommandableModule, ITerrainModule 48 public class TerrainModule : INonSharedRegionModule, ICommandableModule, ITerrainModule
47 { 49 {
48 #region StandardTerrainEffects enum 50 #region StandardTerrainEffects enum
@@ -414,6 +416,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
414 private void LoadPlugins() 416 private void LoadPlugins()
415 { 417 {
416 m_plugineffects = new Dictionary<string, ITerrainEffect>(); 418 m_plugineffects = new Dictionary<string, ITerrainEffect>();
419 LoadPlugins(Assembly.GetCallingAssembly());
417 string plugineffectsPath = "Terrain"; 420 string plugineffectsPath = "Terrain";
418 421
419 // Load the files in the Terrain/ dir 422 // Load the files in the Terrain/ dir
@@ -427,34 +430,39 @@ namespace OpenSim.Region.CoreModules.World.Terrain
427 try 430 try
428 { 431 {
429 Assembly library = Assembly.LoadFrom(file); 432 Assembly library = Assembly.LoadFrom(file);
430 foreach (Type pluginType in library.GetTypes()) 433 LoadPlugins(library);
431 { 434 }
432 try 435 catch (BadImageFormatException)
433 { 436 {
434 if (pluginType.IsAbstract || pluginType.IsNotPublic) 437 }
435 continue; 438 }
439 }
436 440
437 string typeName = pluginType.Name; 441 private void LoadPlugins(Assembly library)
442 {
443 foreach (Type pluginType in library.GetTypes())
444 {
445 try
446 {
447 if (pluginType.IsAbstract || pluginType.IsNotPublic)
448 continue;
438 449
439 if (pluginType.GetInterface("ITerrainEffect", false) != null) 450 string typeName = pluginType.Name;
440 {
441 ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString()));
442 451
443 InstallPlugin(typeName, terEffect); 452 if (pluginType.GetInterface("ITerrainEffect", false) != null)
444 } 453 {
445 else if (pluginType.GetInterface("ITerrainLoader", false) != null) 454 ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString()));
446 { 455
447 ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString())); 456 InstallPlugin(typeName, terEffect);
448 m_loaders[terLoader.FileExtension] = terLoader; 457 }
449 m_log.Info("L ... " + typeName); 458 else if (pluginType.GetInterface("ITerrainLoader", false) != null)
450 } 459 {
451 } 460 ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString()));
452 catch (AmbiguousMatchException) 461 m_loaders[terLoader.FileExtension] = terLoader;
453 { 462 m_log.Info("L ... " + typeName);
454 }
455 } 463 }
456 } 464 }
457 catch (BadImageFormatException) 465 catch (AmbiguousMatchException)
458 { 466 {
459 } 467 }
460 } 468 }
@@ -1178,7 +1186,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1178 1186
1179 private void InterfaceRunPluginEffect(Object[] args) 1187 private void InterfaceRunPluginEffect(Object[] args)
1180 { 1188 {
1181 if ((string) args[0] == "list") 1189 string firstArg = (string)args[0];
1190 if (firstArg == "list")
1182 { 1191 {
1183 m_log.Info("List of loaded plugins"); 1192 m_log.Info("List of loaded plugins");
1184 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects) 1193 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects)
@@ -1187,14 +1196,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1187 } 1196 }
1188 return; 1197 return;
1189 } 1198 }
1190 if ((string) args[0] == "reload") 1199 if (firstArg == "reload")
1191 { 1200 {
1192 LoadPlugins(); 1201 LoadPlugins();
1193 return; 1202 return;
1194 } 1203 }
1195 if (m_plugineffects.ContainsKey((string) args[0])) 1204 if (m_plugineffects.ContainsKey(firstArg))
1196 { 1205 {
1197 m_plugineffects[(string) args[0]].RunEffect(m_channel); 1206 m_plugineffects[firstArg].RunEffect(m_channel);
1198 CheckForTerrainUpdates(); 1207 CheckForTerrainUpdates();
1199 } 1208 }
1200 else 1209 else
diff --git a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs
index f5f35bb..3f5d375 100644
--- a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs
+++ b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs
@@ -28,15 +28,17 @@
28using System; 28using System;
29using System.Reflection; 29using System.Reflection;
30using log4net; 30using log4net;
31using Mono.Addins;
31using Nini.Config; 32using Nini.Config;
32using OpenMetaverse; 33using OpenMetaverse;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
36 37
37namespace OpenSim.Region.CoreModules.Avatar.Vegetation 38namespace OpenSim.Region.CoreModules.World.Vegetation
38{ 39{
39 public class VegetationModule : IRegionModule, IVegetationModule 40 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "VegetationModule")]
41 public class VegetationModule : INonSharedRegionModule, IVegetationModule
40 { 42 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42 44
@@ -45,16 +47,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Vegetation
45 protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.Grass, PCode.NewTree, PCode.Tree }; 47 protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.Grass, PCode.NewTree, PCode.Tree };
46 public PCode[] CreationCapabilities { get { return creationCapabilities; } } 48 public PCode[] CreationCapabilities { get { return creationCapabilities; } }
47 49
48 public void Initialise(Scene scene, IConfigSource source) 50 public void Initialise(IConfigSource source)
51 {
52 }
53
54 public void AddRegion(Scene scene)
49 { 55 {
50 m_scene = scene; 56 m_scene = scene;
51 m_scene.RegisterModuleInterface<IVegetationModule>(this); 57 m_scene.RegisterModuleInterface<IVegetationModule>(this);
52 } 58 }
53 59
54 public void PostInitialise() {} 60 public void RemoveRegion(Scene scene)
61 {
62 m_scene.UnregisterModuleInterface<IVegetationModule>(this);
63 }
64
55 public void Close() {} 65 public void Close() {}
56 public string Name { get { return "Vegetation Module"; } } 66 public string Name { get { return "Vegetation Module"; } }
57 public bool IsSharedModule { get { return false; } } 67
68 public Type ReplaceableInterface
69 {
70 get { return null; }
71 }
72
73 public void RegionLoaded(Scene scene)
74 {
75 }
58 76
59 public SceneObjectGroup AddTree( 77 public SceneObjectGroup AddTree(
60 UUID uuid, UUID groupID, Vector3 scale, Quaternion rotation, Vector3 position, Tree treeType, bool newTree) 78 UUID uuid, UUID groupID, Vector3 scale, Quaternion rotation, Vector3 position, Tree treeType, bool newTree)
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index 3c48d07..7ef44db 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -35,6 +35,7 @@ using CSJ2K;
35using Nini.Config; 35using Nini.Config;
36using log4net; 36using log4net;
37using Rednettle.Warp3D; 37using Rednettle.Warp3D;
38using Mono.Addins;
38using OpenMetaverse; 39using OpenMetaverse;
39using OpenMetaverse.Imaging; 40using OpenMetaverse.Imaging;
40using OpenMetaverse.Rendering; 41using OpenMetaverse.Rendering;
@@ -49,6 +50,7 @@ using WarpRenderer = global::Warp3D.Warp3D;
49 50
50namespace OpenSim.Region.CoreModules.World.Warp3DMap 51namespace OpenSim.Region.CoreModules.World.Warp3DMap
51{ 52{
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "Warp3DImageModule")]
52 public class Warp3DImageModule : IMapImageGenerator, INonSharedRegionModule 54 public class Warp3DImageModule : IMapImageGenerator, INonSharedRegionModule
53 { 55 {
54 private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3"); 56 private static readonly UUID TEXTURE_METADATA_MAGIC = new UUID("802dc0e0-f080-4931-8b57-d1be8611c4f3");
@@ -66,7 +68,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
66 private Bitmap lastImage = null; 68 private Bitmap lastImage = null;
67 private DateTime lastImageTime = DateTime.MinValue; 69 private DateTime lastImageTime = DateTime.MinValue;
68 70
69 #region IRegionModule Members 71 #region Region Module interface
70 72
71 public void Initialise(IConfigSource source) 73 public void Initialise(IConfigSource source)
72 { 74 {
@@ -222,6 +224,13 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
222 bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height); 224 bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
223 } 225 }
224 226
227 // XXX: It shouldn't really be necesary to force a GC here as one should occur anyway pretty shortly
228 // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory
229 // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating
230 // this map tile simply takes a lot of memory.
231 GC.Collect();
232 m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()");
233
225 return bitmap; 234 return bitmap;
226 } 235 }
227 236
diff --git a/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs b/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs
index 9d47e19..6af4050 100644
--- a/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/Plugins/ConfigurableWind.cs
@@ -31,12 +31,14 @@ using System.Reflection;
31 31
32using log4net; 32using log4net;
33using OpenMetaverse; 33using OpenMetaverse;
34using Mono.Addins;
34 35
35using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.CoreModules.World.Wind; 37using OpenSim.Region.CoreModules.World.Wind;
37 38
38namespace OpenSim.Region.CoreModules.World.Wind.Plugins 39namespace OpenSim.Region.CoreModules.World.Wind.Plugins
39{ 40{
41 [Extension(Path = "/OpenSim/WindModule", NodeName = "WindModel", Id = "ConfigurableWind")]
40 class ConfigurableWind : Mono.Addins.TypeExtensionNode, IWindModelPlugin 42 class ConfigurableWind : Mono.Addins.TypeExtensionNode, IWindModelPlugin
41 { 43 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs b/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs
index 071e20b..fcb0c10 100644
--- a/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/Plugins/SimpleRandomWind.cs
@@ -29,11 +29,13 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30 30
31using OpenMetaverse; 31using OpenMetaverse;
32using Mono.Addins;
32 33
33using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
34 35
35namespace OpenSim.Region.CoreModules.World.Wind.Plugins 36namespace OpenSim.Region.CoreModules.World.Wind.Plugins
36{ 37{
38 [Extension(Path = "/OpenSim/WindModule", NodeName = "WindModel", Id = "SimpleRandomWind")]
37 class SimpleRandomWind : Mono.Addins.TypeExtensionNode, IWindModelPlugin 39 class SimpleRandomWind : Mono.Addins.TypeExtensionNode, IWindModelPlugin
38 { 40 {
39 private Vector2[] m_windSpeeds = new Vector2[16 * 16]; 41 private Vector2[] m_windSpeeds = new Vector2[16 * 16];
diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
index 7b6fbda..fd8e2b4 100644
--- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
@@ -40,6 +40,7 @@ using OpenSim.Region.CoreModules.World.Wind;
40 40
41namespace OpenSim.Region.CoreModules 41namespace OpenSim.Region.CoreModules
42{ 42{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WindModule")]
43 public class WindModule : IWindModule 44 public class WindModule : IWindModule
44 { 45 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -52,31 +53,31 @@ namespace OpenSim.Region.CoreModules
52 private bool m_ready = false; 53 private bool m_ready = false;
53 54
54 private bool m_enabled = false; 55 private bool m_enabled = false;
55 56 private IConfig m_windConfig;
56 private IWindModelPlugin m_activeWindPlugin = null; 57 private IWindModelPlugin m_activeWindPlugin = null;
57 private const string m_dWindPluginName = "SimpleRandomWind"; 58 private string m_dWindPluginName = "SimpleRandomWind";
58 private Dictionary<string, IWindModelPlugin> m_availableWindPlugins = new Dictionary<string, IWindModelPlugin>(); 59 private Dictionary<string, IWindModelPlugin> m_availableWindPlugins = new Dictionary<string, IWindModelPlugin>();
59 60
60 // Simplified windSpeeds based on the fact that the client protocal tracks at a resolution of 16m 61 // Simplified windSpeeds based on the fact that the client protocal tracks at a resolution of 16m
61 private Vector2[] windSpeeds = new Vector2[16 * 16]; 62 private Vector2[] windSpeeds = new Vector2[16 * 16];
62 63
63 #region IRegion Methods 64 #region INonSharedRegionModule Methods
64 65
65 public void Initialise(Scene scene, IConfigSource config) 66 public void Initialise(IConfigSource config)
66 { 67 {
67 IConfig windConfig = config.Configs["Wind"]; 68 m_windConfig = config.Configs["Wind"];
68 string desiredWindPlugin = m_dWindPluginName; 69 string desiredWindPlugin = m_dWindPluginName;
69 70
70 if (windConfig != null) 71 if (m_windConfig != null)
71 { 72 {
72 m_enabled = windConfig.GetBoolean("enabled", true); 73 m_enabled = m_windConfig.GetBoolean("enabled", true);
73 74
74 m_frameUpdateRate = windConfig.GetInt("wind_update_rate", 150); 75 m_frameUpdateRate = m_windConfig.GetInt("wind_update_rate", 150);
75 76
76 // Determine which wind model plugin is desired 77 // Determine which wind model plugin is desired
77 if (windConfig.Contains("wind_plugin")) 78 if (m_windConfig.Contains("wind_plugin"))
78 { 79 {
79 desiredWindPlugin = windConfig.GetString("wind_plugin"); 80 m_dWindPluginName = m_windConfig.GetString("wind_plugin", m_dWindPluginName);
80 } 81 }
81 } 82 }
82 83
@@ -84,104 +85,111 @@ namespace OpenSim.Region.CoreModules
84 { 85 {
85 m_log.InfoFormat("[WIND] Enabled with an update rate of {0} frames.", m_frameUpdateRate); 86 m_log.InfoFormat("[WIND] Enabled with an update rate of {0} frames.", m_frameUpdateRate);
86 87
87 m_scene = scene; 88 }
88 m_frame = 0;
89
90 // Register all the Wind Model Plug-ins
91 foreach (IWindModelPlugin windPlugin in AddinManager.GetExtensionObjects("/OpenSim/WindModule", false))
92 {
93 m_log.InfoFormat("[WIND] Found Plugin: {0}", windPlugin.Name);
94 m_availableWindPlugins.Add(windPlugin.Name, windPlugin);
95 }
96 89
97 // Check for desired plugin 90 }
98 if (m_availableWindPlugins.ContainsKey(desiredWindPlugin))
99 {
100 m_activeWindPlugin = m_availableWindPlugins[desiredWindPlugin];
101 91
102 m_log.InfoFormat("[WIND] {0} plugin found, initializing.", desiredWindPlugin); 92 public void AddRegion(Scene scene)
93 {
94 if (!m_enabled)
95 return;
103 96
104 if (windConfig != null) 97 m_scene = scene;
105 { 98 m_frame = 0;
106 m_activeWindPlugin.Initialise();
107 m_activeWindPlugin.WindConfig(m_scene, windConfig);
108 }
109 }
110 99
100 // Register all the Wind Model Plug-ins
101 foreach (IWindModelPlugin windPlugin in AddinManager.GetExtensionObjects("/OpenSim/WindModule", false))
102 {
103 m_log.InfoFormat("[WIND] Found Plugin: {0}", windPlugin.Name);
104 m_availableWindPlugins.Add(windPlugin.Name, windPlugin);
105 }
111 106
112 // if the plug-in wasn't found, default to no wind. 107 // Check for desired plugin
113 if (m_activeWindPlugin == null) 108 if (m_availableWindPlugins.ContainsKey(m_dWindPluginName))
114 { 109 {
115 m_log.ErrorFormat("[WIND] Could not find specified wind plug-in: {0}", desiredWindPlugin); 110 m_activeWindPlugin = m_availableWindPlugins[m_dWindPluginName];
116 m_log.ErrorFormat("[WIND] Defaulting to no wind.");
117 }
118 111
119 // This one puts an entry in the main help screen 112 m_log.InfoFormat("[WIND] {0} plugin found, initializing.", m_dWindPluginName);
120// m_scene.AddCommand("Regions", this, "wind", "wind", "Usage: wind <plugin> <param> [value] - Get or Update Wind paramaters", null);
121
122 // This one enables the ability to type just the base command without any parameters
123// m_scene.AddCommand("Regions", this, "wind", "", "", HandleConsoleCommand);
124 113
125 // Get a list of the parameters for each plugin 114 if (m_windConfig != null)
126 foreach (IWindModelPlugin windPlugin in m_availableWindPlugins.Values)
127 { 115 {
128// m_scene.AddCommand("Regions", this, String.Format("wind base wind_plugin {0}", windPlugin.Name), String.Format("{0} - {1}", windPlugin.Name, windPlugin.Description), "", HandleConsoleBaseCommand); 116 m_activeWindPlugin.Initialise();
129 m_scene.AddCommand( 117 m_activeWindPlugin.WindConfig(m_scene, m_windConfig);
130 "Regions",
131 this,
132 "wind base wind_update_rate",
133 "wind base wind_update_rate [<value>]",
134 "Get or set the wind update rate.",
135 "",
136 HandleConsoleBaseCommand);
137
138 foreach (KeyValuePair<string, string> kvp in windPlugin.WindParams())
139 {
140 string windCommand = String.Format("wind {0} {1}", windPlugin.Name, kvp.Key);
141 m_scene.AddCommand("Regions", this, windCommand, string.Format("{0} [<value>]", windCommand), kvp.Value, "", HandleConsoleParamCommand);
142 }
143 } 118 }
119 }
144 120
145 // Register event handlers for when Avatars enter the region, and frame ticks
146 m_scene.EventManager.OnFrame += WindUpdate;
147 m_scene.EventManager.OnMakeRootAgent += OnAgentEnteredRegion;
148 121
149 // Register the wind module 122 // if the plug-in wasn't found, default to no wind.
150 m_scene.RegisterModuleInterface<IWindModule>(this); 123 if (m_activeWindPlugin == null)
124 {
125 m_log.ErrorFormat("[WIND] Could not find specified wind plug-in: {0}", m_dWindPluginName);
126 m_log.ErrorFormat("[WIND] Defaulting to no wind.");
127 }
151 128
152 // Generate initial wind values 129 // This one puts an entry in the main help screen
153 GenWindPos(); 130 // m_scene.AddCommand("Regions", this, "wind", "wind", "Usage: wind <plugin> <param> [value] - Get or Update Wind paramaters", null);
154 131
155 // Mark Module Ready for duty 132 // This one enables the ability to type just the base command without any parameters
156 m_ready = true; 133 // m_scene.AddCommand("Regions", this, "wind", "", "", HandleConsoleCommand);
157 134
135 // Get a list of the parameters for each plugin
136 foreach (IWindModelPlugin windPlugin in m_availableWindPlugins.Values)
137 {
138 // m_scene.AddCommand("Regions", this, String.Format("wind base wind_plugin {0}", windPlugin.Name), String.Format("{0} - {1}", windPlugin.Name, windPlugin.Description), "", HandleConsoleBaseCommand);
139 m_scene.AddCommand(
140 "Regions",
141 this,
142 "wind base wind_update_rate",
143 "wind base wind_update_rate [<value>]",
144 "Get or set the wind update rate.",
145 "",
146 HandleConsoleBaseCommand);
147
148 foreach (KeyValuePair<string, string> kvp in windPlugin.WindParams())
149 {
150 string windCommand = String.Format("wind {0} {1}", windPlugin.Name, kvp.Key);
151 m_scene.AddCommand("Regions", this, windCommand, string.Format("{0} [<value>]", windCommand), kvp.Value, "", HandleConsoleParamCommand);
152 }
158 } 153 }
159 154
160 } 155 // Register event handlers for when Avatars enter the region, and frame ticks
156 m_scene.EventManager.OnFrame += WindUpdate;
157 m_scene.EventManager.OnMakeRootAgent += OnAgentEnteredRegion;
161 158
162 public void PostInitialise() 159 // Register the wind module
163 { 160 m_scene.RegisterModuleInterface<IWindModule>(this);
161
162 // Generate initial wind values
163 GenWindPos();
164
165 // Mark Module Ready for duty
166 m_ready = true;
164 } 167 }
165 168
166 public void Close() 169 public void RemoveRegion(Scene scene)
167 { 170 {
168 if (m_enabled) 171 if (!m_enabled)
172 return;
173
174 m_ready = false;
175
176 // REVIEW: If a region module is closed, is there a possibility that it'll re-open/initialize ??
177 m_activeWindPlugin = null;
178 foreach (IWindModelPlugin windPlugin in m_availableWindPlugins.Values)
169 { 179 {
170 m_ready = false; 180 windPlugin.Dispose();
181 }
171 182
172 // REVIEW: If a region module is closed, is there a possibility that it'll re-open/initialize ?? 183 m_availableWindPlugins.Clear();
173 m_activeWindPlugin = null;
174 foreach (IWindModelPlugin windPlugin in m_availableWindPlugins.Values)
175 {
176 windPlugin.Dispose();
177 }
178 184
179 m_availableWindPlugins.Clear(); 185 // Remove our hooks
186 m_scene.EventManager.OnFrame -= WindUpdate;
187 m_scene.EventManager.OnMakeRootAgent -= OnAgentEnteredRegion;
180 188
181 // Remove our hooks 189 }
182 m_scene.EventManager.OnFrame -= WindUpdate; 190
183 m_scene.EventManager.OnMakeRootAgent -= OnAgentEnteredRegion; 191 public void Close()
184 } 192 {
185 } 193 }
186 194
187 public string Name 195 public string Name
@@ -189,11 +197,14 @@ namespace OpenSim.Region.CoreModules
189 get { return "WindModule"; } 197 get { return "WindModule"; }
190 } 198 }
191 199
192 public bool IsSharedModule 200 public Type ReplaceableInterface
193 { 201 {
194 get { return false; } 202 get { return null; }
195 } 203 }
196 204
205 public void RegionLoaded(Scene scene)
206 {
207 }
197 208
198 #endregion 209 #endregion
199 210
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
index 2417b1a..4c96a50 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs
@@ -24,11 +24,13 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27using System;
27using System.Collections.Generic; 28using System.Collections.Generic;
28using System.Reflection; 29using System.Reflection;
29using log4net; 30using log4net;
30using Nini.Config; 31using Nini.Config;
31using OpenMetaverse; 32using OpenMetaverse;
33using Mono.Addins;
32using OpenSim.Framework; 34using OpenSim.Framework;
33using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
@@ -37,16 +39,22 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
37 39
38namespace OpenSim.Region.CoreModules.World.WorldMap 40namespace OpenSim.Region.CoreModules.World.WorldMap
39{ 41{
40 public class MapSearchModule : IRegionModule 42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MapSearchModule")]
43 public class MapSearchModule : ISharedRegionModule
41 { 44 {
42 private static readonly ILog m_log = 45 private static readonly ILog m_log =
43 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 47
45 Scene m_scene = null; // only need one for communication with GridService 48 Scene m_scene = null; // only need one for communication with GridService
46 List<Scene> m_scenes = new List<Scene>(); 49 List<Scene> m_scenes = new List<Scene>();
50 List<UUID> m_Clients;
47 51
48 #region IRegionModule Members 52 #region ISharedRegionModule Members
49 public void Initialise(Scene scene, IConfigSource source) 53 public void Initialise(IConfigSource source)
54 {
55 }
56
57 public void AddRegion(Scene scene)
50 { 58 {
51 if (m_scene == null) 59 if (m_scene == null)
52 { 60 {
@@ -55,6 +63,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
55 63
56 m_scenes.Add(scene); 64 m_scenes.Add(scene);
57 scene.EventManager.OnNewClient += OnNewClient; 65 scene.EventManager.OnNewClient += OnNewClient;
66 m_Clients = new List<UUID>();
67 }
68
69 public void RemoveRegion(Scene scene)
70 {
71 m_scenes.Remove(scene);
72 if (m_scene == scene && m_scenes.Count > 0)
73 m_scene = m_scenes[0];
74
75 scene.EventManager.OnNewClient -= OnNewClient;
58 } 76 }
59 77
60 public void PostInitialise() 78 public void PostInitialise()
@@ -72,16 +90,40 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
72 get { return "MapSearchModule"; } 90 get { return "MapSearchModule"; }
73 } 91 }
74 92
75 public bool IsSharedModule 93 public Type ReplaceableInterface
76 { 94 {
77 get { return true; } 95 get { return null; }
78 } 96 }
79 97
98 public void RegionLoaded(Scene scene)
99 {
100 }
80 #endregion 101 #endregion
81 102
82 private void OnNewClient(IClientAPI client) 103 private void OnNewClient(IClientAPI client)
83 { 104 {
84 client.OnMapNameRequest += OnMapNameRequest; 105 client.OnMapNameRequest += OnMapNameRequestHandler;
106 }
107
108 private void OnMapNameRequestHandler(IClientAPI remoteClient, string mapName, uint flags)
109 {
110 lock (m_Clients)
111 {
112 if (m_Clients.Contains(remoteClient.AgentId))
113 return;
114
115 m_Clients.Add(remoteClient.AgentId);
116 }
117
118 try
119 {
120 OnMapNameRequest(remoteClient, mapName, flags);
121 }
122 finally
123 {
124 lock (m_Clients)
125 m_Clients.Remove(remoteClient.AgentId);
126 }
85 } 127 }
86 128
87 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags) 129 private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags)
@@ -175,6 +217,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
175 }); 217 });
176 } 218 }
177 219
220 private void AddFinalBlock(List<MapBlockData> blocks)
221 {
222 // final block, closing the search result
223 MapBlockData data = new MapBlockData();
224 data.Agents = 0;
225 data.Access = 255;
226 data.MapImageId = UUID.Zero;
227 data.Name = "";
228 data.RegionFlags = 0;
229 data.WaterHeight = 0; // not used
230 data.X = 0;
231 data.Y = 0;
232 blocks.Add(data);
233 }
178// private Scene GetClientScene(IClientAPI client) 234// private Scene GetClientScene(IClientAPI client)
179// { 235// {
180// foreach (Scene s in m_scenes) 236// foreach (Scene s in m_scenes)
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 26b406e..2184a59 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -40,6 +40,7 @@ using Nini.Config;
40using OpenMetaverse; 40using OpenMetaverse;
41using OpenMetaverse.Imaging; 41using OpenMetaverse.Imaging;
42using OpenMetaverse.StructuredData; 42using OpenMetaverse.StructuredData;
43using Mono.Addins;
43using OpenSim.Framework; 44using OpenSim.Framework;
44using OpenSim.Framework.Capabilities; 45using OpenSim.Framework.Capabilities;
45using OpenSim.Framework.Monitoring; 46using OpenSim.Framework.Monitoring;
@@ -55,6 +56,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
55 56
56namespace OpenSim.Region.CoreModules.World.WorldMap 57namespace OpenSim.Region.CoreModules.World.WorldMap
57{ 58{
59 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WorldMapModule")]
58 public class WorldMapModule : INonSharedRegionModule, IWorldMapModule 60 public class WorldMapModule : INonSharedRegionModule, IWorldMapModule
59 { 61 {
60 private static readonly ILog m_log = 62 private static readonly ILog m_log =
diff --git a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
index 5540656..5e62f23 100644
--- a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
+++ b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
@@ -35,15 +35,20 @@ using System.Xml;
35using log4net; 35using log4net;
36using Nini.Config; 36using Nini.Config;
37using OpenMetaverse; 37using OpenMetaverse;
38using Mono.Addins;
38using OpenSim.Framework; 39using OpenSim.Framework;
39using OpenSim.Framework.Communications; 40using OpenSim.Framework.Communications;
40using OpenSim.Region.DataSnapshot.Interfaces; 41using OpenSim.Region.DataSnapshot.Interfaces;
41using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
43 44
45[assembly: Addin("DataSnapshot", "0.1")]
46[assembly: AddinDependency("OpenSim", "0.5")]
47
44namespace OpenSim.Region.DataSnapshot 48namespace OpenSim.Region.DataSnapshot
45{ 49{
46 public class DataSnapshotManager : IRegionModule, IDataSnapshot 50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DataSnapshotManager")]
51 public class DataSnapshotManager : ISharedRegionModule, IDataSnapshot
47 { 52 {
48 #region Class members 53 #region Class members
49 //Information from config 54 //Information from config
@@ -67,6 +72,7 @@ namespace OpenSim.Region.DataSnapshot
67 public string m_listener_port = ConfigSettings.DefaultRegionHttpPort.ToString(); 72 public string m_listener_port = ConfigSettings.DefaultRegionHttpPort.ToString();
68 public string m_hostname = "127.0.0.1"; 73 public string m_hostname = "127.0.0.1";
69 private UUID m_Secret = UUID.Random(); 74 private UUID m_Secret = UUID.Random();
75 private bool m_servicesNotified = false;
70 76
71 //Update timers 77 //Update timers
72 private int m_period = 20; // in seconds 78 private int m_period = 20; // in seconds
@@ -93,9 +99,9 @@ namespace OpenSim.Region.DataSnapshot
93 99
94 #endregion 100 #endregion
95 101
96 #region IRegionModule 102 #region Region Module interface
97 103
98 public void Initialise(Scene scene, IConfigSource config) 104 public void Initialise(IConfigSource config)
99 { 105 {
100 if (!m_configLoaded) 106 if (!m_configLoaded)
101 { 107 {
@@ -133,82 +139,128 @@ namespace OpenSim.Region.DataSnapshot
133 m_enabled = false; 139 m_enabled = false;
134 return; 140 return;
135 } 141 }
136 }
137 142
138 if (m_enabled) 143 if (m_enabled)
139 { 144 m_snapStore = new SnapshotStore(m_snapsDir, m_gridinfo, m_listener_port, m_hostname);
140 //Hand it the first scene, assuming that all scenes have the same BaseHTTPServer 145 }
141 new DataRequestHandler(scene, this);
142 146
143 m_hostname = scene.RegionInfo.ExternalHostName; 147 }
144 m_snapStore = new SnapshotStore(m_snapsDir, m_gridinfo, m_listener_port, m_hostname);
145 148
146 MakeEverythingStale(); 149 }
147 150
148 if (m_dataServices != "" && m_dataServices != "noservices") 151 public void AddRegion(Scene scene)
149 NotifyDataServices(m_dataServices, "online"); 152 {
150 } 153 if (!m_enabled)
151 } 154 return;
152 155
153 if (m_enabled) 156 m_log.DebugFormat("[DATASNAPSHOT]: Module added to Scene {0}.", scene.RegionInfo.RegionName);
154 {
155 m_log.Info("[DATASNAPSHOT]: Scene added to module.");
156 157
157 m_snapStore.AddScene(scene); 158 m_snapStore.AddScene(scene);
158 m_scenes.Add(scene); 159 m_scenes.Add(scene);
159 160
160 Assembly currentasm = Assembly.GetExecutingAssembly(); 161 Assembly currentasm = Assembly.GetExecutingAssembly();
161 162
162 foreach (Type pluginType in currentasm.GetTypes()) 163 foreach (Type pluginType in currentasm.GetTypes())
164 {
165 if (pluginType.IsPublic)
163 { 166 {
164 if (pluginType.IsPublic) 167 if (!pluginType.IsAbstract)
165 { 168 {
166 if (!pluginType.IsAbstract) 169 if (pluginType.GetInterface("IDataSnapshotProvider") != null)
167 { 170 {
168 if (pluginType.GetInterface("IDataSnapshotProvider") != null) 171 IDataSnapshotProvider module = (IDataSnapshotProvider)Activator.CreateInstance(pluginType);
169 { 172 module.Initialize(scene, this);
170 IDataSnapshotProvider module = (IDataSnapshotProvider)Activator.CreateInstance(pluginType); 173 module.OnStale += MarkDataStale;
171 module.Initialize(scene, this);
172 module.OnStale += MarkDataStale;
173 174
174 m_dataproviders.Add(module); 175 m_dataproviders.Add(module);
175 m_snapStore.AddProvider(module); 176 m_snapStore.AddProvider(module);
176 177
177 m_log.Info("[DATASNAPSHOT]: Added new data provider type: " + pluginType.Name); 178 m_log.Debug("[DATASNAPSHOT]: Added new data provider type: " + pluginType.Name);
178 }
179 } 179 }
180 } 180 }
181 } 181 }
182 }
183
184 // Must be done here because on shared modules, PostInitialise() will run
185 // BEFORE any scenes are registered. There is no "all scenes have been loaded"
186 // kind of callback because scenes may be created dynamically, so we cannot
187 // have that info, ever.
188 if (!m_servicesNotified)
189 {
190 //Hand it the first scene, assuming that all scenes have the same BaseHTTPServer
191 new DataRequestHandler(m_scenes[0], this);
192
193 m_hostname = m_scenes[0].RegionInfo.ExternalHostName;
182 194
183 //scene.OnRestart += OnSimRestart; 195 if (m_dataServices != "" && m_dataServices != "noservices")
184 scene.EventManager.OnShutdown += delegate() { OnSimRestart(scene.RegionInfo); }; 196 NotifyDataServices(m_dataServices, "online");
197
198 m_servicesNotified = true;
185 } 199 }
186 else 200 }
201
202 public void RemoveRegion(Scene scene)
203 {
204 if (!m_enabled)
205 return;
206
207 m_log.Info("[DATASNAPSHOT]: Region " + scene.RegionInfo.RegionName + " is being removed, removing from indexing");
208 Scene restartedScene = SceneForUUID(scene.RegionInfo.RegionID);
209
210 m_scenes.Remove(restartedScene);
211 m_snapStore.RemoveScene(restartedScene);
212
213 //Getting around the fact that we can't remove objects from a collection we are enumerating over
214 List<IDataSnapshotProvider> providersToRemove = new List<IDataSnapshotProvider>();
215
216 foreach (IDataSnapshotProvider provider in m_dataproviders)
217 {
218 if (provider.GetParentScene == restartedScene)
219 {
220 providersToRemove.Add(provider);
221 }
222 }
223
224 foreach (IDataSnapshotProvider provider in providersToRemove)
187 { 225 {
188 //m_log.Debug("[DATASNAPSHOT]: Data snapshot disabled, not adding scene to module (or anything else)."); 226 m_dataproviders.Remove(provider);
227 m_snapStore.RemoveProvider(provider);
189 } 228 }
229
230 m_snapStore.RemoveScene(restartedScene);
190 } 231 }
191 232
192 public void Close() 233 public void PostInitialise()
193 { 234 {
194 if (m_enabled && m_dataServices != "" && m_dataServices != "noservices")
195 NotifyDataServices(m_dataServices, "offline");
196 } 235 }
197 236
237 public void RegionLoaded(Scene scene)
238 {
239 if (!m_enabled)
240 return;
241
242 m_log.DebugFormat("[DATASNAPSHOT]: Marking scene {0} as stale.", scene.RegionInfo.RegionName);
243 m_snapStore.ForceSceneStale(scene);
244 }
198 245
199 public bool IsSharedModule 246 public void Close()
200 { 247 {
201 get { return true; } 248 if (!m_enabled)
249 return;
250
251 if (m_enabled && m_dataServices != "" && m_dataServices != "noservices")
252 NotifyDataServices(m_dataServices, "offline");
202 } 253 }
203 254
255
204 public string Name 256 public string Name
205 { 257 {
206 get { return "External Data Generator"; } 258 get { return "External Data Generator"; }
207 } 259 }
208 260
209 public void PostInitialise() 261 public Type ReplaceableInterface
210 { 262 {
211 263 get { return null; }
212 } 264 }
213 265
214 #endregion 266 #endregion
@@ -399,35 +451,7 @@ namespace OpenSim.Region.DataSnapshot
399 m_snapStore.ForceSceneStale(scene); 451 m_snapStore.ForceSceneStale(scene);
400 } 452 }
401 } 453 }
402
403 #endregion 454 #endregion
404 455
405 public void OnSimRestart(RegionInfo thisRegion)
406 {
407 m_log.Info("[DATASNAPSHOT]: Region " + thisRegion.RegionName + " is restarting, removing from indexing");
408 Scene restartedScene = SceneForUUID(thisRegion.RegionID);
409
410 m_scenes.Remove(restartedScene);
411 m_snapStore.RemoveScene(restartedScene);
412
413 //Getting around the fact that we can't remove objects from a collection we are enumerating over
414 List<IDataSnapshotProvider> providersToRemove = new List<IDataSnapshotProvider>();
415
416 foreach (IDataSnapshotProvider provider in m_dataproviders)
417 {
418 if (provider.GetParentScene == restartedScene)
419 {
420 providersToRemove.Add(provider);
421 }
422 }
423
424 foreach (IDataSnapshotProvider provider in providersToRemove)
425 {
426 m_dataproviders.Remove(provider);
427 m_snapStore.RemoveProvider(provider);
428 }
429
430 m_snapStore.RemoveScene(restartedScene);
431 }
432 } 456 }
433} 457}
diff --git a/OpenSim/Region/DataSnapshot/Interfaces/IDataSnapshot.cs b/OpenSim/Region/DataSnapshot/Interfaces/IDataSnapshot.cs
index 59cdab9..3b3db65 100644
--- a/OpenSim/Region/DataSnapshot/Interfaces/IDataSnapshot.cs
+++ b/OpenSim/Region/DataSnapshot/Interfaces/IDataSnapshot.cs
@@ -32,6 +32,5 @@ namespace OpenSim.Region.DataSnapshot.Interfaces
32 public interface IDataSnapshot 32 public interface IDataSnapshot
33 { 33 {
34 XmlDocument GetSnapshot(string regionName); 34 XmlDocument GetSnapshot(string regionName);
35 void MakeEverythingStale();
36 } 35 }
37} 36}
diff --git a/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs b/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b926264
--- /dev/null
+++ b/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.DataSnapshot")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("06c36944-a28d-470e-912c-654c3edaba6b")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 90a13a7..d781eae 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -114,6 +114,15 @@ namespace OpenSim.Region.Framework.Interfaces
114 void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID); 114 void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID);
115 115
116 /// <summary> 116 /// <summary>
117 /// Detach the given item to the ground at the specified coordinates & rotation
118 /// </summary>
119 /// <param name="sp"></param>
120 /// <param name="objectLocalID"></param>
121 /// <param name="absolutePos"></param>
122 /// <param name="absoluteRot"></param>
123 void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID, Vector3 absolutePos, Quaternion absoluteRot);
124
125 /// <summary>
117 /// Detach the given attachment so that it remains in the user's inventory. 126 /// Detach the given attachment so that it remains in the user's inventory.
118 /// </summary> 127 /// </summary>
119 /// <param name="sp">/param> 128 /// <param name="sp">/param>
diff --git a/OpenSim/Region/Framework/Interfaces/ICloudModule.cs b/OpenSim/Region/Framework/Interfaces/ICloudModule.cs
index 7296ac3..54172bd 100644
--- a/OpenSim/Region/Framework/Interfaces/ICloudModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ICloudModule.cs
@@ -27,7 +27,7 @@
27 27
28namespace OpenSim.Region.Framework.Interfaces 28namespace OpenSim.Region.Framework.Interfaces
29{ 29{
30 public interface ICloudModule : IRegionModule 30 public interface ICloudModule
31 { 31 {
32 /// <summary> 32 /// <summary>
33 /// Retrieves the cloud density at the given region coordinates 33 /// Retrieves the cloud density at the given region coordinates
diff --git a/OpenSim/Region/Framework/Interfaces/IDialogModule.cs b/OpenSim/Region/Framework/Interfaces/IDialogModule.cs
index be9764a..4d35c1c 100644
--- a/OpenSim/Region/Framework/Interfaces/IDialogModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDialogModule.cs
@@ -33,95 +33,140 @@ namespace OpenSim.Region.Framework.Interfaces
33 public interface IDialogModule 33 public interface IDialogModule
34 { 34 {
35 /// <summary> 35 /// <summary>
36 /// Send a non-modal alert message to a particular user. This can disappear from the user's view after a 36 /// Send a non-modal alert message to a particular user. This can
37 /// small interval. 37 /// disappear from the user's view after a small interval.
38 /// </summary> 38 /// </summary>
39 /// <param name="client"></param> 39 /// <param name="client">
40 /// <param name="message"></param> 40 /// IClientAPI object representing the user.
41 /// </param>
42 /// <param name="message">Message text to send to the user.</param>
41 void SendAlertToUser(IClientAPI client, string message); 43 void SendAlertToUser(IClientAPI client, string message);
42 44
43 /// <summary> 45 /// <summary>
44 /// Send an alert message to a particular user. 46 /// Send an alert message to a particular user.
45 /// </summary> 47 /// </summary>
46 /// <param name="client"></param> 48 /// <param name="client">
47 /// <param name="message"></param> 49 /// IClientAPI object representing the user.
48 /// <param name="modal"></param> 50 /// </param>
51 /// <param name="message">Message text to send to the user.</param>
52 /// <param name="modal">Flag to control modality.</param>
49 void SendAlertToUser(IClientAPI client, string message, bool modal); 53 void SendAlertToUser(IClientAPI client, string message, bool modal);
50 54
51 /// <summary> 55 /// <summary>
52 /// Send a non-modal alert message to a particular user. 56 /// Send a non-modal alert message to a particular user.
53 /// </summary> 57 /// </summary>
54 /// <param name="agentID"></param> 58 /// <param name="agentID">UUID of agent representing the user.</param>
55 /// <param name="message"></param> 59 /// <param name="message">Message text to send to the user.</param>
56 void SendAlertToUser(UUID agentID, string message); 60 void SendAlertToUser(UUID agentID, string message);
57 61
58 /// <summary> 62 /// <summary>
59 /// Send an alert message to a particular user. 63 /// Send an alert message to a particular user.
60 /// </summary> 64 /// </summary>
61 /// <param name="agentID"></param> 65 /// <param name="agentID">UUID of agent representing the user.</param>
62 /// <param name="message"></param> 66 /// <param name="message">Message text to send to the user.</param>
63 /// <param name="modal"></param> 67 /// <param name="modal">Flag to control modality.</param>
64 void SendAlertToUser(UUID agentID, string message, bool modal); 68 void SendAlertToUser(UUID agentID, string message, bool modal);
65 69
66 /// <summary> 70 /// <summary>
67 /// Send an alert message to a particular user. 71 /// Send an alert message to a particular user.
68 /// </summary> 72 /// </summary>
69 /// <param name="firstName"></param> 73 /// <param name="firstName">Account first name</param>
70 /// <param name="lastName"></param> 74 /// <param name="lastName">Account last name</param>
71 /// <param name="message"></param> 75 /// <param name="message">Message text to send to the user.</param>
72 /// <param name="modal"></param> 76 /// <param name="modal">Flag to control modality.</param>
73 void SendAlertToUser(string firstName, string lastName, string message, bool modal); 77 void SendAlertToUser(string firstName, string lastName,
74 78 string message, bool modal);
79
75 /// <summary> 80 /// <summary>
76 /// Send an alert message to all users in the scene. 81 /// Send an alert message to all users in the scene.
77 /// </summary> 82 /// </summary>
78 /// <param name="message"></param> 83 /// <param name="message">Message text to send to all users.</param>
79 void SendGeneralAlert(string message); 84 void SendGeneralAlert(string message);
80 85
81 /// <summary> 86 /// <summary>
82 /// Send a dialog box to a particular user. 87 /// Send a dialog box to a particular user.
83 /// </summary> 88 /// </summary>
84 /// <param name="avatarID"></param> 89 /// <param name="avatarID">
85 /// <param name="objectName"></param> 90 /// UUID of the avatar representing the user.
86 /// <param name="objectID"></param> 91 /// </param>
87 /// <param name="ownerID"></param> 92 /// <param name="objectName">
88 /// <param name="message"></param> 93 /// Name of the object sending the dialog.
89 /// <param name="textureID"></param> 94 /// </param>
90 /// <param name="ch"></param> 95 /// <param name="objectID">
91 /// <param name="buttonlabels"></param> 96 /// UUID of the object sending the dialog.
92 void SendDialogToUser( 97 /// </param>
93 UUID avatarID, string objectName, UUID objectID, UUID ownerID, 98 /// <param name="ownerID">
94 string message, UUID textureID, int ch, string[] buttonlabels); 99 /// UUID of the user that owns the object.
95 100 /// </param>
101 /// <param name="message">Message text to send to the user.</param>
102 /// <param name="textureID">
103 /// Texture UUID to pass along with the dialog.
104 /// </param>
105 /// <param name="ch">
106 /// Channel on which the selected button text should be broadcast.
107 /// </param>
108 /// <param name="buttonlabels">Dialog button text.</param>
109 void SendDialogToUser(UUID avatarID, string objectName, UUID objectID,
110 UUID ownerID, string message, UUID textureID, int ch,
111 string[] buttonlabels);
112
96 /// <summary> 113 /// <summary>
97 /// Send a url to a particular user. 114 /// Send a url to a particular user.
98 /// </summary> 115 /// </summary>
99 /// <param name="avatarID"></param> 116 /// <param name="avatarID">
100 /// <param name="objectName"></param> 117 /// UUID of the avatar representing the user.
101 /// <param name="objectID"></param> 118 /// </param>
102 /// <param name="ownerID"></param> 119 /// <param name="objectName">
103 /// <param name="groupOwned"></param> 120 /// Name of the object sending the dialog.
104 /// <param name="message"></param> 121 /// </param>
105 /// <param name="url"></param> 122 /// <param name="objectID">
106 void SendUrlToUser( 123 /// UUID of the object sending the dialog.
107 UUID avatarID, string objectName, UUID objectID, UUID ownerID, bool groupOwned, string message, string url); 124 /// </param>
108 125 /// <param name="ownerID">
126 /// UUID of the user that owns the object.
127 /// </param>
128 /// <param name="groupOwned">
129 /// Flag indicating whether or not the object is group-owned.
130 /// </param>
131 /// <param name="message">Message text to send to the user.</param>
132 /// <param name="url">Url to send to the user.</param>
133 void SendUrlToUser(UUID avatarID, string objectName, UUID objectID,
134 UUID ownerID, bool groupOwned, string message, string url);
135
109 /// <summary> 136 /// <summary>
110 /// Send a notification to all users in the scene. This notification should remain around until the 137 /// Send a notification to all users in the scene. This notification
111 /// user explicitly dismisses it. 138 /// should remain around until the user explicitly dismisses it.
112 /// </summary> 139 /// </summary>
113 /// 140 /// <remarks>
114 /// On the Linden Labs Second Client (as of 1.21), this is a big blue box message on the upper right of the 141 /// On the Linden Labs Second Client (as of 1.21), this is a big blue
115 /// screen. 142 /// box message on the upper right of the screen.
116 /// 143 /// </remarks>
117 /// <param name="fromAvatarID">The user sending the message</param> 144 /// <param name="fromAvatarID">The user sending the message</param>
118 /// <param name="fromAvatarName">The name of the user doing the sending</param> 145 /// <param name="fromAvatarName">
146 /// The name of the user doing the sending
147 /// </param>
119 /// <param name="message">The message being sent to the user</param> 148 /// <param name="message">The message being sent to the user</param>
120 void SendNotificationToUsersInRegion(UUID fromAvatarID, string fromAvatarName, string message); 149 void SendNotificationToUsersInRegion(UUID fromAvatarID,
121 150 string fromAvatarName, string message);
151
122 /// <summary> 152 /// <summary>
123 /// Send a textbox entry for the client to respond to 153 /// Send a textbox entry for the client to respond to
124 /// </summary> 154 /// </summary>
125 void SendTextBoxToUser(UUID avatarid, string message, int chatChannel, string name, UUID objectid, UUID ownerid); 155 /// <param name="avatarID">
156 /// UUID of the avatar representing the user.
157 /// </param>
158 /// <param name="message">Message text to send to the user.</param>
159 /// <param name="chatChannel">
160 /// Chat channel that the user's input should be broadcast on.
161 /// </param>
162 /// <param name="name">Name of the object sending the dialog.</param>
163 /// <param name="objectid">
164 /// UUID of the object sending the dialog.
165 /// </param>
166 /// <param name="ownerid">
167 /// UUID of the user that owns the object.
168 /// </param>
169 void SendTextBoxToUser(UUID avatarid, string message, int chatChannel,
170 string name, UUID objectid, UUID ownerid);
126 } 171 }
127} 172}
diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
index 8954513..6df5cc2 100644
--- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
@@ -25,6 +25,8 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Drawing;
28using System.IO; 30using System.IO;
29using OpenMetaverse; 31using OpenMetaverse;
30 32
@@ -33,7 +35,14 @@ namespace OpenSim.Region.Framework.Interfaces
33 public interface IDynamicTextureManager 35 public interface IDynamicTextureManager
34 { 36 {
35 void RegisterRender(string handleType, IDynamicTextureRender render); 37 void RegisterRender(string handleType, IDynamicTextureRender render);
36 void ReturnData(UUID id, byte[] data); 38
39 /// <summary>
40 /// Used by IDynamicTextureRender implementations to return renders
41 /// </summary>
42 /// <param name='id'></param>
43 /// <param name='data'></param>
44 /// <param name='isReuseable'></param>
45 void ReturnData(UUID id, IDynamicTexture texture);
37 46
38 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, 47 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
39 int updateTimer); 48 int updateTimer);
@@ -113,11 +122,65 @@ namespace OpenSim.Region.Framework.Interfaces
113 string GetName(); 122 string GetName();
114 string GetContentType(); 123 string GetContentType();
115 bool SupportsAsynchronous(); 124 bool SupportsAsynchronous();
116 byte[] ConvertUrl(string url, string extraParams); 125
117 byte[] ConvertStream(Stream data, string extraParams); 126// /// <summary>
127// /// Return true if converting the input body and extra params data will always result in the same byte[] array
128// /// </summary>
129// /// <remarks>
130// /// This method allows the caller to use a previously generated asset if it has one.
131// /// </remarks>
132// /// <returns></returns>
133// /// <param name='bodyData'></param>
134// /// <param name='extraParams'></param>
135// bool AlwaysIdenticalConversion(string bodyData, string extraParams);
136
137 IDynamicTexture ConvertUrl(string url, string extraParams);
138 IDynamicTexture ConvertData(string bodyData, string extraParams);
139
118 bool AsyncConvertUrl(UUID id, string url, string extraParams); 140 bool AsyncConvertUrl(UUID id, string url, string extraParams);
119 bool AsyncConvertData(UUID id, string bodyData, string extraParams); 141 bool AsyncConvertData(UUID id, string bodyData, string extraParams);
142
120 void GetDrawStringSize(string text, string fontName, int fontSize, 143 void GetDrawStringSize(string text, string fontName, int fontSize,
121 out double xSize, out double ySize); 144 out double xSize, out double ySize);
122 } 145 }
146
147 public interface IDynamicTexture
148 {
149 /// <summary>
150 /// Input commands used to generate this data.
151 /// </summary>
152 /// <remarks>
153 /// Null if input commands were not used.
154 /// </remarks>
155 string InputCommands { get; }
156
157 /// <summary>
158 /// Uri used to generate this data.
159 /// </summary>
160 /// <remarks>
161 /// Null if a uri was not used.
162 /// </remarks>
163 Uri InputUri { get; }
164
165 /// <summary>
166 /// Extra input params used to generate this data.
167 /// </summary>
168 string InputParams { get; }
169
170 /// <summary>
171 /// Texture data.
172 /// </summary>
173 byte[] Data { get; }
174
175 /// <summary>
176 /// Size of texture.
177 /// </summary>
178 Size Size { get; }
179
180 /// <summary>
181 /// Signal whether the texture is reuseable (i.e. whether the same input data will always generate the same
182 /// texture).
183 /// </summary>
184 bool IsReuseable { get; }
185 }
123} 186}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 4274cbe..8028d87 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -152,6 +152,19 @@ namespace OpenSim.Region.Framework.Interfaces
152 void StopScriptInstance(UUID itemId); 152 void StopScriptInstance(UUID itemId);
153 153
154 /// <summary> 154 /// <summary>
155 /// Try to get the script running status.
156 /// </summary>
157 /// <returns>
158 /// Returns true if a script for the item was found in one of the simulator's script engines. In this case,
159 /// the running parameter will reflect the running status.
160 /// Returns false if the item could not be found, if the item is not a script or if a script instance for the
161 /// item was not found in any of the script engines. In this case, running status is irrelevant.
162 /// </returns>
163 /// <param name='itemId'></param>
164 /// <param name='running'></param>
165 bool TryGetScriptInstanceRunning(UUID itemId, out bool running);
166
167 /// <summary>
155 /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative 168 /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative
156 /// name is chosen. 169 /// name is chosen.
157 /// </summary> 170 /// </summary>
@@ -270,17 +283,25 @@ namespace OpenSim.Region.Framework.Interfaces
270 void ApplyGodPermissions(uint perms); 283 void ApplyGodPermissions(uint perms);
271 284
272 /// <summary> 285 /// <summary>
286 /// Number of items in this inventory.
287 /// </summary>
288 int Count { get; }
289
290 /// <summary>
273 /// Returns true if this inventory contains any scripts 291 /// Returns true if this inventory contains any scripts
274 /// </summary></returns> 292 /// </summary></returns>
275 bool ContainsScripts(); 293 bool ContainsScripts();
276 294
277 /// <summary> 295 /// <summary>
278 /// Returns the count of scripts contained 296 /// Number of scripts in this inventory.
279 /// </summary></returns> 297 /// </summary>
298 /// <remarks>
299 /// Includes both running and non running scripts.
300 /// </remarks>
280 int ScriptCount(); 301 int ScriptCount();
281 302
282 /// <summary> 303 /// <summary>
283 /// Returns the count of running scripts contained 304 /// Number of running scripts in this inventory.
284 /// </summary></returns> 305 /// </summary></returns>
285 int RunningScriptCount(); 306 int RunningScriptCount();
286 307
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index ca2ad94..292efa4 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -46,6 +46,10 @@ namespace OpenSim.Region.Framework.Interfaces
46 /// </summary> 46 /// </summary>
47 void sendRegionHandshakeToAll(); 47 void sendRegionHandshakeToAll();
48 void TriggerEstateInfoChange(); 48 void TriggerEstateInfoChange();
49
50 /// <summary>
51 /// Fires the OnRegionInfoChange event.
52 /// </summary>
49 void TriggerRegionInfoChange(); 53 void TriggerRegionInfoChange();
50 54
51 void setEstateTerrainBaseTexture(int level, UUID texture); 55 void setEstateTerrainBaseTexture(int level, UUID texture);
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
index baac6e8..da39e95 100644
--- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
@@ -35,7 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces
35 35
36 public interface IJsonStoreModule 36 public interface IJsonStoreModule
37 { 37 {
38 bool CreateStore(string value, out UUID result); 38 bool CreateStore(string value, ref UUID result);
39 bool DestroyStore(UUID storeID); 39 bool DestroyStore(UUID storeID);
40 bool TestPath(UUID storeID, string path, bool useJson); 40 bool TestPath(UUID storeID, string path, bool useJson);
41 bool SetValue(UUID storeID, string path, string value, bool useJson); 41 bool SetValue(UUID storeID, string path, string value, bool useJson);
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionModule.cs b/OpenSim/Region/Framework/Interfaces/ILightShareModule.cs
index 2bb0c75..b5fd24f 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ILightShareModule.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 *
@@ -25,29 +25,9 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using Nini.Config;
29using OpenSim.Region.Framework.Scenes;
30
31namespace OpenSim.Region.Framework.Interfaces 28namespace OpenSim.Region.Framework.Interfaces
32{ 29{
33 /// <summary> 30 public interface ILightShareModule
34 /// DEPRECATED! Use INonSharedRegionModule or ISharedRegionModule instead
35 /// </summary>
36 public interface IRegionModule
37 { 31 {
38 /// <summary>
39 /// Initialize the module.
40 /// </summary>
41 /// <remarks>
42 /// For a shared module this can be called multiple times - once per scene.
43 /// </remarks>
44 /// <param name="scene"></param>
45 /// <param name="source">Configuration information. For a shared module this will be identical on every scene call</param>
46 void Initialise(Scene scene, IConfigSource source);
47
48 void PostInitialise();
49 void Close();
50 string Name { get; }
51 bool IsSharedModule { get; }
52 } 32 }
53} 33} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
index d582149..9817cf7 100644
--- a/OpenSim/Region/Framework/Interfaces/INPCModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
@@ -32,14 +32,16 @@ using OpenSim.Region.Framework.Scenes;
32namespace OpenSim.Region.Framework.Interfaces 32namespace OpenSim.Region.Framework.Interfaces
33{ 33{
34 /// <summary> 34 /// <summary>
35 /// Temporary interface. More methods to come at some point to make NPCs more object oriented rather than 35 /// Temporary interface. More methods to come at some point to make NPCs
36 /// controlling purely through module level interface calls (e.g. sit/stand). 36 /// more object oriented rather than controlling purely through module
37 /// level interface calls (e.g. sit/stand).
37 /// </summary> 38 /// </summary>
38 public interface INPC 39 public interface INPC
39 { 40 {
40 /// <summary> 41 /// <summary>
41 /// Should this NPC be sensed by LSL sensors as an 'agent' (interpreted here to mean a normal user) 42 /// Should this NPC be sensed by LSL sensors as an 'agent'
42 /// rather than an OpenSim specific NPC extension? 43 /// (interpreted here to mean a normal user) rather than an OpenSim
44 /// specific NPC extension?
43 /// </summary> 45 /// </summary>
44 bool SenseAsAgent { get; } 46 bool SenseAsAgent { get; }
45 } 47 }
@@ -53,35 +55,42 @@ namespace OpenSim.Region.Framework.Interfaces
53 /// <param name="lastname"></param> 55 /// <param name="lastname"></param>
54 /// <param name="position"></param> 56 /// <param name="position"></param>
55 /// <param name="senseAsAgent"> 57 /// <param name="senseAsAgent">
56 /// Make the NPC show up as an agent on LSL sensors. The default is that they 58 /// Make the NPC show up as an agent on LSL sensors. The default is
57 /// show up as the NPC type instead, but this is currently an OpenSim-only extension. 59 /// that they show up as the NPC type instead, but this is currently
60 /// an OpenSim-only extension.
58 /// </param> 61 /// </param>
59 /// <param name="scene"></param> 62 /// <param name="scene"></param>
60 /// <param name="appearance">The avatar appearance to use for the new NPC.</param> 63 /// <param name="appearance">
61 /// <returns>The UUID of the ScenePresence created. UUID.Zero if there was a failure.</returns> 64 /// The avatar appearance to use for the new NPC.
62 UUID CreateNPC( 65 /// </param>
63 string firstname, 66 /// <returns>
64 string lastname, 67 /// The UUID of the ScenePresence created. UUID.Zero if there was a
65 Vector3 position, 68 /// failure.
66 UUID owner, 69 /// </returns>
67 bool senseAsAgent, 70 UUID CreateNPC(string firstname, string lastname, Vector3 position,
68 Scene scene, 71 UUID owner, bool senseAsAgent, Scene scene,
69 AvatarAppearance appearance); 72 AvatarAppearance appearance);
70 73
71 /// <summary> 74 /// <summary>
72 /// Check if the agent is an NPC. 75 /// Check if the agent is an NPC.
73 /// </summary> 76 /// </summary>
74 /// <param name="agentID"></param> 77 /// <param name="agentID"></param>
75 /// <param name="scene"></param> 78 /// <param name="scene"></param>
76 /// <returns>True if the agent is an NPC in the given scene. False otherwise.</returns> 79 /// <returns>
80 /// True if the agent is an NPC in the given scene. False otherwise.
81 /// </returns>
77 bool IsNPC(UUID agentID, Scene scene); 82 bool IsNPC(UUID agentID, Scene scene);
78 83
79 /// <summary> 84 /// <summary>
80 /// Get the NPC. This is not currently complete - manipulation of NPCs still occurs through the region interface 85 /// Get the NPC.
81 /// </summary> 86 /// </summary>
87 /// <remarks>
88 /// This is not currently complete - manipulation of NPCs still occurs
89 /// through the region interface.
90 /// </remarks>
82 /// <param name="agentID"></param> 91 /// <param name="agentID"></param>
83 /// <param name="scene"></param> 92 /// <param name="scene"></param>
84 /// <returns>The NPC. null if it does not exist.</returns> 93 /// <returns>The NPC. null if it does not exist.</returns>
85 INPC GetNPC(UUID agentID, Scene scene); 94 INPC GetNPC(UUID agentID, Scene scene);
86 95
87 /// <summary> 96 /// <summary>
@@ -89,7 +98,10 @@ namespace OpenSim.Region.Framework.Interfaces
89 /// </summary> 98 /// </summary>
90 /// <param name="npcID"></param> 99 /// <param name="npcID"></param>
91 /// <param name="callerID"></param> 100 /// <param name="callerID"></param>
92 /// <returns>true if they do, false if they don't or if there's no NPC with the given ID.</returns> 101 /// <returns>
102 /// true if they do, false if they don't or if there's no NPC with the
103 /// given ID.
104 /// </returns>
93 bool CheckPermissions(UUID npcID, UUID callerID); 105 bool CheckPermissions(UUID npcID, UUID callerID);
94 106
95 /// <summary> 107 /// <summary>
@@ -98,8 +110,12 @@ namespace OpenSim.Region.Framework.Interfaces
98 /// <param name="agentID"></param> 110 /// <param name="agentID"></param>
99 /// <param name="appearance"></param> 111 /// <param name="appearance"></param>
100 /// <param name="scene"></param> 112 /// <param name="scene"></param>
101 /// <returns>True if the operation succeeded, false if there was no such agent or the agent was not an NPC</returns> 113 /// <returns>
102 bool SetNPCAppearance(UUID agentID, AvatarAppearance appearance, Scene scene); 114 /// True if the operation succeeded, false if there was no such agent
115 /// or the agent was not an NPC.
116 /// </returns>
117 bool SetNPCAppearance(UUID agentID, AvatarAppearance appearance,
118 Scene scene);
103 119
104 /// <summary> 120 /// <summary>
105 /// Move an NPC to a target over time. 121 /// Move an NPC to a target over time.
@@ -108,23 +124,29 @@ namespace OpenSim.Region.Framework.Interfaces
108 /// <param name="scene"></param> 124 /// <param name="scene"></param>
109 /// <param name="pos"></param> 125 /// <param name="pos"></param>
110 /// <param name="noFly"> 126 /// <param name="noFly">
111 /// If true, then the avatar will attempt to walk to the location even if it's up in the air. 127 /// If true, then the avatar will attempt to walk to the location even
112 /// This is to allow walking on prims. 128 /// if it's up in the air. This is to allow walking on prims.
113 /// </param> 129 /// </param>
114 /// <param name="landAtTarget"> 130 /// <param name="landAtTarget">
115 /// If true and the avatar is flying when it reaches the target, land. 131 /// If true and the avatar is flying when it reaches the target, land.
116 /// </param> name="running"> 132 /// </param> name="running">
117 /// If true, NPC moves with running speed. 133 /// If true, NPC moves with running speed.
118 /// <returns>True if the operation succeeded, false if there was no such agent or the agent was not an NPC</returns> 134 /// <returns>
119 /// 135 /// True if the operation succeeded, false if there was no such agent
120 bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, bool noFly, bool landAtTarget, bool running); 136 /// or the agent was not an NPC.
137 /// </returns>
138 bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, bool noFly,
139 bool landAtTarget, bool running);
121 140
122 /// <summary> 141 /// <summary>
123 /// Stop the NPC's current movement. 142 /// Stop the NPC's current movement.
124 /// </summary> 143 /// </summary>
125 /// <param name="agentID">The UUID of the NPC</param> 144 /// <param name="agentID">The UUID of the NPC</param>
126 /// <param name="scene"></param> 145 /// <param name="scene"></param>
127 /// <returns>True if the operation succeeded, false if there was no such agent or the agent was not an NPC</returns> 146 /// <returns>
147 /// True if the operation succeeded, false if there was no such agent
148 /// or the agent was not an NPC.
149 /// </returns>
128 bool StopMoveToTarget(UUID agentID, Scene scene); 150 bool StopMoveToTarget(UUID agentID, Scene scene);
129 151
130 /// <summary> 152 /// <summary>
@@ -133,7 +155,10 @@ namespace OpenSim.Region.Framework.Interfaces
133 /// <param name="agentID">The UUID of the NPC</param> 155 /// <param name="agentID">The UUID of the NPC</param>
134 /// <param name="scene"></param> 156 /// <param name="scene"></param>
135 /// <param name="text"></param> 157 /// <param name="text"></param>
136 /// <returns>True if the operation succeeded, false if there was no such agent or the agent was not an NPC</returns> 158 /// <returns>
159 /// True if the operation succeeded, false if there was no such agent
160 /// or the agent was not an NPC.
161 /// </returns>
137 bool Say(UUID agentID, Scene scene, string text); 162 bool Say(UUID agentID, Scene scene, string text);
138 163
139 /// <summary> 164 /// <summary>
@@ -143,7 +168,10 @@ namespace OpenSim.Region.Framework.Interfaces
143 /// <param name="scene"></param> 168 /// <param name="scene"></param>
144 /// <param name="text"></param> 169 /// <param name="text"></param>
145 /// <param name="channel"></param> 170 /// <param name="channel"></param>
146 /// <returns>True if the operation succeeded, false if there was no such agent or the agent was not an NPC</returns> 171 /// <returns>
172 /// True if the operation succeeded, false if there was no such agent
173 /// or the agent was not an NPC.
174 /// </returns>
147 bool Say(UUID agentID, Scene scene, string text, int channel); 175 bool Say(UUID agentID, Scene scene, string text, int channel);
148 176
149 /// <summary> 177 /// <summary>
@@ -153,7 +181,10 @@ namespace OpenSim.Region.Framework.Interfaces
153 /// <param name="scene"></param> 181 /// <param name="scene"></param>
154 /// <param name="text"></param> 182 /// <param name="text"></param>
155 /// <param name="channel"></param> 183 /// <param name="channel"></param>
156 /// <returns>True if the operation succeeded, false if there was no such agent or the agent was not an NPC</returns> 184 /// <returns>
185 /// True if the operation succeeded, false if there was no such agent
186 /// or the agent was not an NPC.
187 /// </returns>
157 bool Shout(UUID agentID, Scene scene, string text, int channel); 188 bool Shout(UUID agentID, Scene scene, string text, int channel);
158 189
159 /// <summary> 190 /// <summary>
@@ -163,7 +194,10 @@ namespace OpenSim.Region.Framework.Interfaces
163 /// <param name="scene"></param> 194 /// <param name="scene"></param>
164 /// <param name="text"></param> 195 /// <param name="text"></param>
165 /// <param name="channel"></param> 196 /// <param name="channel"></param>
166 /// <returns>True if the operation succeeded, false if there was no such agent or the agent was not an NPC</returns> 197 /// <returns>
198 /// True if the operation succeeded, false if there was no such agent
199 /// or the agent was not an NPC.
200 /// </returns>
167 bool Whisper(UUID agentID, Scene scene, string text, int channel); 201 bool Whisper(UUID agentID, Scene scene, string text, int channel);
168 202
169 /// <summary> 203 /// <summary>
@@ -188,7 +222,9 @@ namespace OpenSim.Region.Framework.Interfaces
188 /// </summary> 222 /// </summary>
189 /// <param name="agentID"></param> 223 /// <param name="agentID"></param>
190 /// <param name="partID"></param> 224 /// <param name="partID"></param>
191 /// <returns>true if the touch is actually attempted, false if not</returns> 225 /// <returns>
226 /// true if the touch is actually attempted, false if not.
227 /// </returns>
192 bool Touch(UUID agentID, UUID partID); 228 bool Touch(UUID agentID, UUID partID);
193 229
194 /// <summary> 230 /// <summary>
@@ -196,14 +232,20 @@ namespace OpenSim.Region.Framework.Interfaces
196 /// </summary> 232 /// </summary>
197 /// <param name="agentID">The UUID of the NPC</param> 233 /// <param name="agentID">The UUID of the NPC</param>
198 /// <param name="scene"></param> 234 /// <param name="scene"></param>
199 /// <returns>True if the operation succeeded, false if there was no such agent or the agent was not an NPC</returns> 235 /// <returns>
236 /// True if the operation succeeded, false if there was no such agent
237 /// or the agent was not an NPC.
238 /// </returns>
200 bool DeleteNPC(UUID agentID, Scene scene); 239 bool DeleteNPC(UUID agentID, Scene scene);
201 240
202 /// <summary> 241 /// <summary>
203 /// Get the owner of a NPC 242 /// Get the owner of a NPC
204 /// </summary> 243 /// </summary>
205 /// <param name="agentID">The UUID of the NPC</param> 244 /// <param name="agentID">The UUID of the NPC</param>
206 /// <returns>UUID of owner if the NPC exists, UUID.Zero if there was no such agent, the agent is unowned or the agent was not an NPC</returns> 245 /// <returns>
246 /// UUID of owner if the NPC exists, UUID.Zero if there was no such
247 /// agent, the agent is unowned or the agent was not an NPC.
248 /// </returns>
207 UUID GetOwner(UUID agentID); 249 UUID GetOwner(UUID agentID);
208 } 250 }
209} \ No newline at end of file 251}
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
index ed71a95..70ff954 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic;
30using OpenMetaverse; 31using OpenMetaverse;
31 32
32namespace OpenSim.Region.Framework.Interfaces 33namespace OpenSim.Region.Framework.Interfaces
@@ -46,9 +47,46 @@ namespace OpenSim.Region.Framework.Interfaces
46 /// </summary> 47 /// </summary>
47 event ScriptCommand OnScriptCommand; 48 event ScriptCommand OnScriptCommand;
48 49
50 /// <summary>
51 /// Register an instance method as a script call by method name
52 /// </summary>
53 /// <param name="target"></param>
54 /// <param name="method"></param>
49 void RegisterScriptInvocation(object target, string method); 55 void RegisterScriptInvocation(object target, string method);
56
57 /// <summary>
58 /// Register a static or instance method as a script call by method info
59 /// </summary>
60 /// <param name="target">If target is a Type object, will assume method is static.</param>
61 /// <param name="method"></param>
50 void RegisterScriptInvocation(object target, MethodInfo method); 62 void RegisterScriptInvocation(object target, MethodInfo method);
63
64 /// <summary>
65 /// Register one or more instance methods as script calls by method name
66 /// </summary>
67 /// <param name="target"></param>
68 /// <param name="methods"></param>
51 void RegisterScriptInvocation(object target, string[] methods); 69 void RegisterScriptInvocation(object target, string[] methods);
70
71 /// <summary>
72 /// Register one or more static methods as script calls by method name
73 /// </summary>
74 /// <param name="target"></param>
75 /// <param name="methods"></param>
76 void RegisterScriptInvocation(Type target, string[] methods);
77
78 /// <summary>
79 /// Automatically register script invocations by checking for methods
80 /// with <see cref="ScriptInvocationAttribute"/>. Should only check
81 /// public methods.
82 /// </summary>
83 /// <param name="target"></param>
84 void RegisterScriptInvocations(IRegionModuleBase target);
85
86 /// <summary>
87 /// Returns an array of all registered script calls
88 /// </summary>
89 /// <returns></returns>
52 Delegate[] GetScriptInvocationList(); 90 Delegate[] GetScriptInvocationList();
53 91
54 Delegate LookupScriptInvocation(string fname); 92 Delegate LookupScriptInvocation(string fname);
@@ -67,11 +105,44 @@ namespace OpenSim.Region.Framework.Interfaces
67 /// <param name="key"></param> 105 /// <param name="key"></param>
68 void DispatchReply(UUID scriptId, int code, string text, string key); 106 void DispatchReply(UUID scriptId, int code, string text, string key);
69 107
70 /// For constants 108 /// <summary>
109 /// Operation to for a region module to register a constant to be used
110 /// by the script engine
111 /// </summary>
112 /// <param name="cname">
113 /// The name of the constant. LSL convention is for constant names to
114 /// be uppercase.
115 /// </param>
116 /// <param name="value">
117 /// The value of the constant. Should be of a type that can be
118 /// converted to one of <see cref="OpenSim.Region.ScriptEngine.Shared.LSL_Types"/>
119 /// </param>
71 void RegisterConstant(string cname, object value); 120 void RegisterConstant(string cname, object value);
121
122 /// <summary>
123 /// Automatically register all constants on a region module by
124 /// checking for fields with <see cref="ScriptConstantAttribute"/>.
125 /// </summary>
126 /// <param name="target"></param>
127 void RegisterConstants(IRegionModuleBase target);
128
129 /// <summary>
130 /// Operation to check for a registered constant
131 /// </summary>
132 /// <param name="cname">Name of constant</param>
133 /// <returns>Value of constant or null if none found.</returns>
72 object LookupModConstant(string cname); 134 object LookupModConstant(string cname);
135 Dictionary<string, object> GetConstants();
73 136
74 // For use ONLY by the script API 137 // For use ONLY by the script API
75 void RaiseEvent(UUID script, string id, string module, string command, string key); 138 void RaiseEvent(UUID script, string id, string module, string command, string key);
76 } 139 }
140
141 [AttributeUsage(AttributeTargets.Method)]
142 public class ScriptInvocationAttribute : Attribute
143 { }
144
145 [AttributeUsage(AttributeTargets.Field)]
146 public class ScriptConstantAttribute : Attribute
147 { }
77} 148}
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
index 6117a80..68af492 100644
--- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
@@ -32,9 +32,96 @@ namespace OpenSim.Region.Framework.Interfaces
32{ 32{
33 public interface ISoundModule 33 public interface ISoundModule
34 { 34 {
35 void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius); 35 /// <summary>
36 36 /// Maximum distance between a sound source and a recipient.
37 /// </summary>
38 float MaxDistance { get; }
39
40 /// <summary>
41 /// Play a sound from an object.
42 /// </summary>
43 /// <param name="soundID">Sound asset ID</param>
44 /// <param name="ownerID">Sound source owner</param>
45 /// <param name="objectID">Sound source ID</param>
46 /// <param name="gain">Sound volume</param>
47 /// <param name="position">Sound source position</param>
48 /// <param name="flags">Sound flags</param>
49 /// <param name="radius">
50 /// Radius used to affect gain over distance.
51 /// </param>
52 void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID,
53 double gain, Vector3 position, byte flags, float radius);
54
55 /// <summary>
56 /// Trigger a sound in the scene.
57 /// </summary>
58 /// <param name="soundId">Sound asset ID</param>
59 /// <param name="ownerID">Sound source owner</param>
60 /// <param name="objectID">Sound source ID</param>
61 /// <param name="parentID">Sound source parent.</param>
62 /// <param name="gain">Sound volume</param>
63 /// <param name="position">Sound source position</param>
64 /// <param name="handle"></param>
65 /// <param name="radius">
66 /// Radius used to affect gain over distance.
67 /// </param>
37 void TriggerSound( 68 void TriggerSound(
38 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius); 69 UUID soundId, UUID ownerID, UUID objectID, UUID parentID,
70 double gain, Vector3 position, UInt64 handle, float radius);
71
72 /// <summary>
73 /// Stop sounds eminating from an object.
74 /// </summary>
75 /// <param name="objectID">Sound source ID</param>
76 void StopSound(UUID objectID);
77
78 /// <summary>
79 /// Preload sound to viewers within range.
80 /// </summary>
81 /// <param name="objectID">Sound source ID</param>
82 /// <param name="soundID">Sound asset ID</param>
83 /// <param name="radius">
84 /// Radius used to determine which viewers should preload the sound.
85 /// </param>
86 void PreloadSound(UUID objectID, UUID soundID, float radius);
87
88 /// <summary>
89 /// Loop specified sound at specified volume with specified radius,
90 /// optionally declaring object as new sync master.
91 /// </summary>
92 /// <param name="objectID">Sound source ID</param>
93 /// <param name="soundID">Sound asset ID</param>
94 /// <param name="gain">Sound volume</param>
95 /// <param name="radius">Sound radius</param>
96 /// <param name="isMaster">Set object to sync master if true</param>
97 void LoopSound(UUID objectID, UUID soundID, double gain,
98 double radius, bool isMaster);
99
100 /// <summary>
101 /// Trigger or play an attached sound in this part's inventory.
102 /// </summary>
103 /// <param name="objectID">Sound source ID</param>
104 /// <param name="sound">Sound asset ID</param>
105 /// <param name="volume">Sound volume</param>
106 /// <param name="triggered">Triggered or not.</param>
107 /// <param name="flags"></param>
108 /// <param name="radius">Sound radius</param>
109 /// <param name="useMaster">Play using sound master</param>
110 /// <param name="isMaster">Play as sound master</param>
111 void SendSound(UUID objectID, UUID sound, double volume,
112 bool triggered, byte flags, float radius, bool useMaster,
113 bool isMaster);
114
115 /// <summary>
116 /// Trigger a sound to be played to all agents within an axis-aligned
117 /// bounding box.
118 /// </summary>
119 /// <param name="objectID">Sound source ID</param>
120 /// <param name="sound">Sound asset ID</param>
121 /// <param name="volume">Sound volume</param>
122 /// <param name="min">AABB bottom south-west corner</param>
123 /// <param name="max">AABB top north-east corner</param>
124 void TriggerSoundLimited(UUID objectID, UUID sound, double volume,
125 Vector3 min, Vector3 max);
39 } 126 }
40} \ No newline at end of file 127} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/ISunModule.cs b/OpenSim/Region/Framework/Interfaces/ISunModule.cs
index 819ae11..8231716 100644
--- a/OpenSim/Region/Framework/Interfaces/ISunModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISunModule.cs
@@ -29,7 +29,7 @@ using OpenMetaverse;
29 29
30namespace OpenSim.Region.Framework.Interfaces 30namespace OpenSim.Region.Framework.Interfaces
31{ 31{
32 public interface ISunModule : IRegionModule 32 public interface ISunModule : INonSharedRegionModule
33 { 33 {
34 double GetSunParameter(string param); 34 double GetSunParameter(string param);
35 35
diff --git a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
index 457444c..79e9f9d 100644
--- a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
@@ -39,6 +39,8 @@ namespace OpenSim.Region.Framework.Interfaces
39 UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID); 39 UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID);
40 void ReleaseURL(string url); 40 void ReleaseURL(string url);
41 void HttpResponse(UUID request, int status, string body); 41 void HttpResponse(UUID request, int status, string body);
42 void HttpContentType(UUID request, string type);
43
42 string GetHttpHeader(UUID request, string header); 44 string GetHttpHeader(UUID request, string header);
43 int GetFreeUrls(); 45 int GetFreeUrls();
44 46
diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
index 24cd069..f8088c3 100644
--- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
+++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
@@ -1,4 +1,31 @@
1using System; 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
2using System.Collections.Generic; 29using System.Collections.Generic;
3 30
4using OpenMetaverse; 31using OpenMetaverse;
diff --git a/OpenSim/Region/Framework/Interfaces/IWindModule.cs b/OpenSim/Region/Framework/Interfaces/IWindModule.cs
index 10ecc32..4a26a71 100644
--- a/OpenSim/Region/Framework/Interfaces/IWindModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWindModule.cs
@@ -29,7 +29,7 @@ using OpenMetaverse;
29 29
30namespace OpenSim.Region.Framework.Interfaces 30namespace OpenSim.Region.Framework.Interfaces
31{ 31{
32 public interface IWindModule : IRegionModule 32 public interface IWindModule : INonSharedRegionModule
33 { 33 {
34 34
35 /// <summary> 35 /// <summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
index e8e375e..20e0199 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
@@ -45,6 +45,13 @@ namespace OpenSim.Region.Framework.Interfaces
45 void Deactivate(); 45 void Deactivate();
46 void Activate(); 46 void Activate();
47 UUID GetID(); 47 UUID GetID();
48
49 /// <summary>
50 /// Bitfield indicating which strings should be processed as regex.
51 /// 1 corresponds to IWorldCommListenerInfo::GetName()
52 /// 2 corresponds to IWorldCommListenerInfo::GetMessage()
53 /// </summary>
54 int RegexBitfield { get; }
48 } 55 }
49 56
50 public interface IWorldComm 57 public interface IWorldComm
@@ -60,7 +67,7 @@ namespace OpenSim.Region.Framework.Interfaces
60 /// the script during 'peek' time. Parameter hostID is needed to 67 /// the script during 'peek' time. Parameter hostID is needed to
61 /// determine the position of the script. 68 /// determine the position of the script.
62 /// </summary> 69 /// </summary>
63 /// <param name="localID">localID of the script engine</param> 70 /// <param name="LocalID">localID of the script engine</param>
64 /// <param name="itemID">UUID of the script engine</param> 71 /// <param name="itemID">UUID of the script engine</param>
65 /// <param name="hostID">UUID of the SceneObjectPart</param> 72 /// <param name="hostID">UUID of the SceneObjectPart</param>
66 /// <param name="channel">channel to listen on</param> 73 /// <param name="channel">channel to listen on</param>
@@ -70,6 +77,23 @@ namespace OpenSim.Region.Framework.Interfaces
70 /// <returns>number of the scripts handle</returns> 77 /// <returns>number of the scripts handle</returns>
71 int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg); 78 int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg);
72 79
80 /// <summary>
81 /// Create a listen event callback with the specified filters.
82 /// The parameters localID,itemID are needed to uniquely identify
83 /// the script during 'peek' time. Parameter hostID is needed to
84 /// determine the position of the script.
85 /// </summary>
86 /// <param name="LocalID">localID of the script engine</param>
87 /// <param name="itemID">UUID of the script engine</param>
88 /// <param name="hostID">UUID of the SceneObjectPart</param>
89 /// <param name="channel">channel to listen on</param>
90 /// <param name="name">name to filter on</param>
91 /// <param name="id">key to filter on (user given, could be totally faked)</param>
92 /// <param name="msg">msg to filter on</param>
93 /// <param name="regexBitfield">Bitfield indicating which strings should be processed as regex.</param>
94 /// <returns>number of the scripts handle</returns>
95 int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg, int regexBitfield);
96
73 /// <summary> 97 /// <summary>
74 /// This method scans over the objects which registered an interest in listen callbacks. 98 /// This method scans over the objects which registered an interest in listen callbacks.
75 /// For everyone it finds, it checks if it fits the given filter. If it does, then 99 /// For everyone it finds, it checks if it fits the given filter. If it does, then
diff --git a/OpenSim/Region/Framework/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs
deleted file mode 100644
index 32ee674..0000000
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ /dev/null
@@ -1,263 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes;
36
37namespace OpenSim.Region.Framework
38{
39 public class ModuleLoader
40 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42
43 public Dictionary<string, Assembly> LoadedAssemblys = new Dictionary<string, Assembly>();
44
45 private readonly List<IRegionModule> m_loadedModules = new List<IRegionModule>();
46 private readonly Dictionary<string, IRegionModule> m_loadedSharedModules = new Dictionary<string, IRegionModule>();
47 private readonly IConfigSource m_config;
48
49 public ModuleLoader(IConfigSource config)
50 {
51 m_config = config;
52 }
53
54 public IRegionModule[] GetLoadedSharedModules
55 {
56 get
57 {
58 IRegionModule[] regionModules = new IRegionModule[m_loadedSharedModules.Count];
59 m_loadedSharedModules.Values.CopyTo(regionModules, 0);
60 return regionModules;
61 }
62 }
63
64 public List<IRegionModule> PickupModules(Scene scene, string moduleDir)
65 {
66 DirectoryInfo dir = new DirectoryInfo(moduleDir);
67 List<IRegionModule> modules = new List<IRegionModule>();
68
69 foreach (FileInfo fileInfo in dir.GetFiles("*.dll"))
70 {
71 modules.AddRange(LoadRegionModules(fileInfo.FullName, scene));
72 }
73 return modules;
74 }
75
76 public void LoadDefaultSharedModule(IRegionModule module)
77 {
78 if (m_loadedSharedModules.ContainsKey(module.Name))
79 {
80 m_log.ErrorFormat("[MODULES]: Module name \"{0}\" already exists in module list. Module not added!", module.Name);
81 }
82 else
83 {
84 m_loadedSharedModules.Add(module.Name, module);
85 }
86 }
87
88
89 public void InitialiseSharedModules(Scene scene)
90 {
91 foreach (IRegionModule module in m_loadedSharedModules.Values)
92 {
93 module.Initialise(scene, m_config);
94 scene.AddModule(module.Name, module); //should be doing this?
95 }
96 }
97
98 public void InitializeModule(IRegionModule module, Scene scene)
99 {
100 module.Initialise(scene, m_config);
101 scene.AddModule(module.Name, module);
102 m_loadedModules.Add(module);
103 }
104
105 /// <summary>
106 /// Loads/initialises a Module instance that can be used by multiple Regions
107 /// </summary>
108 /// <param name="dllName"></param>
109 /// <param name="moduleName"></param>
110 public void LoadSharedModule(string dllName, string moduleName)
111 {
112 IRegionModule module = LoadModule(dllName, moduleName);
113
114 if (module != null)
115 LoadSharedModule(module);
116 }
117
118 /// <summary>
119 /// Loads/initialises a Module instance that can be used by multiple Regions
120 /// </summary>
121 /// <param name="module"></param>
122 public void LoadSharedModule(IRegionModule module)
123 {
124 if (!m_loadedSharedModules.ContainsKey(module.Name))
125 {
126 m_loadedSharedModules.Add(module.Name, module);
127 }
128 }
129
130 public List<IRegionModule> LoadRegionModules(string dllName, Scene scene)
131 {
132 IRegionModule[] modules = LoadModules(dllName);
133 List<IRegionModule> initializedModules = new List<IRegionModule>();
134
135 if (modules.Length > 0)
136 {
137 m_log.InfoFormat("[MODULES]: Found Module Library [{0}]", dllName);
138 foreach (IRegionModule module in modules)
139 {
140 if (!module.IsSharedModule)
141 {
142 m_log.InfoFormat("[MODULES]: [{0}]: Initializing.", module.Name);
143 InitializeModule(module, scene);
144 initializedModules.Add(module);
145 }
146 else
147 {
148 m_log.InfoFormat("[MODULES]: [{0}]: Loading Shared Module.", module.Name);
149 LoadSharedModule(module);
150 }
151 }
152 }
153 return initializedModules;
154 }
155
156 public void LoadRegionModule(string dllName, string moduleName, Scene scene)
157 {
158 IRegionModule module = LoadModule(dllName, moduleName);
159 if (module != null)
160 {
161 InitializeModule(module, scene);
162 }
163 }
164
165 /// <summary>
166 /// Loads a external Module (if not already loaded) and creates a new instance of it.
167 /// </summary>
168 /// <param name="dllName"></param>
169 /// <param name="moduleName"></param>
170 public IRegionModule LoadModule(string dllName, string moduleName)
171 {
172 IRegionModule[] modules = LoadModules(dllName);
173
174 foreach (IRegionModule module in modules)
175 {
176 if ((module != null) && (module.Name == moduleName))
177 {
178 return module;
179 }
180 }
181
182 return null;
183 }
184
185 public IRegionModule[] LoadModules(string dllName)
186 {
187 //m_log.DebugFormat("[MODULES]: Looking for modules in {0}", dllName);
188
189 List<IRegionModule> modules = new List<IRegionModule>();
190
191 Assembly pluginAssembly;
192 if (!LoadedAssemblys.TryGetValue(dllName, out pluginAssembly))
193 {
194 try
195 {
196 pluginAssembly = Assembly.LoadFrom(dllName);
197 LoadedAssemblys.Add(dllName, pluginAssembly);
198 }
199 catch (BadImageFormatException)
200 {
201 //m_log.InfoFormat("[MODULES]: The file [{0}] is not a module assembly.", e.FileName);
202 }
203 }
204
205 if (pluginAssembly != null)
206 {
207 try
208 {
209 foreach (Type pluginType in pluginAssembly.GetTypes())
210 {
211 if (pluginType.IsPublic)
212 {
213 if (!pluginType.IsAbstract)
214 {
215 if (pluginType.GetInterface("IRegionModule") != null)
216 {
217 modules.Add((IRegionModule)Activator.CreateInstance(pluginType));
218 }
219 }
220 }
221 }
222 }
223 catch (Exception e)
224 {
225 m_log.ErrorFormat(
226 "[MODULES]: Could not load types for plugin DLL {0}. Exception {1} {2}",
227 pluginAssembly.FullName, e.Message, e.StackTrace);
228
229 // justincc: Right now this is fatal to really get the user's attention
230 // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
231 //throw e;
232 }
233 }
234
235 return modules.ToArray();
236 }
237
238 public void PostInitialise()
239 {
240 foreach (IRegionModule module in m_loadedSharedModules.Values)
241 {
242 module.PostInitialise();
243 }
244
245 foreach (IRegionModule module in m_loadedModules)
246 {
247 module.PostInitialise();
248 }
249 }
250
251 public void ClearCache()
252 {
253 LoadedAssemblys.Clear();
254 }
255
256 public void UnloadModule(IRegionModule rm)
257 {
258 rm.Close();
259
260 m_loadedModules.Remove(rm);
261 }
262 }
263}
diff --git a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..9b504c0
--- /dev/null
+++ b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.Framework")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("d25e7aed-7f55-4bb8-9970-0d7d978ea8a5")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
index ad421ee..65ae445 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
@@ -41,6 +41,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
41 { 41 {
42// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 43
44 private OpenSim.Framework.Animation m_implicitDefaultAnimation = new OpenSim.Framework.Animation();
44 private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation(); 45 private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation();
45 private List<OpenSim.Framework.Animation> m_animations = new List<OpenSim.Framework.Animation>(); 46 private List<OpenSim.Framework.Animation> m_animations = new List<OpenSim.Framework.Animation>();
46 47
@@ -49,6 +50,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
49 get { return m_defaultAnimation; } 50 get { return m_defaultAnimation; }
50 } 51 }
51 52
53 public OpenSim.Framework.Animation ImplicitDefaultAnimation
54 {
55 get { return m_implicitDefaultAnimation; }
56 }
57
52 public AnimationSet() 58 public AnimationSet()
53 { 59 {
54 ResetDefaultAnimation(); 60 ResetDefaultAnimation();
@@ -119,11 +125,18 @@ namespace OpenSim.Region.Framework.Scenes.Animation
119 if (m_defaultAnimation.AnimID != animID) 125 if (m_defaultAnimation.AnimID != animID)
120 { 126 {
121 m_defaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID); 127 m_defaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID);
128 m_implicitDefaultAnimation = m_defaultAnimation;
122 return true; 129 return true;
123 } 130 }
124 return false; 131 return false;
125 } 132 }
126 133
134 // Called from serialization only
135 public void SetImplicitDefaultAnimation(UUID animID, int sequenceNum, UUID objectID)
136 {
137 m_implicitDefaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID);
138 }
139
127 protected bool ResetDefaultAnimation() 140 protected bool ResetDefaultAnimation()
128 { 141 {
129 return TrySetDefaultAnimation("STAND", 1, UUID.Zero); 142 return TrySetDefaultAnimation("STAND", 1, UUID.Zero);
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 7916c42..5b1c9f4 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -47,30 +47,75 @@ namespace OpenSim.Region.Framework.Scenes
47 47
48 public delegate void OnFrameDelegate(); 48 public delegate void OnFrameDelegate();
49 49
50 /// <summary>
51 /// Triggered on each sim frame.
52 /// </summary>
53 /// <remarks>
54 /// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.Update"/>
55 /// Core uses it for things like Sun, Wind & Clouds
56 /// The MRM module also uses it.
57 /// </remarks>
50 public event OnFrameDelegate OnFrame; 58 public event OnFrameDelegate OnFrame;
51 59
52 public delegate void ClientMovement(ScenePresence client); 60 public delegate void ClientMovement(ScenePresence client);
53 61
62 /// <summary>
63 /// Trigerred when an agent moves.
64 /// </summary>
65 /// <remarks>
66 /// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.ScenePresence.HandleAgentUpdate"/>
67 /// prior to <see cref="OpenSim.Region.Framework.Scenes.ScenePresence.TriggerScenePresenceUpdated"/>
68 /// </remarks>
54 public event ClientMovement OnClientMovement; 69 public event ClientMovement OnClientMovement;
55 70
56 public delegate void OnTerrainTaintedDelegate(); 71 public delegate void OnTerrainTaintedDelegate();
57 72
73 /// <summary>
74 /// Triggered if the terrain has been edited
75 /// </summary>
76 /// <remarks>
77 /// This gets triggered in <see cref="OpenSim.Region.CoreModules.World.Terrain.CheckForTerrainUpdates"/>
78 /// after it determines that an update has been made.
79 /// </remarks>
58 public event OnTerrainTaintedDelegate OnTerrainTainted; 80 public event OnTerrainTaintedDelegate OnTerrainTainted;
59 81
60 public delegate void OnTerrainTickDelegate(); 82 public delegate void OnTerrainTickDelegate();
61 83
62 public delegate void OnTerrainUpdateDelegate(); 84 /// <summary>
63 85 /// Triggered if the terrain has been edited
86 /// </summary>
87 /// <remarks>
88 /// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.UpdateTerrain"/>
89 /// but is used by core solely to update the physics engine.
90 /// </remarks>
64 public event OnTerrainTickDelegate OnTerrainTick; 91 public event OnTerrainTickDelegate OnTerrainTick;
65 92
93 public delegate void OnTerrainUpdateDelegate();
94
66 public event OnTerrainUpdateDelegate OnTerrainUpdate; 95 public event OnTerrainUpdateDelegate OnTerrainUpdate;
67 96
68 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 97 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
69 98
99 /// <summary>
100 /// Triggered when a region is backed up/persisted to storage
101 /// </summary>
102 /// <remarks>
103 /// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.Backup"/>
104 /// and is fired before the persistence occurs.
105 /// </remarks>
70 public event OnBackupDelegate OnBackup; 106 public event OnBackupDelegate OnBackup;
71 107
72 public delegate void OnClientConnectCoreDelegate(IClientCore client); 108 public delegate void OnClientConnectCoreDelegate(IClientCore client);
73 109
110 /// <summary>
111 /// Triggered when a new client connects to the scene.
112 /// </summary>
113 /// <remarks>
114 /// This gets triggered in <see cref="TriggerOnNewClient"/>,
115 /// which checks if an instance of <see cref="OpenSim.Framework.IClientAPI"/>
116 /// also implements <see cref="OpenSim.Framework.Client.IClientCore"/> and as such,
117 /// is not triggered by <see cref="OpenSim.Region.OptionalModules.World.NPC">NPCs</see>.
118 /// </remarks>
74 public event OnClientConnectCoreDelegate OnClientConnect; 119 public event OnClientConnectCoreDelegate OnClientConnect;
75 120
76 public delegate void OnNewClientDelegate(IClientAPI client); 121 public delegate void OnNewClientDelegate(IClientAPI client);
@@ -80,33 +125,96 @@ namespace OpenSim.Region.Framework.Scenes
80 /// </summary> 125 /// </summary>
81 /// <remarks> 126 /// <remarks>
82 /// This is triggered for both child and root agent client connections. 127 /// This is triggered for both child and root agent client connections.
128 ///
83 /// Triggered before OnClientLogin. 129 /// Triggered before OnClientLogin.
130 ///
131 /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please
132 /// do this on a separate thread.
84 /// </remarks> 133 /// </remarks>
85 public event OnNewClientDelegate OnNewClient; 134 public event OnNewClientDelegate OnNewClient;
86 135
87 /// <summary> 136 /// <summary>
88 /// Fired if the client entering this sim is doing so as a new login 137 /// Fired if the client entering this sim is doing so as a new login
89 /// </summary> 138 /// </summary>
139 /// <remarks>
140 /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please
141 /// do this on a separate thread.
142 /// </remarks>
90 public event Action<IClientAPI> OnClientLogin; 143 public event Action<IClientAPI> OnClientLogin;
91 144
92 public delegate void OnNewPresenceDelegate(ScenePresence presence); 145 public delegate void OnNewPresenceDelegate(ScenePresence presence);
93 146
147 /// <summary>
148 /// Triggered when a new presence is added to the scene
149 /// </summary>
150 /// <remarks>
151 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
152 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
153 /// </remarks>
94 public event OnNewPresenceDelegate OnNewPresence; 154 public event OnNewPresenceDelegate OnNewPresence;
95 155
96 public delegate void OnRemovePresenceDelegate(UUID agentId); 156 public delegate void OnRemovePresenceDelegate(UUID agentId);
97 157
158 /// <summary>
159 /// Triggered when a presence is removed from the scene
160 /// </summary>
161 /// <remarks>
162 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
163 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
164 ///
165 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please
166 /// do this on a separate thread.
167 /// </remarks>
98 public event OnRemovePresenceDelegate OnRemovePresence; 168 public event OnRemovePresenceDelegate OnRemovePresence;
99 169
100 public delegate void OnParcelPrimCountUpdateDelegate(); 170 public delegate void OnParcelPrimCountUpdateDelegate();
101 171
172 /// <summary>
173 /// Triggered whenever the prim count may have been altered, or prior
174 /// to an action that requires the current prim count to be accurate.
175 /// </summary>
176 /// <remarks>
177 /// Triggered by <see cref="TriggerParcelPrimCountUpdate"/> in
178 /// <see cref="OpenSim.OpenSimBase.CreateRegion"/>,
179 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.EventManagerOnRequestParcelPrimCountUpdate"/>,
180 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ClientOnParcelObjectOwnerRequest"/>,
181 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.GetPrimsFree"/>,
182 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.UpdateLandSold"/>,
183 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.DeedToGroup"/>,
184 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.SendLandUpdateToClient"/>
185 /// </remarks>
102 public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate; 186 public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate;
103 187
104 public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj); 188 public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj);
105 189
190 /// <summary>
191 /// Triggered in response to <see cref="OnParcelPrimCountUpdate"/> for
192 /// objects that actually contribute to parcel prim count.
193 /// </summary>
194 /// <remarks>
195 /// Triggered by <see cref="TriggerParcelPrimCountAdd"/> in
196 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.EventManagerOnParcelPrimCountUpdate"/>
197 /// </remarks>
106 public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd; 198 public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd;
107 199
108 public delegate void OnPluginConsoleDelegate(string[] args); 200 public delegate void OnPluginConsoleDelegate(string[] args);
109 201
202 /// <summary>
203 /// Triggered after <see cref="OpenSim.IApplicationPlugin.PostInitialise"/>
204 /// has been called for all <see cref="OpenSim.IApplicationPlugin"/>
205 /// loaded via <see cref="OpenSim.OpenSimBase.LoadPlugins"/>.
206 /// Handlers for this event are typically used to parse the arguments
207 /// from <see cref="OnPluginConsoleDelegate"/> in order to process or
208 /// filter the arguments and pass them onto <see cref="OpenSim.Region.CoreModules.Framework.InterfaceCommander.Commander.ProcessConsoleCommand"/>
209 /// </summary>
210 /// <remarks>
211 /// Triggered by <see cref="TriggerOnPluginConsole"/> in
212 /// <see cref="Scene.SendCommandToPlugins"/> via
213 /// <see cref="SceneManager.SendCommandToPluginModules"/> via
214 /// <see cref="OpenSim.OpenSimBase.HandleCommanderCommand"/> via
215 /// <see cref="OpenSim.OpenSimBase.AddPluginCommands"/> via
216 /// <see cref="OpenSim.OpenSimBase.StartupSpecific"/>
217 /// </remarks>
110 public event OnPluginConsoleDelegate OnPluginConsole; 218 public event OnPluginConsoleDelegate OnPluginConsole;
111 219
112 /// <summary> 220 /// <summary>
@@ -121,8 +229,28 @@ namespace OpenSim.Region.Framework.Scenes
121 229
122 public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene); 230 public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene);
123 231
232 /// <summary>
233 /// Triggered before the grunt work for adding a root agent to a
234 /// scene has been performed (resuming attachment scripts, physics,
235 /// animations etc.)
236 /// </summary>
237 /// <remarks>
238 /// Triggered before <see cref="OnMakeRootAgent"/>
239 /// by <see cref="TriggerSetRootAgentScene"/>
240 /// in <see cref="ScenePresence.MakeRootAgent"/>
241 /// via <see cref="Scene.AgentCrossing"/>
242 /// and <see cref="ScenePresence.CompleteMovement"/>
243 /// </remarks>
124 public event OnSetRootAgentSceneDelegate OnSetRootAgentScene; 244 public event OnSetRootAgentSceneDelegate OnSetRootAgentScene;
125 245
246 /// <summary>
247 /// Triggered after parcel properties have been updated.
248 /// </summary>
249 /// <remarks>
250 /// Triggered by <see cref="TriggerOnParcelPropertiesUpdateRequest"/> in
251 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ClientOnParcelPropertiesUpdateRequest"/>,
252 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ProcessPropertiesUpdate"/>
253 /// </remarks>
126 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; 254 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
127 255
128 /// <summary> 256 /// <summary>
@@ -137,13 +265,45 @@ namespace OpenSim.Region.Framework.Scenes
137 /// <summary> 265 /// <summary>
138 /// Fired when an object is touched/grabbed. 266 /// Fired when an object is touched/grabbed.
139 /// </summary> 267 /// </summary>
268 /// <remarks>
140 /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of 269 /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of
141 /// the root part. 270 /// the root part.
271 /// Triggerd in response to <see cref="OpenSim.Framework.IClientAPI.OnGrabObject"/>
272 /// via <see cref="TriggerObjectGrab"/>
273 /// in <see cref="Scene.ProcessObjectGrab"/>
274 /// </remarks>
142 public event ObjectGrabDelegate OnObjectGrab; 275 public event ObjectGrabDelegate OnObjectGrab;
143 public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); 276 public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs);
144 277
278 /// <summary>
279 /// Triggered when an object is being touched/grabbed continuously.
280 /// </summary>
281 /// <remarks>
282 /// Triggered in response to <see cref="OpenSim.Framework.IClientAPI.OnGrabUpdate"/>
283 /// via <see cref="TriggerObjectGrabbing"/>
284 /// in <see cref="Scene.ProcessObjectGrabUpdate"/>
285 /// </remarks>
145 public event ObjectGrabDelegate OnObjectGrabbing; 286 public event ObjectGrabDelegate OnObjectGrabbing;
287
288 /// <summary>
289 /// Triggered when an object stops being touched/grabbed.
290 /// </summary>
291 /// <remarks>
292 /// Triggered in response to <see cref="OpenSim.Framework.IClientAPI.OnDeGrabObject"/>
293 /// via <see cref="TriggerObjectDeGrab"/>
294 /// in <see cref="Scene.ProcessObjectDeGrab"/>
295 /// </remarks>
146 public event ObjectDeGrabDelegate OnObjectDeGrab; 296 public event ObjectDeGrabDelegate OnObjectDeGrab;
297
298 /// <summary>
299 /// Triggered when a script resets.
300 /// </summary>
301 /// <remarks>
302 /// Triggered by <see cref="TriggerScriptReset"/>
303 /// in <see cref="Scene.ProcessScriptReset"/>
304 /// via <see cref="OpenSim.Framework.IClientAPI.OnScriptReset"/>
305 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleScriptReset"/>
306 /// </remarks>
147 public event ScriptResetDelegate OnScriptReset; 307 public event ScriptResetDelegate OnScriptReset;
148 308
149 public event OnPermissionErrorDelegate OnPermissionError; 309 public event OnPermissionErrorDelegate OnPermissionError;
@@ -153,29 +313,105 @@ namespace OpenSim.Region.Framework.Scenes
153 /// </summary> 313 /// </summary>
154 /// <remarks> 314 /// <remarks>
155 /// Occurs after OnNewScript. 315 /// Occurs after OnNewScript.
316 /// Triggered by <see cref="TriggerRezScript"/>
317 /// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>
156 /// </remarks> 318 /// </remarks>
157 public event NewRezScript OnRezScript; 319 public event NewRezScript OnRezScript;
158 public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource); 320 public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource);
159 321
160 public delegate void RemoveScript(uint localID, UUID itemID); 322 public delegate void RemoveScript(uint localID, UUID itemID);
323
324 /// <summary>
325 /// Triggered when a script is removed from an object.
326 /// </summary>
327 /// <remarks>
328 /// Triggered by <see cref="TriggerRemoveScript"/>
329 /// in <see cref="Scene.RemoveTaskInventory"/>,
330 /// <see cref="Scene.CreateAgentInventoryItemFromTask"/>,
331 /// <see cref="SceneObjectPartInventory.RemoveScriptInstance"/>,
332 /// <see cref="SceneObjectPartInventory.RemoveInventoryItem"/>
333 /// </remarks>
161 public event RemoveScript OnRemoveScript; 334 public event RemoveScript OnRemoveScript;
162 335
163 public delegate void StartScript(uint localID, UUID itemID); 336 public delegate void StartScript(uint localID, UUID itemID);
337
338 /// <summary>
339 /// Triggered when a script starts.
340 /// </summary>
341 /// <remarks>
342 /// Triggered by <see cref="TriggerStartScript"/>
343 /// in <see cref="Scene.SetScriptRunning"/>
344 /// via <see cref="OpenSim.Framework.IClientAPI.OnSetScriptRunning"/>,
345 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.HandleSetScriptRunning"/>
346 /// </remarks>
164 public event StartScript OnStartScript; 347 public event StartScript OnStartScript;
165 348
166 public delegate void StopScript(uint localID, UUID itemID); 349 public delegate void StopScript(uint localID, UUID itemID);
350
351 /// <summary>
352 /// Triggered when a script stops.
353 /// </summary>
354 /// <remarks>
355 /// Triggered by <see cref="TriggerStopScript"/>,
356 /// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>,
357 /// <see cref="SceneObjectPartInventory.StopScriptInstance"/>,
358 /// <see cref="Scene.SetScriptRunning"/>
359 /// </remarks>
167 public event StopScript OnStopScript; 360 public event StopScript OnStopScript;
168 361
169 public delegate bool SceneGroupMoved(UUID groupID, Vector3 delta); 362 public delegate bool SceneGroupMoved(UUID groupID, Vector3 delta);
363
364 /// <summary>
365 /// Triggered when an object is moved.
366 /// </summary>
367 /// <remarks>
368 /// Triggered by <see cref="TriggerGroupMove"/>
369 /// in <see cref="SceneObjectGroup.UpdateGroupPosition"/>,
370 /// <see cref="SceneObjectGroup.GrabMovement"/>
371 /// </remarks>
170 public event SceneGroupMoved OnSceneGroupMove; 372 public event SceneGroupMoved OnSceneGroupMove;
171 373
172 public delegate void SceneGroupGrabed(UUID groupID, Vector3 offset, UUID userID); 374 public delegate void SceneGroupGrabed(UUID groupID, Vector3 offset, UUID userID);
375
376 /// <summary>
377 /// Triggered when an object is grabbed.
378 /// </summary>
379 /// <remarks>
380 /// Triggered by <see cref="TriggerGroupGrab"/>
381 /// in <see cref="SceneObjectGroup.OnGrabGroup"/>
382 /// via <see cref="SceneObjectGroup.ObjectGrabHandler"/>
383 /// via <see cref="Scene.ProcessObjectGrab"/>
384 /// via <see cref="OpenSim.Framework.IClientAPI.OnGrabObject"/>
385 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleObjectGrab"/>
386 /// </remarks>
173 public event SceneGroupGrabed OnSceneGroupGrab; 387 public event SceneGroupGrabed OnSceneGroupGrab;
174 388
175 public delegate bool SceneGroupSpinStarted(UUID groupID); 389 public delegate bool SceneGroupSpinStarted(UUID groupID);
390
391 /// <summary>
392 /// Triggered when an object starts to spin.
393 /// </summary>
394 /// <remarks>
395 /// Triggered by <see cref="TriggerGroupSpinStart"/>
396 /// in <see cref="SceneObjectGroup.SpinStart"/>
397 /// via <see cref="SceneGraph.SpinStart"/>
398 /// via <see cref="OpenSim.Framework.IClientAPI.OnSpinStart"/>
399 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleObjectSpinStart"/>
400 /// </remarks>
176 public event SceneGroupSpinStarted OnSceneGroupSpinStart; 401 public event SceneGroupSpinStarted OnSceneGroupSpinStart;
177 402
178 public delegate bool SceneGroupSpun(UUID groupID, Quaternion rotation); 403 public delegate bool SceneGroupSpun(UUID groupID, Quaternion rotation);
404
405 /// <summary>
406 /// Triggered when an object is being spun.
407 /// </summary>
408 /// <remarks>
409 /// Triggered by <see cref="TriggerGroupSpin"/>
410 /// in <see cref="SceneObjectGroup.SpinMovement"/>
411 /// via <see cref="SceneGraph.SpinObject"/>
412 /// via <see cref="OpenSim.Framework.IClientAPI.OnSpinUpdate"/>
413 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleObjectSpinUpdate"/>
414 /// </remarks>
179 public event SceneGroupSpun OnSceneGroupSpin; 415 public event SceneGroupSpun OnSceneGroupSpin;
180 416
181 public delegate void LandObjectAdded(ILandObject newParcel); 417 public delegate void LandObjectAdded(ILandObject newParcel);
@@ -204,6 +440,9 @@ namespace OpenSim.Region.Framework.Scenes
204 /// </summary> 440 /// </summary>
205 /// <remarks> 441 /// <remarks>
206 /// At the point of firing, the scene still contains the client's scene presence. 442 /// At the point of firing, the scene still contains the client's scene presence.
443 ///
444 /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please
445 /// do this on a separate thread.
207 /// </remarks> 446 /// </remarks>
208 public event ClientClosed OnClientClosed; 447 public event ClientClosed OnClientClosed;
209 448
@@ -214,6 +453,9 @@ namespace OpenSim.Region.Framework.Scenes
214 /// </summary> 453 /// </summary>
215 /// <remarks> 454 /// <remarks>
216 /// Occurs before OnRezScript 455 /// Occurs before OnRezScript
456 /// Triggered by <see cref="TriggerNewScript"/>
457 /// in <see cref="Scene.RezScriptFromAgentInventory"/>,
458 /// <see cref="Scene.RezNewScript"/>
217 /// </remarks> 459 /// </remarks>
218 public event NewScript OnNewScript; 460 public event NewScript OnNewScript;
219 461
@@ -248,6 +490,12 @@ namespace OpenSim.Region.Framework.Scenes
248 /// </summary> 490 /// </summary>
249 /// <remarks> 491 /// <remarks>
250 /// Triggered after the scene receives a client's upload of an updated script and has stored it in an asset. 492 /// Triggered after the scene receives a client's upload of an updated script and has stored it in an asset.
493 /// Triggered by <see cref="TriggerUpdateScript"/>
494 /// in <see cref="Scene.CapsUpdateTaskInventoryScriptAsset"/>
495 /// via <see cref="Scene.CapsUpdateTaskInventoryScriptAsset"/>
496 /// via <see cref="OpenSim.Region.ClientStack.Linden.BunchOfCaps.TaskScriptUpdated"/>
497 /// via <see cref="OpenSim.Region.ClientStack.Linden.TaskInventoryScriptUpdater.OnUpLoad"/>
498 /// via <see cref="OpenSim.Region.ClientStack.Linden.TaskInventoryScriptUpdater.uploaderCaps"/>
251 /// </remarks> 499 /// </remarks>
252 public event UpdateScript OnUpdateScript; 500 public event UpdateScript OnUpdateScript;
253 501
@@ -273,48 +521,203 @@ namespace OpenSim.Region.Framework.Scenes
273 } 521 }
274 522
275 /// <summary> 523 /// <summary>
524 /// Triggered when some scene object properties change.
525 /// </summary>
526 /// <remarks>
276 /// ScriptChangedEvent is fired when a scene object property that a script might be interested 527 /// ScriptChangedEvent is fired when a scene object property that a script might be interested
277 /// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event. 528 /// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event.
278 /// This is not an indication that the script has changed (see OnUpdateScript for that). 529 /// This is not an indication that the script has changed (see OnUpdateScript for that).
279 /// This event is sent to a script to tell it that some property changed on 530 /// This event is sent to a script to tell it that some property changed on
280 /// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed . 531 /// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed .
281 /// </summary> 532 /// Triggered by <see cref="TriggerOnScriptChangedEvent"/>
533 /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.TeleportAgentWithinRegion"/>,
534 /// <see cref="SceneObjectPart.TriggerScriptChangedEvent"/>
535 /// </remarks>
282 public event ScriptChangedEvent OnScriptChangedEvent; 536 public event ScriptChangedEvent OnScriptChangedEvent;
283 public delegate void ScriptChangedEvent(uint localID, uint change); 537 public delegate void ScriptChangedEvent(uint localID, uint change);
284 538
285 public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed); 539 public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed);
540
541 /// <summary>
542 /// Triggered when a script receives control input from an agent.
543 /// </summary>
544 /// <remarks>
545 /// Triggered by <see cref="TriggerControlEvent"/>
546 /// in <see cref="ScenePresence.SendControlsToScripts"/>
547 /// via <see cref="ScenePresence.HandleAgentUpdate"/>
548 /// via <see cref="OpenSim.Framework.IClientAPI.OnAgentUpdate"/>
549 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleAgentUpdate"/>
550 /// </remarks>
286 public event ScriptControlEvent OnScriptControlEvent; 551 public event ScriptControlEvent OnScriptControlEvent;
287 552
288 public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos); 553 public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos);
554
555 /// <summary>
556 /// Triggered when an object has arrived within a tolerance distance
557 /// of a motion target.
558 /// </summary>
559 /// <remarks>
560 /// Triggered by <see cref="TriggerAtTargetEvent"/>
561 /// in <see cref="SceneObjectGroup.checkAtTargets"/>
562 /// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>,
563 /// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/>
564 /// </remarks>
289 public event ScriptAtTargetEvent OnScriptAtTargetEvent; 565 public event ScriptAtTargetEvent OnScriptAtTargetEvent;
290 566
291 public delegate void ScriptNotAtTargetEvent(uint localID); 567 public delegate void ScriptNotAtTargetEvent(uint localID);
568
569 /// <summary>
570 /// Triggered when an object has a motion target but has not arrived
571 /// within a tolerance distance.
572 /// </summary>
573 /// <remarks>
574 /// Triggered by <see cref="TriggerNotAtTargetEvent"/>
575 /// in <see cref="SceneObjectGroup.checkAtTargets"/>
576 /// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>,
577 /// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/>
578 /// </remarks>
292 public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent; 579 public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent;
293 580
294 public delegate void ScriptAtRotTargetEvent(uint localID, uint handle, Quaternion targetrot, Quaternion atrot); 581 public delegate void ScriptAtRotTargetEvent(uint localID, uint handle, Quaternion targetrot, Quaternion atrot);
582
583 /// <summary>
584 /// Triggered when an object has arrived within a tolerance rotation
585 /// of a rotation target.
586 /// </summary>
587 /// <remarks>
588 /// Triggered by <see cref="TriggerAtRotTargetEvent"/>
589 /// in <see cref="SceneObjectGroup.checkAtTargets"/>
590 /// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>,
591 /// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/>
592 /// </remarks>
295 public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent; 593 public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent;
296 594
297 public delegate void ScriptNotAtRotTargetEvent(uint localID); 595 public delegate void ScriptNotAtRotTargetEvent(uint localID);
596
597 /// <summary>
598 /// Triggered when an object has a rotation target but has not arrived
599 /// within a tolerance rotation.
600 /// </summary>
601 /// <remarks>
602 /// Triggered by <see cref="TriggerNotAtRotTargetEvent"/>
603 /// in <see cref="SceneObjectGroup.checkAtTargets"/>
604 /// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>,
605 /// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/>
606 /// </remarks>
298 public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent; 607 public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent;
299 608
300 public delegate void ScriptColliding(uint localID, ColliderArgs colliders); 609 public delegate void ScriptColliding(uint localID, ColliderArgs colliders);
610
611 /// <summary>
612 /// Triggered when a physical collision has started between a prim
613 /// and something other than the region terrain.
614 /// </summary>
615 /// <remarks>
616 /// Triggered by <see cref="TriggerScriptCollidingStart"/>
617 /// in <see cref="SceneObjectPart.SendCollisionEvent"/>
618 /// via <see cref="SceneObjectPart.PhysicsCollision"/>
619 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
620 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
621 /// </remarks>
301 public event ScriptColliding OnScriptColliderStart; 622 public event ScriptColliding OnScriptColliderStart;
623
624 /// <summary>
625 /// Triggered when something that previously collided with a prim has
626 /// not stopped colliding with it.
627 /// </summary>
628 /// <remarks>
629 /// <seealso cref="OnScriptColliderStart"/>
630 /// Triggered by <see cref="TriggerScriptColliding"/>
631 /// in <see cref="SceneObjectPart.SendCollisionEvent"/>
632 /// via <see cref="SceneObjectPart.PhysicsCollision"/>
633 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
634 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
635 /// </remarks>
302 public event ScriptColliding OnScriptColliding; 636 public event ScriptColliding OnScriptColliding;
637
638 /// <summary>
639 /// Triggered when something that previously collided with a prim has
640 /// stopped colliding with it.
641 /// </summary>
642 /// <remarks>
643 /// Triggered by <see cref="TriggerScriptCollidingEnd"/>
644 /// in <see cref="SceneObjectPart.SendCollisionEvent"/>
645 /// via <see cref="SceneObjectPart.PhysicsCollision"/>
646 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
647 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
648 /// </remarks>
303 public event ScriptColliding OnScriptCollidingEnd; 649 public event ScriptColliding OnScriptCollidingEnd;
650
651 /// <summary>
652 /// Triggered when a physical collision has started between an object
653 /// and the region terrain.
654 /// </summary>
655 /// <remarks>
656 /// Triggered by <see cref="TriggerScriptLandCollidingStart"/>
657 /// in <see cref="SceneObjectPart.SendLandCollisionEvent"/>
658 /// via <see cref="SceneObjectPart.PhysicsCollision"/>
659 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
660 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
661 /// </remarks>
304 public event ScriptColliding OnScriptLandColliderStart; 662 public event ScriptColliding OnScriptLandColliderStart;
663
664 /// <summary>
665 /// Triggered when an object that previously collided with the region
666 /// terrain has not yet stopped colliding with it.
667 /// </summary>
668 /// <remarks>
669 /// Triggered by <see cref="TriggerScriptLandColliding"/>
670 /// in <see cref="SceneObjectPart.SendLandCollisionEvent"/>
671 /// via <see cref="SceneObjectPart.PhysicsCollision"/>
672 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
673 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
674 /// </remarks>
305 public event ScriptColliding OnScriptLandColliding; 675 public event ScriptColliding OnScriptLandColliding;
676
677 /// <summary>
678 /// Triggered when an object that previously collided with the region
679 /// terrain has stopped colliding with it.
680 /// </summary>
681 /// <remarks>
682 /// Triggered by <see cref="TriggerScriptLandCollidingEnd"/>
683 /// in <see cref="SceneObjectPart.SendLandCollisionEvent"/>
684 /// via <see cref="SceneObjectPart.PhysicsCollision"/>
685 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
686 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
687 /// </remarks>
306 public event ScriptColliding OnScriptLandColliderEnd; 688 public event ScriptColliding OnScriptLandColliderEnd;
307 689
308 public delegate void OnMakeChildAgentDelegate(ScenePresence presence); 690 public delegate void OnMakeChildAgentDelegate(ScenePresence presence);
691
692 /// <summary>
693 /// Triggered when an agent has been made a child agent of a scene.
694 /// </summary>
695 /// <remarks>
696 /// Triggered by <see cref="TriggerOnMakeChildAgent"/>
697 /// in <see cref="ScenePresence.MakeChildAgent"/>
698 /// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.CrossAgentToNewRegionAsync"/>,
699 /// <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>,
700 /// <see cref="OpenSim.Region.CoreModules.InterGrid.KillAUser.ShutdownNoLogout"/>
701 /// </remarks>
309 public event OnMakeChildAgentDelegate OnMakeChildAgent; 702 public event OnMakeChildAgentDelegate OnMakeChildAgent;
310 703
311 public delegate void OnSaveNewWindlightProfileDelegate(); 704 public delegate void OnSaveNewWindlightProfileDelegate();
312 public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user); 705 public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user);
313 706
314 /// <summary> 707 /// <summary>
708 /// Triggered after the grunt work for adding a root agent to a
709 /// scene has been performed (resuming attachment scripts, physics,
710 /// animations etc.)
711 /// </summary>
712 /// <remarks>
315 /// This event is on the critical path for transferring an avatar from one region to another. Try and do 713 /// This event is on the critical path for transferring an avatar from one region to another. Try and do
316 /// as little work on this event as possible, or do work asynchronously. 714 /// as little work on this event as possible, or do work asynchronously.
317 /// </summary> 715 /// Triggered after <see cref="OnSetRootAgentScene"/>
716 /// by <see cref="TriggerOnMakeRootAgent"/>
717 /// in <see cref="ScenePresence.MakeRootAgent"/>
718 /// via <see cref="Scene.AgentCrossing"/>
719 /// and <see cref="ScenePresence.CompleteMovement"/>
720 /// </remarks>
318 public event Action<ScenePresence> OnMakeRootAgent; 721 public event Action<ScenePresence> OnMakeRootAgent;
319 722
320 public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted; 723 public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted;
@@ -340,9 +743,17 @@ namespace OpenSim.Region.Framework.Scenes
340 public event AvatarKillData OnAvatarKilled; 743 public event AvatarKillData OnAvatarKilled;
341 public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar); 744 public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar);
342 745
343// public delegate void ScriptTimerEvent(uint localID, double timerinterval); 746 /*
344 747 public delegate void ScriptTimerEvent(uint localID, double timerinterval);
345// public event ScriptTimerEvent OnScriptTimerEvent; 748 /// <summary>
749 /// Used to be triggered when the LSL timer event fires.
750 /// </summary>
751 /// <remarks>
752 /// Triggered by <see cref="TriggerTimerEvent"/>
753 /// via <see cref="SceneObjectPart.handleTimerAccounting"/>
754 /// </remarks>
755 public event ScriptTimerEvent OnScriptTimerEvent;
756 */
346 757
347 public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour); 758 public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour);
348 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); 759 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID);
@@ -352,12 +763,27 @@ namespace OpenSim.Region.Framework.Scenes
352 /// <summary> 763 /// <summary>
353 /// Triggered when an object is added to the scene. 764 /// Triggered when an object is added to the scene.
354 /// </summary> 765 /// </summary>
766 /// <remarks>
767 /// Triggered by <see cref="TriggerObjectAddedToScene"/>
768 /// in <see cref="Scene.AddNewSceneObject"/>,
769 /// <see cref="Scene.DuplicateObject"/>,
770 /// <see cref="Scene.doObjectDuplicateOnRay"/>
771 /// </remarks>
355 public event Action<SceneObjectGroup> OnObjectAddedToScene; 772 public event Action<SceneObjectGroup> OnObjectAddedToScene;
356 773
357 /// <summary> 774 /// <summary>
358 /// Triggered when an object is removed from the scene. 775 /// Delegate for <see cref="OnObjectBeingRemovedFromScene"/>
359 /// </summary> 776 /// </summary>
777 /// <param name="obj">The object being removed from the scene</param>
360 public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); 778 public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
779
780 /// <summary>
781 /// Triggered when an object is removed from the scene.
782 /// </summary>
783 /// <remarks>
784 /// Triggered by <see cref="TriggerObjectBeingRemovedFromScene"/>
785 /// in <see cref="Scene.DeleteSceneObject"/>
786 /// </remarks>
361 public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene; 787 public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene;
362 788
363 public delegate void NoticeNoLandDataFromStorage(); 789 public delegate void NoticeNoLandDataFromStorage();
@@ -373,9 +799,27 @@ namespace OpenSim.Region.Framework.Scenes
373 public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate; 799 public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate;
374 800
375 public delegate void ParcelPrimCountTainted(); 801 public delegate void ParcelPrimCountTainted();
802
803 /// <summary>
804 /// Triggered when the parcel prim count has been altered.
805 /// </summary>
806 /// <remarks>
807 /// Triggered by <see cref="TriggerParcelPrimCountTainted"/> in
808 /// <see cref="OpenSim.Region.CoreModules.Avatar.Attachments.AttachmentsModule.DetachSingleAttachmentToGround"/>,
809 /// <see cref="OpenSim.Region.CoreModules.Avatar.Attachments.AttachmentsModule.AttachToAgent"/>,
810 /// <see cref="Scene.DeleteSceneObject"/>,
811 /// <see cref="Scene.SelectPrim"/>,
812 /// <see cref="Scene.DeselectPrim"/>,
813 /// <see cref="SceneObjectGroup.UpdatePrimFlags"/>,
814 /// <see cref="SceneObjectGroup.AbsolutePosition"/>
815 /// </remarks>
376 public event ParcelPrimCountTainted OnParcelPrimCountTainted; 816 public event ParcelPrimCountTainted OnParcelPrimCountTainted;
377 public event GetScriptRunning OnGetScriptRunning; 817 public event GetScriptRunning OnGetScriptRunning;
378 818
819 public delegate void ThrottleUpdate(ScenePresence scenePresence);
820
821 public event ThrottleUpdate OnThrottleUpdate;
822
379 /// <summary> 823 /// <summary>
380 /// RegisterCapsEvent is called by Scene after the Caps object 824 /// RegisterCapsEvent is called by Scene after the Caps object
381 /// has been instantiated and before it is return to the 825 /// has been instantiated and before it is return to the
@@ -432,7 +876,7 @@ namespace OpenSim.Region.Framework.Scenes
432 /// the scripts may not have started yet 876 /// the scripts may not have started yet
433 /// Message is non empty string if there were problems loading the oar file 877 /// Message is non empty string if there were problems loading the oar file
434 /// </summary> 878 /// </summary>
435 public delegate void OarFileLoaded(Guid guid, string message); 879 public delegate void OarFileLoaded(Guid guid, List<UUID> loadedScenes, string message);
436 public event OarFileLoaded OnOarFileLoaded; 880 public event OarFileLoaded OnOarFileLoaded;
437 881
438 /// <summary> 882 /// <summary>
@@ -485,10 +929,13 @@ namespace OpenSim.Region.Framework.Scenes
485 /// <param name="copy"></param> 929 /// <param name="copy"></param>
486 /// <param name="original"></param> 930 /// <param name="original"></param>
487 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> 931 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
932 /// <remarks>
933 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.SceneObjectPart.Copy"/>
934 /// </remarks>
488 public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy; 935 public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy;
489 public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed); 936 public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed);
490 937
491 public delegate void SceneObjectPartUpdated(SceneObjectPart sop); 938 public delegate void SceneObjectPartUpdated(SceneObjectPart sop, bool full);
492 public event SceneObjectPartUpdated OnSceneObjectPartUpdated; 939 public event SceneObjectPartUpdated OnSceneObjectPartUpdated;
493 940
494 public delegate void ScenePresenceUpdated(ScenePresence sp); 941 public delegate void ScenePresenceUpdated(ScenePresence sp);
@@ -526,9 +973,28 @@ namespace OpenSim.Region.Framework.Scenes
526 public event PrimsLoaded OnPrimsLoaded; 973 public event PrimsLoaded OnPrimsLoaded;
527 974
528 public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout); 975 public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout);
976
977 /// <summary>
978 /// Triggered when a teleport starts
979 /// </summary>
980 /// <remarks>
981 /// Triggered by <see cref="TriggerTeleportStart"/>
982 /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.CreateAgent"/>
983 /// and <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.HGEntityTransferModule.CreateAgent"/>
984 /// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>
985 /// </remarks>
529 public event TeleportStart OnTeleportStart; 986 public event TeleportStart OnTeleportStart;
530 987
531 public delegate void TeleportFail(IClientAPI client, bool gridLogout); 988 public delegate void TeleportFail(IClientAPI client, bool gridLogout);
989
990 /// <summary>
991 /// Trigered when a teleport fails.
992 /// </summary>
993 /// <remarks>
994 /// Triggered by <see cref="TriggerTeleportFail"/>
995 /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.Fail"/>
996 /// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>
997 /// </remarks>
532 public event TeleportFail OnTeleportFail; 998 public event TeleportFail OnTeleportFail;
533 999
534 public class MoneyTransferArgs : EventArgs 1000 public class MoneyTransferArgs : EventArgs
@@ -536,7 +1002,9 @@ namespace OpenSim.Region.Framework.Scenes
536 public UUID sender; 1002 public UUID sender;
537 public UUID receiver; 1003 public UUID receiver;
538 1004
539 // Always false. The SL protocol sucks. 1005 /// <summary>
1006 /// Always false. The SL protocol sucks.
1007 /// </summary>
540 public bool authenticated = false; 1008 public bool authenticated = false;
541 1009
542 public int amount; 1010 public int amount;
@@ -593,8 +1061,29 @@ namespace OpenSim.Region.Framework.Scenes
593 1061
594 public delegate void LandBuy(Object sender, LandBuyArgs e); 1062 public delegate void LandBuy(Object sender, LandBuyArgs e);
595 1063
1064 /// <summary>
1065 /// Triggered when an attempt to transfer grid currency occurs
1066 /// </summary>
1067 /// <remarks>
1068 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/>
1069 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/>
1070 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/>
1071 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/>
1072 /// </remarks>
596 public event MoneyTransferEvent OnMoneyTransfer; 1073 public event MoneyTransferEvent OnMoneyTransfer;
1074
1075 /// <summary>
1076 /// Triggered after after <see cref="OnValidateLandBuy"/>
1077 /// </summary>
597 public event LandBuy OnLandBuy; 1078 public event LandBuy OnLandBuy;
1079
1080 /// <summary>
1081 /// Triggered to allow or prevent a real estate transaction
1082 /// </summary>
1083 /// <remarks>
1084 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessParcelBuy"/>
1085 /// <seealso cref="OpenSim.Region.OptionalModules.World.MoneyModule.SampleMoneyModule.ValidateLandBuy"/>
1086 /// </remarks>
598 public event LandBuy OnValidateLandBuy; 1087 public event LandBuy OnValidateLandBuy;
599 1088
600 public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID) 1089 public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID)
@@ -2031,7 +2520,11 @@ namespace OpenSim.Region.Framework.Scenes
2031 } 2520 }
2032 } 2521 }
2033 2522
2034 // this lets us keep track of nasty script events like timer, etc. 2523 /// <summary>
2524 /// this lets us keep track of nasty script events like timer, etc.
2525 /// </summary>
2526 /// <param name="objLocalID"></param>
2527 /// <param name="Interval"></param>
2035 public void TriggerTimerEvent(uint objLocalID, double Interval) 2528 public void TriggerTimerEvent(uint objLocalID, double Interval)
2036 { 2529 {
2037 throw new NotImplementedException("TriggerTimerEvent was thought to be not used anymore and the registration for the event from scene object part has been commented out due to a memory leak"); 2530 throw new NotImplementedException("TriggerTimerEvent was thought to be not used anymore and the registration for the event from scene object part has been commented out due to a memory leak");
@@ -2093,7 +2586,7 @@ namespace OpenSim.Region.Framework.Scenes
2093 return 6; 2586 return 6;
2094 } 2587 }
2095 2588
2096 public void TriggerOarFileLoaded(Guid requestId, string message) 2589 public void TriggerOarFileLoaded(Guid requestId, List<UUID> loadedScenes, string message)
2097 { 2590 {
2098 OarFileLoaded handlerOarFileLoaded = OnOarFileLoaded; 2591 OarFileLoaded handlerOarFileLoaded = OnOarFileLoaded;
2099 if (handlerOarFileLoaded != null) 2592 if (handlerOarFileLoaded != null)
@@ -2102,7 +2595,7 @@ namespace OpenSim.Region.Framework.Scenes
2102 { 2595 {
2103 try 2596 try
2104 { 2597 {
2105 d(requestId, message); 2598 d(requestId, loadedScenes, message);
2106 } 2599 }
2107 catch (Exception e) 2600 catch (Exception e)
2108 { 2601 {
@@ -2387,7 +2880,7 @@ namespace OpenSim.Region.Framework.Scenes
2387 } 2880 }
2388 } 2881 }
2389 2882
2390 public void TriggerSceneObjectPartUpdated(SceneObjectPart sop) 2883 public void TriggerSceneObjectPartUpdated(SceneObjectPart sop, bool full)
2391 { 2884 {
2392 SceneObjectPartUpdated handler = OnSceneObjectPartUpdated; 2885 SceneObjectPartUpdated handler = OnSceneObjectPartUpdated;
2393 if (handler != null) 2886 if (handler != null)
@@ -2396,7 +2889,7 @@ namespace OpenSim.Region.Framework.Scenes
2396 { 2889 {
2397 try 2890 try
2398 { 2891 {
2399 d(sop); 2892 d(sop, full);
2400 } 2893 }
2401 catch (Exception e) 2894 catch (Exception e)
2402 { 2895 {
@@ -2641,5 +3134,14 @@ namespace OpenSim.Region.Framework.Scenes
2641 } 3134 }
2642 } 3135 }
2643 } 3136 }
3137
3138 public void TriggerThrottleUpdate(ScenePresence scenePresence)
3139 {
3140 ThrottleUpdate handler = OnThrottleUpdate;
3141 if (handler != null)
3142 {
3143 handler(scenePresence);
3144 }
3145 }
2644 } 3146 }
2645} 3147}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 906c1ee..c9d1205 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -93,7 +93,7 @@ namespace OpenSim.Region.Framework.Scenes
93 /// </summary> 93 /// </summary>
94 public void StartScripts() 94 public void StartScripts()
95 { 95 {
96 m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName); 96// m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName);
97 97
98 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>(); 98 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>();
99 99
@@ -1469,7 +1469,7 @@ namespace OpenSim.Region.Framework.Scenes
1469 return newFolderID; 1469 return newFolderID;
1470 } 1470 }
1471 1471
1472 private void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) 1472 public void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems)
1473 { 1473 {
1474 if (folder == null) 1474 if (folder == null)
1475 return; 1475 return;
@@ -1954,8 +1954,19 @@ namespace OpenSim.Region.Framework.Scenes
1954 } 1954 }
1955 } 1955 }
1956 1956
1957 public virtual void DeRezObjects(IClientAPI remoteClient, List<uint> localIDs, 1957 /// <summary>
1958 UUID groupID, DeRezAction action, UUID destinationID) 1958 /// Derez one or more objects from the scene.
1959 /// </summary>
1960 /// <remarks>
1961 /// Won't actually remove the scene object in the case where the object is being copied to a user inventory.
1962 /// </remarks>
1963 /// <param name='remoteClient'>Client requesting derez</param>
1964 /// <param name='localIDs'>Local ids of root parts of objects to delete.</param>
1965 /// <param name='groupID'>Not currently used. Here because the client passes this to us.</param>
1966 /// <param name='action'>DeRezAction</param>
1967 /// <param name='destinationID'>User folder ID to place derezzed object</param>
1968 public virtual void DeRezObjects(
1969 IClientAPI remoteClient, List<uint> localIDs, UUID groupID, DeRezAction action, UUID destinationID)
1959 { 1970 {
1960 // First, see of we can perform the requested action and 1971 // First, see of we can perform the requested action and
1961 // build a list of eligible objects 1972 // build a list of eligible objects
@@ -1997,6 +2008,9 @@ namespace OpenSim.Region.Framework.Scenes
1997 // If child prims have invalid perms, fix them 2008 // If child prims have invalid perms, fix them
1998 grp.AdjustChildPrimPermissions(); 2009 grp.AdjustChildPrimPermissions();
1999 2010
2011 // If child prims have invalid perms, fix them
2012 grp.AdjustChildPrimPermissions();
2013
2000 if (remoteClient == null) 2014 if (remoteClient == null)
2001 { 2015 {
2002 // Autoreturn has a null client. Nothing else does. So 2016 // Autoreturn has a null client. Nothing else does. So
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index e970543..ce6415a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -38,8 +38,20 @@ namespace OpenSim.Region.Framework.Scenes
38{ 38{
39 public partial class Scene 39 public partial class Scene
40 { 40 {
41 /// <summary>
42 /// Send chat to listeners.
43 /// </summary>
44 /// <param name='message'></param>
45 /// <param name='type'>/param>
46 /// <param name='channel'></param>
47 /// <param name='fromPos'></param>
48 /// <param name='fromName'></param>
49 /// <param name='fromID'></param>
50 /// <param name='targetID'></param>
51 /// <param name='fromAgent'></param>
52 /// <param name='broadcast'></param>
41 public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 53 public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
42 UUID fromID, bool fromAgent, bool broadcast, UUID destination) 54 UUID fromID, UUID targetID, bool fromAgent, bool broadcast)
43 { 55 {
44 OSChatMessage args = new OSChatMessage(); 56 OSChatMessage args = new OSChatMessage();
45 57
@@ -49,7 +61,7 @@ namespace OpenSim.Region.Framework.Scenes
49 args.Position = fromPos; 61 args.Position = fromPos;
50 args.SenderUUID = fromID; 62 args.SenderUUID = fromID;
51 args.Scene = this; 63 args.Scene = this;
52 args.Destination = destination; 64 args.Destination = targetID;
53 65
54 if (fromAgent) 66 if (fromAgent)
55 { 67 {
@@ -66,6 +78,10 @@ namespace OpenSim.Region.Framework.Scenes
66 args.From = fromName; 78 args.From = fromName;
67 //args. 79 //args.
68 80
81// m_log.DebugFormat(
82// "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}",
83// args.Message.Replace("\n", "\\n"), args.Channel, args.Type, fromName, broadcast);
84
69 if (broadcast) 85 if (broadcast)
70 EventManager.TriggerOnChatBroadcast(this, args); 86 EventManager.TriggerOnChatBroadcast(this, args);
71 else 87 else
@@ -75,7 +91,7 @@ namespace OpenSim.Region.Framework.Scenes
75 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 91 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
76 UUID fromID, bool fromAgent, bool broadcast) 92 UUID fromID, bool fromAgent, bool broadcast)
77 { 93 {
78 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, broadcast, UUID.Zero); 94 SimChat(message, type, channel, fromPos, fromName, fromID, UUID.Zero, fromAgent, broadcast);
79 } 95 }
80 96
81 /// <summary> 97 /// <summary>
@@ -543,7 +559,7 @@ namespace OpenSim.Region.Framework.Scenes
543 if (!InventoryService.AddFolder(folder)) 559 if (!InventoryService.AddFolder(folder))
544 { 560 {
545 m_log.WarnFormat( 561 m_log.WarnFormat(
546 "[AGENT INVENTORY]: Failed to move create folder for user {0} {1}", 562 "[AGENT INVENTORY]: Failed to create folder for user {0} {1}",
547 remoteClient.Name, remoteClient.AgentId); 563 remoteClient.Name, remoteClient.AgentId);
548 } 564 }
549 } 565 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 649d545..c99e37e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -80,6 +80,11 @@ namespace OpenSim.Region.Framework.Scenes
80 public SynchronizeSceneHandler SynchronizeScene; 80 public SynchronizeSceneHandler SynchronizeScene;
81 81
82 /// <summary> 82 /// <summary>
83 /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other.
84 /// </summary>
85 private object m_removeClientLock = new object();
86
87 /// <summary>
83 /// Statistical information for this scene. 88 /// Statistical information for this scene.
84 /// </summary> 89 /// </summary>
85 public SimStatsReporter StatsReporter { get; private set; } 90 public SimStatsReporter StatsReporter { get; private set; }
@@ -103,8 +108,31 @@ namespace OpenSim.Region.Framework.Scenes
103 /// </summary> 108 /// </summary>
104 public bool CollidablePrims { get; private set; } 109 public bool CollidablePrims { get; private set; }
105 110
111 /// <summary>
112 /// Minimum value of the size of a non-physical prim in each axis
113 /// </summary>
114 public float m_minNonphys = 0.001f;
115
116 /// <summary>
117 /// Maximum value of the size of a non-physical prim in each axis
118 /// </summary>
106 public float m_maxNonphys = 256; 119 public float m_maxNonphys = 256;
120
121 /// <summary>
122 /// Minimum value of the size of a physical prim in each axis
123 /// </summary>
124 public float m_minPhys = 0.01f;
125
126 /// <summary>
127 /// Maximum value of the size of a physical prim in each axis
128 /// </summary>
107 public float m_maxPhys = 10; 129 public float m_maxPhys = 10;
130
131 /// <summary>
132 /// Max prims an object will hold
133 /// </summary>
134 public int m_linksetCapacity = 0;
135
108 public bool m_clampPrimSize; 136 public bool m_clampPrimSize;
109 public bool m_trustBinaries; 137 public bool m_trustBinaries;
110 public bool m_allowScriptCrossings; 138 public bool m_allowScriptCrossings;
@@ -149,7 +177,6 @@ namespace OpenSim.Region.Framework.Scenes
149 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 177 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
150 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 178 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
151 protected string m_simulatorVersion = "OpenSimulator Server"; 179 protected string m_simulatorVersion = "OpenSimulator Server";
152 protected ModuleLoader m_moduleLoader;
153 protected AgentCircuitManager m_authenticateHandler; 180 protected AgentCircuitManager m_authenticateHandler;
154 protected SceneCommunicationService m_sceneGridService; 181 protected SceneCommunicationService m_sceneGridService;
155 protected ISnmpModule m_snmpService = null; 182 protected ISnmpModule m_snmpService = null;
@@ -285,6 +312,31 @@ namespace OpenSim.Region.Framework.Scenes
285 } 312 }
286 private volatile bool m_shuttingDown; 313 private volatile bool m_shuttingDown;
287 314
315 /// <summary>
316 /// Is the scene active?
317 /// </summary>
318 /// <remarks>
319 /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if
320 /// the scene is not active.
321 /// </remarks>
322 public bool Active
323 {
324 get { return m_active; }
325 set
326 {
327 if (value)
328 {
329 if (!m_active)
330 Start();
331 }
332 else
333 {
334 m_active = false;
335 }
336 }
337 }
338 private volatile bool m_active;
339
288// private int m_lastUpdate; 340// private int m_lastUpdate;
289 private bool m_firstHeartbeat = true; 341 private bool m_firstHeartbeat = true;
290 342
@@ -626,7 +678,7 @@ namespace OpenSim.Region.Framework.Scenes
626 public Scene(RegionInfo regInfo, AgentCircuitManager authen, 678 public Scene(RegionInfo regInfo, AgentCircuitManager authen,
627 SceneCommunicationService sceneGridService, 679 SceneCommunicationService sceneGridService,
628 ISimulationDataService simDataService, IEstateDataService estateDataService, 680 ISimulationDataService simDataService, IEstateDataService estateDataService,
629 ModuleLoader moduleLoader, bool dumpAssetsToFile, 681 bool dumpAssetsToFile,
630 IConfigSource config, string simulatorVersion) 682 IConfigSource config, string simulatorVersion)
631 : this(regInfo) 683 : this(regInfo)
632 { 684 {
@@ -637,7 +689,6 @@ namespace OpenSim.Region.Framework.Scenes
637 Random random = new Random(); 689 Random random = new Random();
638 690
639 m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue / 2)) + (uint)(uint.MaxValue / 4); 691 m_lastAllocatedLocalId = (uint)(random.NextDouble() * (double)(uint.MaxValue / 2)) + (uint)(uint.MaxValue / 4);
640 m_moduleLoader = moduleLoader;
641 m_authenticateHandler = authen; 692 m_authenticateHandler = authen;
642 m_sceneGridService = sceneGridService; 693 m_sceneGridService = sceneGridService;
643 m_SimulationDataService = simDataService; 694 m_SimulationDataService = simDataService;
@@ -746,12 +797,24 @@ namespace OpenSim.Region.Framework.Scenes
746 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 797 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
747 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 798 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
748 799
749 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys); 800 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
801 if (RegionInfo.NonphysPrimMin > 0)
802 {
803 m_minNonphys = RegionInfo.NonphysPrimMin;
804 }
805
806 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
750 if (RegionInfo.NonphysPrimMax > 0) 807 if (RegionInfo.NonphysPrimMax > 0)
751 { 808 {
752 m_maxNonphys = RegionInfo.NonphysPrimMax; 809 m_maxNonphys = RegionInfo.NonphysPrimMax;
753 } 810 }
754 811
812 m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys);
813 if (RegionInfo.PhysPrimMin > 0)
814 {
815 m_minPhys = RegionInfo.PhysPrimMin;
816 }
817
755 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 818 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
756 819
757 if (RegionInfo.PhysPrimMax > 0) 820 if (RegionInfo.PhysPrimMax > 0)
@@ -759,6 +822,12 @@ namespace OpenSim.Region.Framework.Scenes
759 m_maxPhys = RegionInfo.PhysPrimMax; 822 m_maxPhys = RegionInfo.PhysPrimMax;
760 } 823 }
761 824
825 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
826 if (RegionInfo.LinksetCapacity > 0)
827 {
828 m_linksetCapacity = RegionInfo.LinksetCapacity;
829 }
830
762 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); 831 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
763 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); 832 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
764 833
@@ -784,13 +853,6 @@ namespace OpenSim.Region.Framework.Scenes
784 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 853 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
785 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine); 854 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
786 855
787 IConfig packetConfig = m_config.Configs["PacketPool"];
788 if (packetConfig != null)
789 {
790 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
791 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
792 }
793
794 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 856 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
795 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion); 857 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
796 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); 858 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
@@ -854,6 +916,8 @@ namespace OpenSim.Region.Framework.Scenes
854 } 916 }
855 917
856 // FIXME: Ultimately this should be in a module. 918 // FIXME: Ultimately this should be in a module.
919 SendPeriodicAppearanceUpdates = true;
920
857 IConfig appearanceConfig = m_config.Configs["Appearance"]; 921 IConfig appearanceConfig = m_config.Configs["Appearance"];
858 if (appearanceConfig != null) 922 if (appearanceConfig != null)
859 { 923 {
@@ -1103,15 +1167,9 @@ namespace OpenSim.Region.Framework.Scenes
1103 } 1167 }
1104 } 1168 }
1105 1169
1106 m_log.Error("[REGION]: Closing"); 1170 m_log.InfoFormat("[REGION]: Restarting region {0}", Name);
1107 Close();
1108 1171
1109 if (PhysicsScene != null) 1172 Close();
1110 {
1111 PhysicsScene.Dispose();
1112 }
1113
1114 m_log.Error("[REGION]: Firing Region Restart Message");
1115 1173
1116 base.Restart(); 1174 base.Restart();
1117 } 1175 }
@@ -1151,6 +1209,14 @@ namespace OpenSim.Region.Framework.Scenes
1151 1209
1152 public void SetSceneCoreDebug(Dictionary<string, string> options) 1210 public void SetSceneCoreDebug(Dictionary<string, string> options)
1153 { 1211 {
1212 if (options.ContainsKey("active"))
1213 {
1214 bool active;
1215
1216 if (bool.TryParse(options["active"], out active))
1217 Active = active;
1218 }
1219
1154 if (options.ContainsKey("scripting")) 1220 if (options.ContainsKey("scripting"))
1155 { 1221 {
1156 bool enableScripts = true; 1222 bool enableScripts = true;
@@ -1226,6 +1292,12 @@ namespace OpenSim.Region.Framework.Scenes
1226 // This is the method that shuts down the scene. 1292 // This is the method that shuts down the scene.
1227 public override void Close() 1293 public override void Close()
1228 { 1294 {
1295 if (m_shuttingDown)
1296 {
1297 m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name);
1298 return;
1299 }
1300
1229 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); 1301 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName);
1230 1302
1231 StatsReporter.Close(); 1303 StatsReporter.Close();
@@ -1272,6 +1344,14 @@ namespace OpenSim.Region.Framework.Scenes
1272 m_log.Debug("[SCENE]: Graph close"); 1344 m_log.Debug("[SCENE]: Graph close");
1273 m_sceneGraph.Close(); 1345 m_sceneGraph.Close();
1274 1346
1347 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1348 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1349
1350 base.Close();
1351
1352 // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence.
1353 // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can
1354 // attempt to reference a null or disposed physics scene.
1275 if (PhysicsScene != null) 1355 if (PhysicsScene != null)
1276 { 1356 {
1277 m_log.Debug("[SCENE]: Dispose Physics"); 1357 m_log.Debug("[SCENE]: Dispose Physics");
@@ -1281,13 +1361,6 @@ namespace OpenSim.Region.Framework.Scenes
1281 phys.Dispose(); 1361 phys.Dispose();
1282 phys = null; 1362 phys = null;
1283 } 1363 }
1284
1285 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1286 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1287
1288 // call the base class Close method.
1289 m_log.Debug("[SCENE]: Base close");
1290 base.Close();
1291 } 1364 }
1292 1365
1293 /// <summary> 1366 /// <summary>
@@ -1295,6 +1368,8 @@ namespace OpenSim.Region.Framework.Scenes
1295 /// </summary> 1368 /// </summary>
1296 public void Start() 1369 public void Start()
1297 { 1370 {
1371 m_active = true;
1372
1298// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1373// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1299 1374
1300 //m_heartbeatTimer.Enabled = true; 1375 //m_heartbeatTimer.Enabled = true;
@@ -1354,7 +1429,7 @@ namespace OpenSim.Region.Framework.Scenes
1354 #region Update Methods 1429 #region Update Methods
1355 1430
1356 /// <summary> 1431 /// <summary>
1357 /// Performs per-frame updates regularly 1432 /// Activate the various loops necessary to continually update the scene.
1358 /// </summary> 1433 /// </summary>
1359 private void Heartbeat() 1434 private void Heartbeat()
1360 { 1435 {
@@ -1411,7 +1486,7 @@ namespace OpenSim.Region.Framework.Scenes
1411 List<Vector3> coarseLocations; 1486 List<Vector3> coarseLocations;
1412 List<UUID> avatarUUIDs; 1487 List<UUID> avatarUUIDs;
1413 1488
1414 while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) 1489 while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun))
1415 { 1490 {
1416 runtc = Util.EnvironmentTickCount(); 1491 runtc = Util.EnvironmentTickCount();
1417 ++MaintenanceRun; 1492 ++MaintenanceRun;
@@ -1473,7 +1548,7 @@ namespace OpenSim.Region.Framework.Scenes
1473 int sleepMS; 1548 int sleepMS;
1474 int framestart; 1549 int framestart;
1475 1550
1476 while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) 1551 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
1477 { 1552 {
1478 framestart = Util.EnvironmentTickCount(); 1553 framestart = Util.EnvironmentTickCount();
1479 ++Frame; 1554 ++Frame;
@@ -1672,15 +1747,19 @@ namespace OpenSim.Region.Framework.Scenes
1672 1747
1673 private void CheckAtTargets() 1748 private void CheckAtTargets()
1674 { 1749 {
1675 List<SceneObjectGroup> objs = new List<SceneObjectGroup>(); 1750 List<SceneObjectGroup> objs = null;
1751
1676 lock (m_groupsWithTargets) 1752 lock (m_groupsWithTargets)
1677 { 1753 {
1678 foreach (SceneObjectGroup grp in m_groupsWithTargets.Values) 1754 if (m_groupsWithTargets.Count != 0)
1679 objs.Add(grp); 1755 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1680 } 1756 }
1681 1757
1682 foreach (SceneObjectGroup entry in objs) 1758 if (objs != null)
1683 entry.checkAtTargets(); 1759 {
1760 foreach (SceneObjectGroup entry in objs)
1761 entry.checkAtTargets();
1762 }
1684 } 1763 }
1685 1764
1686 /// <summary> 1765 /// <summary>
@@ -2193,10 +2272,14 @@ namespace OpenSim.Region.Framework.Scenes
2193 public bool AddRestoredSceneObject( 2272 public bool AddRestoredSceneObject(
2194 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 2273 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
2195 { 2274 {
2196 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 2275 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates))
2197 if (result) 2276 {
2198 sceneObject.IsDeleted = false; 2277 sceneObject.IsDeleted = false;
2199 return result; 2278 EventManager.TriggerObjectAddedToScene(sceneObject);
2279 return true;
2280 }
2281
2282 return false;
2200 } 2283 }
2201 2284
2202 /// <summary> 2285 /// <summary>
@@ -2837,77 +2920,89 @@ namespace OpenSim.Region.Framework.Scenes
2837 2920
2838 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 2921 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
2839 { 2922 {
2923 ScenePresence sp;
2924 bool vialogin;
2925
2840 // Validation occurs in LLUDPServer 2926 // Validation occurs in LLUDPServer
2927 //
2928 // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with
2929 // each other. In practice, this does not currently occur in the code.
2841 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); 2930 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
2842 2931
2843 bool vialogin 2932 // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection
2844 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 2933 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point
2845 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2934 // whilst connecting).
2846 2935 //
2847 CheckHeartbeat(); 2936 // It would be easier to lock across all NewUserConnection(), AddNewClient() and
2848 2937 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
2849 ScenePresence sp = GetScenePresence(client.AgentId); 2938 // response in some module listening to AddNewClient()) from holding up unrelated agent calls.
2850 2939 //
2851 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this 2940 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
2852 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause 2941 // AddNewClient() operations (though not other ops).
2853 // other problems, and possible the code calling AddNewClient() should ensure that no client is already 2942 // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved.
2854 // connected. 2943 lock (aCircuit)
2855 if (sp == null) 2944 {
2856 { 2945 vialogin
2857 m_log.DebugFormat( 2946 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2858 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 2947 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2859 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); 2948
2860 2949 CheckHeartbeat();
2861 m_clientManager.Add(client); 2950
2862 SubscribeToClientEvents(client); 2951 sp = GetScenePresence(client.AgentId);
2863
2864 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2865 m_eventManager.TriggerOnNewPresence(sp);
2866
2867 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2868 2952
2869 // The first agent upon login is a root agent by design. 2953 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
2870 // For this agent we will have to rez the attachments. 2954 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
2871 // All other AddNewClient calls find aCircuit.child to be true. 2955 // other problems, and possible the code calling AddNewClient() should ensure that no client is already
2872 if (aCircuit.child == false) 2956 // connected.
2957 if (sp == null)
2873 { 2958 {
2874 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to 2959 m_log.DebugFormat(
2875 // start the scripts again (since this is done in RezAttachments()). 2960 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}",
2876 // XXX: This is convoluted. 2961 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos);
2877 sp.IsChildAgent = false; 2962
2878 2963 m_clientManager.Add(client);
2879 if (AttachmentsModule != null) 2964 SubscribeToClientEvents(client);
2880 Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); 2965
2966 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2967 m_eventManager.TriggerOnNewPresence(sp);
2968
2969 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2970
2971 // The first agent upon login is a root agent by design.
2972 // For this agent we will have to rez the attachments.
2973 // All other AddNewClient calls find aCircuit.child to be true.
2974 if (aCircuit.child == false)
2975 {
2976 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to
2977 // start the scripts again (since this is done in RezAttachments()).
2978 // XXX: This is convoluted.
2979 sp.IsChildAgent = false;
2980
2981 if (AttachmentsModule != null)
2982 Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); });
2983 }
2881 } 2984 }
2882 } 2985 else
2883 else 2986 {
2884 { 2987 m_log.WarnFormat(
2885 m_log.WarnFormat( 2988 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
2886 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 2989 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
2887 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); 2990 }
2888 } 2991
2992 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
2993 // client is for a root or child agent.
2994 client.SceneAgent = sp;
2889 2995
2890 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 2996 // Cache the user's name
2891 // client is for a root or child agent. 2997 CacheUserName(sp, aCircuit);
2892 client.SceneAgent = sp; 2998
2999 EventManager.TriggerOnNewClient(client);
3000 if (vialogin)
3001 EventManager.TriggerOnClientLogin(client);
3002 }
2893 3003
2894 m_LastLogin = Util.EnvironmentTickCount(); 3004 m_LastLogin = Util.EnvironmentTickCount();
2895 3005
2896 // Cache the user's name
2897 CacheUserName(sp, aCircuit);
2898
2899 EventManager.TriggerOnNewClient(client);
2900 if (vialogin)
2901 {
2902 EventManager.TriggerOnClientLogin(client);
2903 // Send initial parcel data
2904/* this is done on TriggerOnNewClient by landmanegement respective event handler
2905 Vector3 pos = sp.AbsolutePosition;
2906 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2907 land.SendLandUpdateToClient(client);
2908*/
2909 }
2910
2911 return sp; 3006 return sp;
2912 } 3007 }
2913 3008
@@ -3447,110 +3542,132 @@ namespace OpenSim.Region.Framework.Scenes
3447 { 3542 {
3448// CheckHeartbeat(); 3543// CheckHeartbeat();
3449 bool isChildAgent = false; 3544 bool isChildAgent = false;
3450 ScenePresence avatar = GetScenePresence(agentID); 3545 AgentCircuitData acd;
3451
3452 if (avatar == null)
3453 {
3454 m_log.WarnFormat(
3455 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3456 3546
3457 return; 3547 lock (m_removeClientLock)
3458 }
3459
3460 try
3461 { 3548 {
3462 isChildAgent = avatar.IsChildAgent; 3549 acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3463 3550
3464 m_log.DebugFormat( 3551 if (acd == null)
3465 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3466 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
3467
3468 // Don't do this to root agents, it's not nice for the viewer
3469 if (closeChildAgents && isChildAgent)
3470 { 3552 {
3471 // Tell a single agent to disconnect from the region. 3553 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID);
3472 IEventQueue eq = RequestModuleInterface<IEventQueue>(); 3554 return;
3473 if (eq != null)
3474 {
3475 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3476 }
3477 else
3478 {
3479 avatar.ControllingClient.SendShutdownConnectionNotice();
3480 }
3481 } 3555 }
3482 3556 else
3483 // Only applies to root agents.
3484 if (avatar.ParentID != 0)
3485 { 3557 {
3486 avatar.StandUp(); 3558 // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
3559 // simultaneously.
3560 // We also need to remove by agent ID since NPCs will have no circuit code.
3561 m_authenticateHandler.RemoveCircuit(agentID);
3487 } 3562 }
3563 }
3488 3564
3489 m_sceneGraph.removeUserCount(!isChildAgent); 3565 lock (acd)
3490 3566 {
3491 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3567 ScenePresence avatar = GetScenePresence(agentID);
3492 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3568
3493 if (closeChildAgents && CapsModule != null) 3569 if (avatar == null)
3494 CapsModule.RemoveCaps(agentID);
3495
3496 // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3497 // this method is doing is HORRIBLE!!!
3498 avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3499
3500 if (closeChildAgents && !isChildAgent)
3501 { 3570 {
3502 List<ulong> regions = avatar.KnownRegionHandles; 3571 m_log.WarnFormat(
3503 regions.Remove(RegionInfo.RegionHandle); 3572 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3504 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3573
3574 return;
3505 } 3575 }
3506 3576
3507 m_eventManager.TriggerClientClosed(agentID, this); 3577 try
3508 m_eventManager.TriggerOnRemovePresence(agentID);
3509
3510 if (!isChildAgent)
3511 { 3578 {
3512 if (AttachmentsModule != null) 3579 isChildAgent = avatar.IsChildAgent;
3580
3581 m_log.DebugFormat(
3582 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3583 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
3584
3585 // Don't do this to root agents, it's not nice for the viewer
3586 if (closeChildAgents && isChildAgent)
3513 { 3587 {
3514 AttachmentsModule.DeRezAttachments(avatar); 3588 // Tell a single agent to disconnect from the region.
3589 IEventQueue eq = RequestModuleInterface<IEventQueue>();
3590 if (eq != null)
3591 {
3592 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3593 }
3594 else
3595 {
3596 avatar.ControllingClient.SendShutdownConnectionNotice();
3597 }
3515 } 3598 }
3516 3599
3517 ForEachClient( 3600 // Only applies to root agents.
3518 delegate(IClientAPI client) 3601 if (avatar.ParentID != 0)
3602 {
3603 avatar.StandUp();
3604 }
3605
3606 m_sceneGraph.removeUserCount(!isChildAgent);
3607
3608 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3609 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3610 if (closeChildAgents && CapsModule != null)
3611 CapsModule.RemoveCaps(agentID);
3612
3613// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3614// // this method is doing is HORRIBLE!!!
3615 // Commented pending deletion since this method no longer appears to do anything at all
3616// avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3617
3618 if (closeChildAgents && !isChildAgent)
3619 {
3620 List<ulong> regions = avatar.KnownRegionHandles;
3621 regions.Remove(RegionInfo.RegionHandle);
3622 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3623 }
3624
3625 m_eventManager.TriggerClientClosed(agentID, this);
3626 m_eventManager.TriggerOnRemovePresence(agentID);
3627
3628 if (!isChildAgent)
3629 {
3630 if (AttachmentsModule != null)
3519 { 3631 {
3520 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3632 AttachmentsModule.DeRezAttachments(avatar);
3521 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } 3633 }
3522 catch (NullReferenceException) { }
3523 });
3524 }
3525
3526 // It's possible for child agents to have transactions if changes are being made cross-border.
3527 if (AgentTransactionsModule != null)
3528 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3529 3634
3530 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3635 ForEachClient(
3531 m_log.Debug("[Scene] The avatar has left the building"); 3636 delegate(IClientAPI client)
3532 } 3637 {
3533 catch (Exception e) 3638 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3534 { 3639 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); }
3535 m_log.Error( 3640 catch (NullReferenceException) { }
3536 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); 3641 });
3537 } 3642 }
3538 finally
3539 {
3540 try
3541 {
3542 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3543 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3544 // the same cleanup exception continually.
3545 m_sceneGraph.RemoveScenePresence(agentID);
3546 m_clientManager.Remove(agentID);
3547 3643
3548 avatar.Close(); 3644 // It's possible for child agents to have transactions if changes are being made cross-border.
3645 if (AgentTransactionsModule != null)
3646 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3647 m_log.Debug("[Scene] The avatar has left the building");
3549 } 3648 }
3550 catch (Exception e) 3649 catch (Exception e)
3551 { 3650 {
3552 m_log.Error( 3651 m_log.Error(
3553 string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); 3652 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e);
3653 }
3654 finally
3655 {
3656 try
3657 {
3658 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3659 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3660 // the same cleanup exception continually.
3661 m_sceneGraph.RemoveScenePresence(agentID);
3662 m_clientManager.Remove(agentID);
3663
3664 avatar.Close();
3665 }
3666 catch (Exception e)
3667 {
3668 m_log.Error(
3669 string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e);
3670 }
3554 } 3671 }
3555 } 3672 }
3556 3673
@@ -3609,11 +3726,9 @@ namespace OpenSim.Region.Framework.Scenes
3609 3726
3610 /// <summary> 3727 /// <summary>
3611 /// Do the work necessary to initiate a new user connection for a particular scene. 3728 /// Do the work necessary to initiate a new user connection for a particular scene.
3612 /// At the moment, this consists of setting up the caps infrastructure
3613 /// The return bool should allow for connections to be refused, but as not all calling paths
3614 /// take proper notice of it let, we allowed banned users in still.
3615 /// </summary> 3729 /// </summary>
3616 /// <param name="agent">CircuitData of the agent who is connecting</param> 3730 /// <param name="agent">CircuitData of the agent who is connecting</param>
3731 /// <param name="teleportFlags"></param>
3617 /// <param name="reason">Outputs the reason for the false response on this string</param> 3732 /// <param name="reason">Outputs the reason for the false response on this string</param>
3618 /// <returns>True if the region accepts this agent. False if it does not. False will 3733 /// <returns>True if the region accepts this agent. False if it does not. False will
3619 /// also return a reason.</returns> 3734 /// also return a reason.</returns>
@@ -3624,10 +3739,20 @@ namespace OpenSim.Region.Framework.Scenes
3624 3739
3625 /// <summary> 3740 /// <summary>
3626 /// Do the work necessary to initiate a new user connection for a particular scene. 3741 /// Do the work necessary to initiate a new user connection for a particular scene.
3627 /// At the moment, this consists of setting up the caps infrastructure 3742 /// </summary>
3743 /// <remarks>
3744 /// The return bool should allow for connections to be refused, but as not all calling paths
3745 /// take proper notice of it yet, we still allowed banned users in.
3746 ///
3747 /// At the moment this method consists of setting up the caps infrastructure
3628 /// The return bool should allow for connections to be refused, but as not all calling paths 3748 /// The return bool should allow for connections to be refused, but as not all calling paths
3629 /// take proper notice of it let, we allowed banned users in still. 3749 /// take proper notice of it let, we allowed banned users in still.
3630 /// </summary> 3750 ///
3751 /// This method is called by the login service (in the case of login) or another simulator (in the case of region
3752 /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection
3753 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3754 /// the LLUDP stack).
3755 /// </remarks>
3631 /// <param name="agent">CircuitData of the agent who is connecting</param> 3756 /// <param name="agent">CircuitData of the agent who is connecting</param>
3632 /// <param name="reason">Outputs the reason for the false response on this string</param> 3757 /// <param name="reason">Outputs the reason for the false response on this string</param>
3633 /// <param name="requirePresenceLookup">True for normal presence. False for NPC 3758 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
@@ -3726,83 +3851,86 @@ namespace OpenSim.Region.Framework.Scenes
3726 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3851 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3727 sp.Name, sp.UUID, RegionInfo.RegionName); 3852 sp.Name, sp.UUID, RegionInfo.RegionName);
3728 3853
3729 sp.ControllingClient.Close(); 3854 sp.ControllingClient.Close(true, true);
3730 sp = null; 3855 sp = null;
3731 } 3856 }
3732 3857
3733 3858 lock (agent)
3734 //On login test land permisions
3735 if (vialogin)
3736 { 3859 {
3737 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 3860 //On login test land permisions
3738 if (cache != null) 3861 if (vialogin)
3739 cache.Remove(agent.firstname + " " + agent.lastname);
3740 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3741 { 3862 {
3742 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); 3863 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3743 return false; 3864 if (cache != null)
3865 cache.Remove(agent.firstname + " " + agent.lastname);
3866 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3867 {
3868 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3869 return false;
3870 }
3744 } 3871 }
3745 }
3746 3872
3747 if (sp == null) // We don't have an [child] agent here already 3873 if (sp == null) // We don't have an [child] agent here already
3748 {
3749 if (requirePresenceLookup)
3750 { 3874 {
3751 try 3875 if (requirePresenceLookup)
3752 { 3876 {
3753 if (!VerifyUserPresence(agent, out reason)) 3877 try
3878 {
3879 if (!VerifyUserPresence(agent, out reason))
3880 return false;
3881 } catch (Exception e)
3882 {
3883 m_log.ErrorFormat(
3884 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
3754 return false; 3885 return false;
3755 } catch (Exception e) 3886 }
3887 }
3888
3889 try
3890 {
3891 // Always check estate if this is a login. Always
3892 // check if banned regions are to be blacked out.
3893 if (vialogin || (!m_seeIntoBannedRegion))
3894 {
3895 if (!AuthorizeUser(agent, out reason))
3896 return false;
3897 }
3898 }
3899 catch (Exception e)
3756 { 3900 {
3757 m_log.ErrorFormat( 3901 m_log.ErrorFormat(
3758 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 3902 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
3759 return false; 3903 return false;
3760 } 3904 }
3761 }
3762 3905
3763 try 3906 m_log.InfoFormat(
3764 { 3907 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3765 // Always check estate if this is a login. Always 3908 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname,
3766 // check if banned regions are to be blacked out. 3909 agent.AgentID, agent.circuitcode);
3767 if (vialogin || (!m_seeIntoBannedRegion)) 3910
3911 if (CapsModule != null)
3768 { 3912 {
3769 if (!AuthorizeUser(agent, out reason)) 3913 CapsModule.SetAgentCapsSeeds(agent);
3770 return false; 3914 CapsModule.CreateCaps(agent.AgentID);
3771 } 3915 }
3772 } 3916 }
3773 catch (Exception e) 3917 else
3774 { 3918 {
3775 m_log.ErrorFormat( 3919 // Let the SP know how we got here. This has a lot of interesting
3776 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 3920 // uses down the line.
3777 return false; 3921 sp.TeleportFlags = (TPFlags)teleportFlags;
3778 }
3779
3780 m_log.InfoFormat(
3781 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3782 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname,
3783 agent.AgentID, agent.circuitcode);
3784 3922
3785 if (CapsModule != null) 3923 if (sp.IsChildAgent)
3786 { 3924 {
3787 CapsModule.SetAgentCapsSeeds(agent); 3925 m_log.DebugFormat(
3788 CapsModule.CreateCaps(agent.AgentID); 3926 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3789 } 3927 agent.AgentID, RegionInfo.RegionName);
3790 } else
3791 {
3792 // Let the SP know how we got here. This has a lot of interesting
3793 // uses down the line.
3794 sp.TeleportFlags = (TPFlags)teleportFlags;
3795 3928
3796 if (sp.IsChildAgent) 3929 sp.AdjustKnownSeeds();
3797 {
3798 m_log.DebugFormat(
3799 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3800 agent.AgentID, RegionInfo.RegionName);
3801 3930
3802 sp.AdjustKnownSeeds(); 3931 if (CapsModule != null)
3803 3932 CapsModule.SetAgentCapsSeeds(agent);
3804 if (CapsModule != null) 3933 }
3805 CapsModule.SetAgentCapsSeeds(agent);
3806 } 3934 }
3807 } 3935 }
3808 3936
@@ -4233,8 +4361,9 @@ namespace OpenSim.Region.Framework.Scenes
4233 return false; 4361 return false;
4234 } 4362 }
4235 4363
4236 // We have to wait until the viewer contacts this region after receiving EAC. 4364 // We have to wait until the viewer contacts this region
4237 // That calls AddNewClient, which finally creates the ScenePresence 4365 // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send
4366 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence.
4238 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4367 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
4239 4368
4240 if (childAgentUpdate != null) 4369 if (childAgentUpdate != null)
@@ -4329,15 +4458,18 @@ namespace OpenSim.Region.Framework.Scenes
4329 /// Tell a single agent to disconnect from the region. 4458 /// Tell a single agent to disconnect from the region.
4330 /// </summary> 4459 /// </summary>
4331 /// <param name="agentID"></param> 4460 /// <param name="agentID"></param>
4332 /// <param name="childOnly"></param> 4461 /// <param name="force">
4333 public bool IncomingCloseAgent(UUID agentID, bool childOnly) 4462 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
4463 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4464 /// </param>
4465 public bool IncomingCloseAgent(UUID agentID, bool force)
4334 { 4466 {
4335 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4467 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
4336 4468
4337 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4469 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
4338 if (presence != null) 4470 if (presence != null)
4339 { 4471 {
4340 presence.ControllingClient.Close(false); 4472 presence.ControllingClient.Close(force, force);
4341 return true; 4473 return true;
4342 } 4474 }
4343 4475
@@ -4543,6 +4675,16 @@ namespace OpenSim.Region.Framework.Scenes
4543 return LandChannel.GetLandObject(x, y).LandData; 4675 return LandChannel.GetLandObject(x, y).LandData;
4544 } 4676 }
4545 4677
4678 /// <summary>
4679 /// Get LandData by position.
4680 /// </summary>
4681 /// <param name="pos"></param>
4682 /// <returns></returns>
4683 public LandData GetLandData(Vector3 pos)
4684 {
4685 return GetLandData(pos.X, pos.Y);
4686 }
4687
4546 public LandData GetLandData(uint x, uint y) 4688 public LandData GetLandData(uint x, uint y)
4547 { 4689 {
4548 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 4690 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
@@ -4773,13 +4915,24 @@ namespace OpenSim.Region.Framework.Scenes
4773 /// Get a group via its UUID 4915 /// Get a group via its UUID
4774 /// </summary> 4916 /// </summary>
4775 /// <param name="fullID"></param> 4917 /// <param name="fullID"></param>
4776 /// <returns>null if no group with that name exists</returns> 4918 /// <returns>null if no group with that id exists</returns>
4777 public SceneObjectGroup GetSceneObjectGroup(UUID fullID) 4919 public SceneObjectGroup GetSceneObjectGroup(UUID fullID)
4778 { 4920 {
4779 return m_sceneGraph.GetSceneObjectGroup(fullID); 4921 return m_sceneGraph.GetSceneObjectGroup(fullID);
4780 } 4922 }
4781 4923
4782 /// <summary> 4924 /// <summary>
4925 /// Get a group via its local ID
4926 /// </summary>
4927 /// <remarks>This will only return a group if the local ID matches a root part</remarks>
4928 /// <param name="localID"></param>
4929 /// <returns>null if no group with that id exists</returns>
4930 public SceneObjectGroup GetSceneObjectGroup(uint localID)
4931 {
4932 return m_sceneGraph.GetSceneObjectGroup(localID);
4933 }
4934
4935 /// <summary>
4783 /// Get a group by name from the scene (will return the first 4936 /// Get a group by name from the scene (will return the first
4784 /// found, if there are more than one prim with the same name) 4937 /// found, if there are more than one prim with the same name)
4785 /// </summary> 4938 /// </summary>
@@ -4791,6 +4944,18 @@ namespace OpenSim.Region.Framework.Scenes
4791 } 4944 }
4792 4945
4793 /// <summary> 4946 /// <summary>
4947 /// Attempt to get the SOG via its UUID
4948 /// </summary>
4949 /// <param name="fullID"></param>
4950 /// <param name="sog"></param>
4951 /// <returns></returns>
4952 public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog)
4953 {
4954 sog = GetSceneObjectGroup(fullID);
4955 return sog != null;
4956 }
4957
4958 /// <summary>
4794 /// Get a prim by name from the scene (will return the first 4959 /// Get a prim by name from the scene (will return the first
4795 /// found, if there are more than one prim with the same name) 4960 /// found, if there are more than one prim with the same name)
4796 /// </summary> 4961 /// </summary>
@@ -4822,6 +4987,18 @@ namespace OpenSim.Region.Framework.Scenes
4822 } 4987 }
4823 4988
4824 /// <summary> 4989 /// <summary>
4990 /// Attempt to get a prim via its UUID
4991 /// </summary>
4992 /// <param name="fullID"></param>
4993 /// <param name="sop"></param>
4994 /// <returns></returns>
4995 public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop)
4996 {
4997 sop = GetSceneObjectPart(fullID);
4998 return sop != null;
4999 }
5000
5001 /// <summary>
4825 /// Get a scene object group that contains the prim with the given local id 5002 /// Get a scene object group that contains the prim with the given local id
4826 /// </summary> 5003 /// </summary>
4827 /// <param name="localID"></param> 5004 /// <param name="localID"></param>
@@ -4915,14 +5092,15 @@ namespace OpenSim.Region.Framework.Scenes
4915 client.SendRegionHandle(regionID, handle); 5092 client.SendRegionHandle(regionID, handle);
4916 } 5093 }
4917 5094
4918 public bool NeedSceneCacheClear(UUID agentID) 5095// Commented pending deletion since this method no longer appears to do anything at all
4919 { 5096// public bool NeedSceneCacheClear(UUID agentID)
4920 IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>(); 5097// {
4921 if (inv == null) 5098// IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>();
4922 return true; 5099// if (inv == null)
4923 5100// return true;
4924 return inv.NeedSceneCacheClear(agentID, this); 5101//
4925 } 5102// return inv.NeedSceneCacheClear(agentID, this);
5103// }
4926 5104
4927 public void CleanTempObjects() 5105 public void CleanTempObjects()
4928 { 5106 {
@@ -5876,6 +6054,9 @@ Environment.Exit(1);
5876 6054
5877 public string GetExtraSetting(string name) 6055 public string GetExtraSetting(string name)
5878 { 6056 {
6057 if (m_extraSettings == null)
6058 return String.Empty;
6059
5879 string val; 6060 string val;
5880 6061
5881 if (!m_extraSettings.TryGetValue(name, out val)) 6062 if (!m_extraSettings.TryGetValue(name, out val))
@@ -5886,6 +6067,9 @@ Environment.Exit(1);
5886 6067
5887 public void StoreExtraSetting(string name, string val) 6068 public void StoreExtraSetting(string name, string val)
5888 { 6069 {
6070 if (m_extraSettings == null)
6071 return;
6072
5889 string oldVal; 6073 string oldVal;
5890 6074
5891 if (m_extraSettings.TryGetValue(name, out oldVal)) 6075 if (m_extraSettings.TryGetValue(name, out oldVal))
@@ -5903,6 +6087,9 @@ Environment.Exit(1);
5903 6087
5904 public void RemoveExtraSetting(string name) 6088 public void RemoveExtraSetting(string name)
5905 { 6089 {
6090 if (m_extraSettings == null)
6091 return;
6092
5906 if (!m_extraSettings.ContainsKey(name)) 6093 if (!m_extraSettings.ContainsKey(name))
5907 return; 6094 return;
5908 6095
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 7c8bd88..74c9582 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -67,12 +67,6 @@ namespace OpenSim.Region.Framework.Scenes
67 /// <value> 67 /// <value>
68 /// All the region modules attached to this scene. 68 /// All the region modules attached to this scene.
69 /// </value> 69 /// </value>
70 public Dictionary<string, IRegionModule> Modules
71 {
72 get { return m_modules; }
73 }
74 protected Dictionary<string, IRegionModule> m_modules = new Dictionary<string, IRegionModule>();
75
76 public Dictionary<string, IRegionModuleBase> RegionModules 70 public Dictionary<string, IRegionModuleBase> RegionModules
77 { 71 {
78 get { return m_regionModules; } 72 get { return m_regionModules; }
@@ -273,16 +267,6 @@ namespace OpenSim.Region.Framework.Scenes
273 /// </summary> 267 /// </summary>
274 public virtual void Close() 268 public virtual void Close()
275 { 269 {
276 // Shut down all non shared modules.
277 foreach (IRegionModule module in Modules.Values)
278 {
279 if (!module.IsSharedModule)
280 {
281 module.Close();
282 }
283 }
284 Modules.Clear();
285
286 try 270 try
287 { 271 {
288 EventManager.TriggerShutdown(); 272 EventManager.TriggerShutdown();
@@ -313,19 +297,6 @@ namespace OpenSim.Region.Framework.Scenes
313 #region Module Methods 297 #region Module Methods
314 298
315 /// <summary> 299 /// <summary>
316 /// Add a module to this scene.
317 /// </summary>
318 /// <param name="name"></param>
319 /// <param name="module"></param>
320 public void AddModule(string name, IRegionModule module)
321 {
322 if (!Modules.ContainsKey(name))
323 {
324 Modules.Add(name, module);
325 }
326 }
327
328 /// <summary>
329 /// Add a region-module to this scene. TODO: This will replace AddModule in the future. 300 /// Add a region-module to this scene. TODO: This will replace AddModule in the future.
330 /// </summary> 301 /// </summary>
331 /// <param name="name"></param> 302 /// <param name="name"></param>
@@ -509,9 +480,9 @@ namespace OpenSim.Region.Framework.Scenes
509 /// <param name="shorthelp"></param> 480 /// <param name="shorthelp"></param>
510 /// <param name="longhelp"></param> 481 /// <param name="longhelp"></param>
511 /// <param name="callback"></param> 482 /// <param name="callback"></param>
512 public void AddCommand(object mod, string command, string shorthelp, string longhelp, CommandDelegate callback) 483 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback)
513 { 484 {
514 AddCommand(mod, command, shorthelp, longhelp, string.Empty, callback); 485 AddCommand(module, command, shorthelp, longhelp, string.Empty, callback);
515 } 486 }
516 487
517 /// <summary> 488 /// <summary>
@@ -529,9 +500,9 @@ namespace OpenSim.Region.Framework.Scenes
529 /// <param name="longhelp"></param> 500 /// <param name="longhelp"></param>
530 /// <param name="callback"></param> 501 /// <param name="callback"></param>
531 public void AddCommand( 502 public void AddCommand(
532 string category, object mod, string command, string shorthelp, string longhelp, CommandDelegate callback) 503 string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback)
533 { 504 {
534 AddCommand(category, mod, command, shorthelp, longhelp, string.Empty, callback); 505 AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback);
535 } 506 }
536 507
537 /// <summary> 508 /// <summary>
@@ -543,29 +514,14 @@ namespace OpenSim.Region.Framework.Scenes
543 /// <param name="longhelp"></param> 514 /// <param name="longhelp"></param>
544 /// <param name="descriptivehelp"></param> 515 /// <param name="descriptivehelp"></param>
545 /// <param name="callback"></param> 516 /// <param name="callback"></param>
546 public void AddCommand(object mod, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) 517 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback)
547 { 518 {
548 string moduleName = ""; 519 string moduleName = "";
549 520
550 if (mod != null) 521 if (module != null)
551 { 522 moduleName = module.Name;
552 if (mod is IRegionModule)
553 {
554 IRegionModule module = (IRegionModule)mod;
555 moduleName = module.Name;
556 }
557 else if (mod is IRegionModuleBase)
558 {
559 IRegionModuleBase module = (IRegionModuleBase)mod;
560 moduleName = module.Name;
561 }
562 else
563 {
564 throw new Exception("AddCommand module parameter must be IRegionModule or IRegionModuleBase");
565 }
566 }
567 523
568 AddCommand(moduleName, mod, command, shorthelp, longhelp, descriptivehelp, callback); 524 AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback);
569 } 525 }
570 526
571 /// <summary> 527 /// <summary>
@@ -581,7 +537,7 @@ namespace OpenSim.Region.Framework.Scenes
581 /// <param name="descriptivehelp"></param> 537 /// <param name="descriptivehelp"></param>
582 /// <param name="callback"></param> 538 /// <param name="callback"></param>
583 public void AddCommand( 539 public void AddCommand(
584 string category, object mod, string command, 540 string category, IRegionModuleBase module, string command,
585 string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback) 541 string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback)
586 { 542 {
587 if (MainConsole.Instance == null) 543 if (MainConsole.Instance == null)
@@ -589,22 +545,8 @@ namespace OpenSim.Region.Framework.Scenes
589 545
590 bool shared = false; 546 bool shared = false;
591 547
592 if (mod != null) 548 if (module != null)
593 { 549 shared = module is ISharedRegionModule;
594 if (mod is IRegionModule)
595 {
596 IRegionModule module = (IRegionModule)mod;
597 shared = module.IsSharedModule;
598 }
599 else if (mod is IRegionModuleBase)
600 {
601 shared = mod is ISharedRegionModule;
602 }
603 else
604 {
605 throw new Exception("AddCommand module parameter must be IRegionModule or IRegionModuleBase");
606 }
607 }
608 550
609 MainConsole.Instance.Commands.AddCommand( 551 MainConsole.Instance.Commands.AddCommand(
610 category, shared, command, shorthelp, longhelp, descriptivehelp, callback); 552 category, shared, command, shorthelp, longhelp, descriptivehelp, callback);
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index af13b46..e599e90 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -342,7 +342,7 @@ namespace OpenSim.Region.Framework.Scenes
342 public bool AddNewSceneObject( 342 public bool AddNewSceneObject(
343 SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) 343 SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel)
344 { 344 {
345 AddNewSceneObject(sceneObject, true, false); 345 AddNewSceneObject(sceneObject, attachToBackup, false);
346 346
347 if (pos != null) 347 if (pos != null)
348 sceneObject.AbsolutePosition = (Vector3)pos; 348 sceneObject.AbsolutePosition = (Vector3)pos;
@@ -421,12 +421,9 @@ namespace OpenSim.Region.Framework.Scenes
421 { 421 {
422 Vector3 scale = part.Shape.Scale; 422 Vector3 scale = part.Shape.Scale;
423 423
424 if (scale.X > m_parentScene.m_maxNonphys) 424 scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X));
425 scale.X = m_parentScene.m_maxNonphys; 425 scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y));
426 if (scale.Y > m_parentScene.m_maxNonphys) 426 scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z));
427 scale.Y = m_parentScene.m_maxNonphys;
428 if (scale.Z > m_parentScene.m_maxNonphys)
429 scale.Z = m_parentScene.m_maxNonphys;
430 427
431 part.Shape.Scale = scale; 428 part.Shape.Scale = scale;
432 } 429 }
@@ -1066,6 +1063,30 @@ namespace OpenSim.Region.Framework.Scenes
1066 } 1063 }
1067 1064
1068 /// <summary> 1065 /// <summary>
1066 /// Get a group in the scene
1067 /// </summary>
1068 /// <remarks>
1069 /// This will only return a group if the local ID matches the root part, not other parts.
1070 /// </remarks>
1071 /// <param name="localID">Local id of the root part of the group</param>
1072 /// <returns>null if no such group was found</returns>
1073 protected internal SceneObjectGroup GetSceneObjectGroup(uint localID)
1074 {
1075 lock (SceneObjectGroupsByLocalPartID)
1076 {
1077 if (SceneObjectGroupsByLocalPartID.ContainsKey(localID))
1078 {
1079 SceneObjectGroup so = SceneObjectGroupsByLocalPartID[localID];
1080
1081 if (so.LocalId == localID)
1082 return so;
1083 }
1084 }
1085
1086 return null;
1087 }
1088
1089 /// <summary>
1069 /// Get a group by name from the scene (will return the first 1090 /// Get a group by name from the scene (will return the first
1070 /// found, if there are more than one prim with the same name) 1091 /// found, if there are more than one prim with the same name)
1071 /// </summary> 1092 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index f1b09ca..0e0b6c3 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -92,7 +92,11 @@ namespace OpenSim.Region.Framework.Scenes
92 private static SceneManager m_instance = null; 92 private static SceneManager m_instance = null;
93 public static SceneManager Instance 93 public static SceneManager Instance
94 { 94 {
95 get { return m_instance; } 95 get {
96 if (m_instance == null)
97 m_instance = new SceneManager();
98 return m_instance;
99 }
96 } 100 }
97 101
98 private readonly DoubleDictionary<UUID, string, Scene> m_localScenes = new DoubleDictionary<UUID, string, Scene>(); 102 private readonly DoubleDictionary<UUID, string, Scene> m_localScenes = new DoubleDictionary<UUID, string, Scene>();
@@ -103,16 +107,19 @@ namespace OpenSim.Region.Framework.Scenes
103 get { return new List<Scene>(m_localScenes.FindAll(delegate(Scene s) { return true; })); } 107 get { return new List<Scene>(m_localScenes.FindAll(delegate(Scene s) { return true; })); }
104 } 108 }
105 109
106 public Scene CurrentScene 110 /// <summary>
107 { 111 /// Scene selected from the console.
108 get { return m_currentScene; } 112 /// </summary>
109 } 113 /// <value>
114 /// If null, then all scenes are considered selected (signalled as "Root" on the console).
115 /// </value>
116 public Scene CurrentScene { get; private set; }
110 117
111 public Scene CurrentOrFirstScene 118 public Scene CurrentOrFirstScene
112 { 119 {
113 get 120 get
114 { 121 {
115 if (m_currentScene == null) 122 if (CurrentScene == null)
116 { 123 {
117 List<Scene> sceneList = Scenes; 124 List<Scene> sceneList = Scenes;
118 if (sceneList.Count == 0) 125 if (sceneList.Count == 0)
@@ -121,7 +128,7 @@ namespace OpenSim.Region.Framework.Scenes
121 } 128 }
122 else 129 else
123 { 130 {
124 return m_currentScene; 131 return CurrentScene;
125 } 132 }
126 } 133 }
127 } 134 }
@@ -134,31 +141,17 @@ namespace OpenSim.Region.Framework.Scenes
134 141
135 public void Close() 142 public void Close()
136 { 143 {
137 // collect known shared modules in sharedModules 144 List<Scene> localScenes = null;
138 Dictionary<string, IRegionModule> sharedModules = new Dictionary<string, IRegionModule>();
139 145
140 List<Scene> sceneList = Scenes; 146 lock (m_localScenes)
141 for (int i = 0; i < sceneList.Count; i++)
142 { 147 {
143 // extract known shared modules from scene 148 localScenes = Scenes;
144 foreach (string k in sceneList[i].Modules.Keys)
145 {
146 if (sceneList[i].Modules[k].IsSharedModule &&
147 !sharedModules.ContainsKey(k))
148 sharedModules[k] = sceneList[i].Modules[k];
149 }
150 // close scene/region
151 sceneList[i].Close();
152 } 149 }
153 150
154 // all regions/scenes are now closed, we can now safely 151 for (int i = 0; i < localScenes.Count; i++)
155 // close all shared modules
156 foreach (IRegionModule mod in sharedModules.Values)
157 { 152 {
158 mod.Close(); 153 localScenes[i].Close();
159 } 154 }
160
161 m_localScenes.Clear();
162 } 155 }
163 156
164 public void Close(Scene cscene) 157 public void Close(Scene cscene)
@@ -179,11 +172,18 @@ namespace OpenSim.Region.Framework.Scenes
179 172
180 public void HandleRestart(RegionInfo rdata) 173 public void HandleRestart(RegionInfo rdata)
181 { 174 {
182 m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main"); 175 Scene restartedScene = null;
183 int RegionSceneElement = -1;
184 176
185 lock (m_localScenes) 177 lock (m_localScenes)
178 {
179 m_localScenes.TryGetValue(rdata.RegionID, out restartedScene);
186 m_localScenes.Remove(rdata.RegionID); 180 m_localScenes.Remove(rdata.RegionID);
181 }
182
183 // If the currently selected scene has been restarted, then we can't reselect here since we the scene
184 // hasn't yet been recreated. We will have to leave this to the caller.
185 if (CurrentScene == restartedScene)
186 CurrentScene = null;
187 187
188 // Send signal to main that we're restarting this sim. 188 // Send signal to main that we're restarting this sim.
189 OnRestartSim(rdata); 189 OnRestartSim(rdata);
@@ -323,14 +323,14 @@ namespace OpenSim.Region.Framework.Scenes
323 323
324 private void ForEachCurrentScene(Action<Scene> func) 324 private void ForEachCurrentScene(Action<Scene> func)
325 { 325 {
326 if (m_currentScene == null) 326 if (CurrentScene == null)
327 { 327 {
328 List<Scene> sceneList = Scenes; 328 List<Scene> sceneList = Scenes;
329 sceneList.ForEach(func); 329 sceneList.ForEach(func);
330 } 330 }
331 else 331 else
332 { 332 {
333 func(m_currentScene); 333 func(CurrentScene);
334 } 334 }
335 } 335 }
336 336
@@ -350,7 +350,7 @@ namespace OpenSim.Region.Framework.Scenes
350 || (String.Compare(regionName, "..") == 0) 350 || (String.Compare(regionName, "..") == 0)
351 || (String.Compare(regionName, "/") == 0)) 351 || (String.Compare(regionName, "/") == 0))
352 { 352 {
353 m_currentScene = null; 353 CurrentScene = null;
354 return true; 354 return true;
355 } 355 }
356 else 356 else
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index e94ecee..b9f9c86 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -2752,6 +2752,25 @@ namespace OpenSim.Region.Framework.Scenes
2752 if (objectGroup == this) 2752 if (objectGroup == this)
2753 return; 2753 return;
2754 2754
2755 // If the configured linkset capacity is greater than zero,
2756 // and the new linkset would have a prim count higher than this
2757 // value, do not link it.
2758 if (m_scene.m_linksetCapacity > 0 &&
2759 (PrimCount + objectGroup.PrimCount) >
2760 m_scene.m_linksetCapacity)
2761 {
2762 m_log.DebugFormat(
2763 "[SCENE OBJECT GROUP]: Cannot link group with root" +
2764 " part {0}, {1} ({2} prims) to group with root part" +
2765 " {3}, {4} ({5} prims) because the new linkset" +
2766 " would exceed the configured maximum of {6}",
2767 objectGroup.RootPart.Name, objectGroup.RootPart.UUID,
2768 objectGroup.PrimCount, RootPart.Name, RootPart.UUID,
2769 PrimCount, m_scene.m_linksetCapacity);
2770
2771 return;
2772 }
2773
2755 // 'linkPart' == the root of the group being linked into this group 2774 // 'linkPart' == the root of the group being linked into this group
2756 SceneObjectPart linkPart = objectGroup.m_rootPart; 2775 SceneObjectPart linkPart = objectGroup.m_rootPart;
2757 2776
@@ -3497,27 +3516,33 @@ namespace OpenSim.Region.Framework.Scenes
3497 /// <param name="scale"></param> 3516 /// <param name="scale"></param>
3498 public void GroupResize(Vector3 scale) 3517 public void GroupResize(Vector3 scale)
3499 { 3518 {
3500 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3519// m_log.DebugFormat(
3501 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); 3520// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
3502 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
3503 3521
3504 PhysicsActor pa = m_rootPart.PhysActor; 3522 PhysicsActor pa = m_rootPart.PhysActor;
3505 3523
3506 if (pa != null && pa.IsPhysical) 3524 if (Scene != null)
3507 { 3525 {
3508 scale.X = Math.Min(scale.X, Scene.m_maxPhys); 3526 scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X));
3509 scale.Y = Math.Min(scale.Y, Scene.m_maxPhys); 3527 scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y));
3510 scale.Z = Math.Min(scale.Z, Scene.m_maxPhys); 3528 scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z));
3529
3530 if (pa != null && pa.IsPhysical)
3531 {
3532 scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X));
3533 scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y));
3534 scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z));
3535 }
3511 } 3536 }
3512 3537
3513 float x = (scale.X / RootPart.Scale.X); 3538 float x = (scale.X / RootPart.Scale.X);
3514 float y = (scale.Y / RootPart.Scale.Y); 3539 float y = (scale.Y / RootPart.Scale.Y);
3515 float z = (scale.Z / RootPart.Scale.Z); 3540 float z = (scale.Z / RootPart.Scale.Z);
3516 3541
3517 SceneObjectPart[] parts; 3542 SceneObjectPart[] parts = m_parts.GetArray();
3518 if (x > 1.0f || y > 1.0f || z > 1.0f) 3543
3544 if (Scene != null & (x > 1.0f || y > 1.0f || z > 1.0f))
3519 { 3545 {
3520 parts = m_parts.GetArray();
3521 for (int i = 0; i < parts.Length; i++) 3546 for (int i = 0; i < parts.Length; i++)
3522 { 3547 {
3523 SceneObjectPart obPart = parts[i]; 3548 SceneObjectPart obPart = parts[i];
@@ -3530,7 +3555,7 @@ namespace OpenSim.Region.Framework.Scenes
3530 3555
3531 if (pa != null && pa.IsPhysical) 3556 if (pa != null && pa.IsPhysical)
3532 { 3557 {
3533 if (oldSize.X * x > m_scene.m_maxPhys) 3558 if (oldSize.X * x > Scene.m_maxPhys)
3534 { 3559 {
3535 f = m_scene.m_maxPhys / oldSize.X; 3560 f = m_scene.m_maxPhys / oldSize.X;
3536 a = f / x; 3561 a = f / x;
@@ -3538,8 +3563,16 @@ namespace OpenSim.Region.Framework.Scenes
3538 y *= a; 3563 y *= a;
3539 z *= a; 3564 z *= a;
3540 } 3565 }
3566 else if (oldSize.X * x < Scene.m_minPhys)
3567 {
3568 f = m_scene.m_minPhys / oldSize.X;
3569 a = f / x;
3570 x *= a;
3571 y *= a;
3572 z *= a;
3573 }
3541 3574
3542 if (oldSize.Y * y > m_scene.m_maxPhys) 3575 if (oldSize.Y * y > Scene.m_maxPhys)
3543 { 3576 {
3544 f = m_scene.m_maxPhys / oldSize.Y; 3577 f = m_scene.m_maxPhys / oldSize.Y;
3545 a = f / y; 3578 a = f / y;
@@ -3547,8 +3580,16 @@ namespace OpenSim.Region.Framework.Scenes
3547 y *= a; 3580 y *= a;
3548 z *= a; 3581 z *= a;
3549 } 3582 }
3583 else if (oldSize.Y * y < Scene.m_minPhys)
3584 {
3585 f = m_scene.m_minPhys / oldSize.Y;
3586 a = f / y;
3587 x *= a;
3588 y *= a;
3589 z *= a;
3590 }
3550 3591
3551 if (oldSize.Z * z > m_scene.m_maxPhys) 3592 if (oldSize.Z * z > Scene.m_maxPhys)
3552 { 3593 {
3553 f = m_scene.m_maxPhys / oldSize.Z; 3594 f = m_scene.m_maxPhys / oldSize.Z;
3554 a = f / z; 3595 a = f / z;
@@ -3556,10 +3597,18 @@ namespace OpenSim.Region.Framework.Scenes
3556 y *= a; 3597 y *= a;
3557 z *= a; 3598 z *= a;
3558 } 3599 }
3600 else if (oldSize.Z * z < Scene.m_minPhys)
3601 {
3602 f = m_scene.m_minPhys / oldSize.Z;
3603 a = f / z;
3604 x *= a;
3605 y *= a;
3606 z *= a;
3607 }
3559 } 3608 }
3560 else 3609 else
3561 { 3610 {
3562 if (oldSize.X * x > m_scene.m_maxNonphys) 3611 if (oldSize.X * x > Scene.m_maxNonphys)
3563 { 3612 {
3564 f = m_scene.m_maxNonphys / oldSize.X; 3613 f = m_scene.m_maxNonphys / oldSize.X;
3565 a = f / x; 3614 a = f / x;
@@ -3567,8 +3616,16 @@ namespace OpenSim.Region.Framework.Scenes
3567 y *= a; 3616 y *= a;
3568 z *= a; 3617 z *= a;
3569 } 3618 }
3619 else if (oldSize.X * x < Scene.m_minNonphys)
3620 {
3621 f = m_scene.m_minNonphys / oldSize.X;
3622 a = f / x;
3623 x *= a;
3624 y *= a;
3625 z *= a;
3626 }
3570 3627
3571 if (oldSize.Y * y > m_scene.m_maxNonphys) 3628 if (oldSize.Y * y > Scene.m_maxNonphys)
3572 { 3629 {
3573 f = m_scene.m_maxNonphys / oldSize.Y; 3630 f = m_scene.m_maxNonphys / oldSize.Y;
3574 a = f / y; 3631 a = f / y;
@@ -3576,8 +3633,16 @@ namespace OpenSim.Region.Framework.Scenes
3576 y *= a; 3633 y *= a;
3577 z *= a; 3634 z *= a;
3578 } 3635 }
3636 else if (oldSize.Y * y < Scene.m_minNonphys)
3637 {
3638 f = m_scene.m_minNonphys / oldSize.Y;
3639 a = f / y;
3640 x *= a;
3641 y *= a;
3642 z *= a;
3643 }
3579 3644
3580 if (oldSize.Z * z > m_scene.m_maxNonphys) 3645 if (oldSize.Z * z > Scene.m_maxNonphys)
3581 { 3646 {
3582 f = m_scene.m_maxNonphys / oldSize.Z; 3647 f = m_scene.m_maxNonphys / oldSize.Z;
3583 a = f / z; 3648 a = f / z;
@@ -3585,6 +3650,14 @@ namespace OpenSim.Region.Framework.Scenes
3585 y *= a; 3650 y *= a;
3586 z *= a; 3651 z *= a;
3587 } 3652 }
3653 else if (oldSize.Z * z < Scene.m_minNonphys)
3654 {
3655 f = m_scene.m_minNonphys / oldSize.Z;
3656 a = f / z;
3657 x *= a;
3658 y *= a;
3659 z *= a;
3660 }
3588 } 3661 }
3589 } 3662 }
3590 } 3663 }
@@ -3597,7 +3670,6 @@ namespace OpenSim.Region.Framework.Scenes
3597 3670
3598 RootPart.Resize(prevScale); 3671 RootPart.Resize(prevScale);
3599 3672
3600 parts = m_parts.GetArray();
3601 for (int i = 0; i < parts.Length; i++) 3673 for (int i = 0; i < parts.Length; i++)
3602 { 3674 {
3603 SceneObjectPart obPart = parts[i]; 3675 SceneObjectPart obPart = parts[i];
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 49b771f..2191cfa 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -790,7 +790,7 @@ namespace OpenSim.Region.Framework.Scenes
790 } 790 }
791 catch (Exception e) 791 catch (Exception e)
792 { 792 {
793 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 793 m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e);
794 } 794 }
795 } 795 }
796 } 796 }
@@ -813,7 +813,7 @@ namespace OpenSim.Region.Framework.Scenes
813 actor.Orientation = GetWorldRotation(); 813 actor.Orientation = GetWorldRotation();
814 814
815 // Tell the physics engines that this prim changed. 815 // Tell the physics engines that this prim changed.
816 if (ParentGroup.Scene != null) 816 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
817 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 817 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
818 } 818 }
819 819
@@ -2864,6 +2864,35 @@ namespace OpenSim.Region.Framework.Scenes
2864 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2864 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2865 } 2865 }
2866 2866
2867 // The Collision sounds code calls this
2868 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
2869 {
2870 if (soundID == UUID.Zero)
2871 return;
2872
2873 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
2874 if (soundModule == null)
2875 return;
2876
2877 if (volume > 1)
2878 volume = 1;
2879 if (volume < 0)
2880 volume = 0;
2881
2882 int now = Util.EnvironmentTickCount();
2883 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
2884 return;
2885
2886 LastColSoundSentTime = now;
2887
2888 UUID ownerID = OwnerID;
2889 UUID objectID = ParentGroup.RootPart.UUID;
2890 UUID parentID = ParentGroup.UUID;
2891 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
2892
2893 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
2894 }
2895
2867 public void PhysicsOutOfBounds(Vector3 pos) 2896 public void PhysicsOutOfBounds(Vector3 pos)
2868 { 2897 {
2869 m_log.Error("[PHYSICS]: Physical Object went out of bounds."); 2898 m_log.Error("[PHYSICS]: Physical Object went out of bounds.");
@@ -2895,38 +2924,6 @@ namespace OpenSim.Region.Framework.Scenes
2895 ScheduleTerseUpdate(); 2924 ScheduleTerseUpdate();
2896 } 2925 }
2897 2926
2898 public void PreloadSound(string sound)
2899 {
2900 // UUID ownerID = OwnerID;
2901 UUID objectID = ParentGroup.RootPart.UUID;
2902 UUID soundID = UUID.Zero;
2903
2904 if (!UUID.TryParse(sound, out soundID))
2905 {
2906 //Trys to fetch sound id from prim's inventory.
2907 //Prim's inventory doesn't support non script items yet
2908
2909 TaskInventory.LockItemsForRead(true);
2910
2911 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2912 {
2913 if (item.Value.Name == sound)
2914 {
2915 soundID = item.Value.ItemID;
2916 break;
2917 }
2918 }
2919
2920 TaskInventory.LockItemsForRead(false);
2921 }
2922
2923 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
2924 {
2925 if (!(Util.GetDistanceTo(sp.AbsolutePosition, AbsolutePosition) >= 100))
2926 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
2927 });
2928 }
2929
2930 public void RemFlag(PrimFlags flag) 2927 public void RemFlag(PrimFlags flag)
2931 { 2928 {
2932 // PrimFlags prevflag = Flags; 2929 // PrimFlags prevflag = Flags;
@@ -2979,17 +2976,20 @@ namespace OpenSim.Region.Framework.Scenes
2979 /// <param name="scale"></param> 2976 /// <param name="scale"></param>
2980 public void Resize(Vector3 scale) 2977 public void Resize(Vector3 scale)
2981 { 2978 {
2982 scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys);
2983 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys);
2984 scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys);
2985
2986 PhysicsActor pa = PhysActor; 2979 PhysicsActor pa = PhysActor;
2987 2980
2988 if (pa != null && pa.IsPhysical) 2981 if (ParentGroup.Scene != null)
2989 { 2982 {
2990 scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys); 2983 scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X));
2991 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys); 2984 scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y));
2992 scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys); 2985 scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z));
2986
2987 if (pa != null && pa.IsPhysical)
2988 {
2989 scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X));
2990 scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y));
2991 scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z));
2992 }
2993 } 2993 }
2994 2994
2995// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); 2995// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
@@ -3086,7 +3086,7 @@ namespace OpenSim.Region.Framework.Scenes
3086 // UUID, Name, TimeStampFull); 3086 // UUID, Name, TimeStampFull);
3087 3087
3088 if (ParentGroup.Scene != null) 3088 if (ParentGroup.Scene != null)
3089 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this); 3089 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true);
3090 } 3090 }
3091 3091
3092 /// <summary> 3092 /// <summary>
@@ -3120,7 +3120,7 @@ namespace OpenSim.Region.Framework.Scenes
3120 } 3120 }
3121 3121
3122 if (ParentGroup.Scene != null) 3122 if (ParentGroup.Scene != null)
3123 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this); 3123 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false);
3124 } 3124 }
3125 3125
3126 public void ScriptSetPhysicsStatus(bool UsePhysics) 3126 public void ScriptSetPhysicsStatus(bool UsePhysics)
@@ -3295,126 +3295,6 @@ namespace OpenSim.Region.Framework.Scenes
3295 } 3295 }
3296 3296
3297 /// <summary> 3297 /// <summary>
3298 /// Trigger or play an attached sound in this part's inventory.
3299 /// </summary>
3300 /// <param name="sound"></param>
3301 /// <param name="volume"></param>
3302 /// <param name="triggered"></param>
3303 /// <param name="flags"></param>
3304 public void SendSound(string sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster)
3305 {
3306 if (volume > 1)
3307 volume = 1;
3308 if (volume < 0)
3309 volume = 0;
3310
3311 UUID ownerID = OwnerID;
3312 UUID objectID = ParentGroup.RootPart.UUID;
3313 UUID parentID = ParentGroup.UUID;
3314
3315 UUID soundID = UUID.Zero;
3316 Vector3 position = AbsolutePosition; // region local
3317 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3318
3319 if (!UUID.TryParse(sound, out soundID))
3320 {
3321 // search sound file from inventory
3322 TaskInventory.LockItemsForRead(true);
3323 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3324 {
3325 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3326 {
3327 soundID = item.Value.ItemID;
3328 break;
3329 }
3330 }
3331 TaskInventory.LockItemsForRead(false);
3332 }
3333
3334 if (soundID == UUID.Zero)
3335 return;
3336
3337 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
3338 if (soundModule != null)
3339 {
3340 if (useMaster)
3341 {
3342 if (isMaster)
3343 {
3344 if (triggered)
3345 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
3346 else
3347 soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
3348 ParentGroup.PlaySoundMasterPrim = this;
3349 ownerID = OwnerID;
3350 objectID = ParentGroup.RootPart.UUID;
3351 parentID = ParentGroup.UUID;
3352 position = AbsolutePosition; // region local
3353 regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3354 if (triggered)
3355 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
3356 else
3357 soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
3358 foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims)
3359 {
3360 ownerID = prim.OwnerID;
3361 objectID = prim.ParentGroup.RootPart.UUID;
3362 parentID = prim.ParentGroup.UUID;
3363 position = prim.AbsolutePosition; // region local
3364 regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle;
3365 if (triggered)
3366 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
3367 else
3368 soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
3369 }
3370 ParentGroup.PlaySoundSlavePrims.Clear();
3371 ParentGroup.PlaySoundMasterPrim = null;
3372 }
3373 else
3374 {
3375 ParentGroup.PlaySoundSlavePrims.Add(this);
3376 }
3377 }
3378 else
3379 {
3380 if (triggered)
3381 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
3382 else
3383 soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
3384 }
3385 }
3386 }
3387
3388 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
3389 {
3390 if (soundID == UUID.Zero)
3391 return;
3392
3393 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
3394 if (soundModule == null)
3395 return;
3396
3397 if (volume > 1)
3398 volume = 1;
3399 if (volume < 0)
3400 volume = 0;
3401
3402 int now = Util.EnvironmentTickCount();
3403 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
3404 return;
3405
3406 LastColSoundSentTime = now;
3407
3408 UUID ownerID = OwnerID;
3409 UUID objectID = ParentGroup.RootPart.UUID;
3410 UUID parentID = ParentGroup.UUID;
3411 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3412
3413 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
3414 }
3415
3416
3417 /// <summary>
3418 /// Send a terse update to all clients 3298 /// Send a terse update to all clients
3419 /// </summary> 3299 /// </summary>
3420 public void SendTerseUpdateToAllClients() 3300 public void SendTerseUpdateToAllClients()
@@ -3575,23 +3455,32 @@ namespace OpenSim.Region.Framework.Scenes
3575 } 3455 }
3576 3456
3577 /// <summary> 3457 /// <summary>
3578 /// Set the color of prim faces 3458 /// Set the color & alpha of prim faces
3579 /// </summary> 3459 /// </summary>
3580 /// <param name="color"></param>
3581 /// <param name="face"></param> 3460 /// <param name="face"></param>
3582 public void SetFaceColor(Vector3 color, int face) 3461 /// <param name="color"></param>
3462 /// <param name="alpha"></param>
3463 public void SetFaceColorAlpha(int face, Vector3 color, double ?alpha)
3583 { 3464 {
3465 Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f);
3466 float clippedAlpha = alpha.HasValue ?
3467 Util.Clip((float)alpha.Value, 0.0f, 1.0f) : 0;
3468
3584 // The only way to get a deep copy/ If we don't do this, we can 3469 // The only way to get a deep copy/ If we don't do this, we can
3585 // mever detect color changes further down. 3470 // never detect color changes further down.
3586 Byte[] buf = Shape.Textures.GetBytes(); 3471 Byte[] buf = Shape.Textures.GetBytes();
3587 Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); 3472 Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length);
3588 Color4 texcolor; 3473 Color4 texcolor;
3589 if (face >= 0 && face < GetNumberOfSides()) 3474 if (face >= 0 && face < GetNumberOfSides())
3590 { 3475 {
3591 texcolor = tex.CreateFace((uint)face).RGBA; 3476 texcolor = tex.CreateFace((uint)face).RGBA;
3592 texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); 3477 texcolor.R = clippedColor.X;
3593 texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); 3478 texcolor.G = clippedColor.Y;
3594 texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); 3479 texcolor.B = clippedColor.Z;
3480 if (alpha.HasValue)
3481 {
3482 texcolor.A = clippedAlpha;
3483 }
3595 tex.FaceTextures[face].RGBA = texcolor; 3484 tex.FaceTextures[face].RGBA = texcolor;
3596 UpdateTextureEntry(tex.GetBytes()); 3485 UpdateTextureEntry(tex.GetBytes());
3597 return; 3486 return;
@@ -3603,15 +3492,23 @@ namespace OpenSim.Region.Framework.Scenes
3603 if (tex.FaceTextures[i] != null) 3492 if (tex.FaceTextures[i] != null)
3604 { 3493 {
3605 texcolor = tex.FaceTextures[i].RGBA; 3494 texcolor = tex.FaceTextures[i].RGBA;
3606 texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); 3495 texcolor.R = clippedColor.X;
3607 texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); 3496 texcolor.G = clippedColor.Y;
3608 texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); 3497 texcolor.B = clippedColor.Z;
3498 if (alpha.HasValue)
3499 {
3500 texcolor.A = clippedAlpha;
3501 }
3609 tex.FaceTextures[i].RGBA = texcolor; 3502 tex.FaceTextures[i].RGBA = texcolor;
3610 } 3503 }
3611 texcolor = tex.DefaultTexture.RGBA; 3504 texcolor = tex.DefaultTexture.RGBA;
3612 texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); 3505 texcolor.R = clippedColor.X;
3613 texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); 3506 texcolor.G = clippedColor.Y;
3614 texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); 3507 texcolor.B = clippedColor.Z;
3508 if (alpha.HasValue)
3509 {
3510 texcolor.A = clippedAlpha;
3511 }
3615 tex.DefaultTexture.RGBA = texcolor; 3512 tex.DefaultTexture.RGBA = texcolor;
3616 } 3513 }
3617 UpdateTextureEntry(tex.GetBytes()); 3514 UpdateTextureEntry(tex.GetBytes());
@@ -4899,6 +4796,57 @@ namespace OpenSim.Region.Framework.Scenes
4899 ScheduleFullUpdate(); 4796 ScheduleFullUpdate();
4900 } 4797 }
4901 4798
4799 public void UpdateSlice(float begin, float end)
4800 {
4801 if (end < begin)
4802 {
4803 float temp = begin;
4804 begin = end;
4805 end = temp;
4806 }
4807 end = Math.Min(1f, Math.Max(0f, end));
4808 begin = Math.Min(Math.Min(1f, Math.Max(0f, begin)), end - 0.02f);
4809 if (begin < 0.02f && end < 0.02f)
4810 {
4811 begin = 0f;
4812 end = 0.02f;
4813 }
4814
4815 ushort uBegin = (ushort)(50000.0 * begin);
4816 ushort uEnd = (ushort)(50000.0 * (1f - end));
4817 bool updatePossiblyNeeded = false;
4818 PrimType primType = GetPrimType();
4819 if (primType == PrimType.SPHERE || primType == PrimType.TORUS || primType == PrimType.TUBE || primType == PrimType.RING)
4820 {
4821 if (m_shape.ProfileBegin != uBegin || m_shape.ProfileEnd != uEnd)
4822 {
4823 m_shape.ProfileBegin = uBegin;
4824 m_shape.ProfileEnd = uEnd;
4825 updatePossiblyNeeded = true;
4826 }
4827 }
4828 else if (m_shape.PathBegin != uBegin || m_shape.PathEnd != uEnd)
4829 {
4830 m_shape.PathBegin = uBegin;
4831 m_shape.PathEnd = uEnd;
4832 updatePossiblyNeeded = true;
4833 }
4834
4835 if (updatePossiblyNeeded && ParentGroup != null)
4836 {
4837 ParentGroup.HasGroupChanged = true;
4838 }
4839 if (updatePossiblyNeeded && PhysActor != null)
4840 {
4841 PhysActor.Shape = m_shape;
4842 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
4843 }
4844 if (updatePossiblyNeeded)
4845 {
4846 ScheduleFullUpdate();
4847 }
4848 }
4849
4902 /// <summary> 4850 /// <summary>
4903 /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics 4851 /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics
4904 /// engine can use it. 4852 /// engine can use it.
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index e010864..3a9a146 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -97,6 +97,15 @@ namespace OpenSim.Region.Framework.Scenes
97 QueryScriptStates(); 97 QueryScriptStates();
98 } 98 }
99 } 99 }
100
101 public int Count
102 {
103 get
104 {
105 lock (m_items)
106 return m_items.Count;
107 }
108 }
100 109
101 /// <summary> 110 /// <summary>
102 /// Constructor 111 /// Constructor
@@ -235,31 +244,52 @@ namespace OpenSim.Region.Framework.Scenes
235 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) 244 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null)
236 return; 245 return;
237 246
238 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
239 if (engines == null) // No engine at all
240 return;
241
242 Items.LockItemsForRead(true); 247 Items.LockItemsForRead(true);
243 foreach (TaskInventoryItem item in Items.Values) 248 foreach (TaskInventoryItem item in Items.Values)
244 { 249 {
245 if (item.InvType == (int)InventoryType.LSL) 250 if (item.InvType == (int)InventoryType.LSL)
246 { 251 {
247 foreach (IScriptModule e in engines) 252 bool running;
248 { 253 if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running))
249 bool running; 254 item.ScriptRunning = running;
250
251 if (e.HasScript(item.ItemID, out running))
252 {
253 item.ScriptRunning = running;
254 break;
255 }
256 }
257 } 255 }
258 } 256 }
259 257
260 Items.LockItemsForRead(false); 258 Items.LockItemsForRead(false);
261 } 259 }
262 260
261 public bool TryGetScriptInstanceRunning(UUID itemId, out bool running)
262 {
263 running = false;
264
265 TaskInventoryItem item = GetInventoryItem(itemId);
266
267 if (item == null)
268 return false;
269
270 return TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running);
271 }
272
273 public static bool TryGetScriptInstanceRunning(Scene scene, TaskInventoryItem item, out bool running)
274 {
275 running = false;
276
277 if (item.InvType != (int)InventoryType.LSL)
278 return false;
279
280 IScriptModule[] engines = scene.RequestModuleInterfaces<IScriptModule>();
281 if (engines == null) // No engine at all
282 return false;
283
284 foreach (IScriptModule e in engines)
285 {
286 if (e.HasScript(item.ItemID, out running))
287 return true;
288 }
289
290 return false;
291 }
292
263 public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 293 public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
264 { 294 {
265 int scriptsValidForStarting = 0; 295 int scriptsValidForStarting = 0;
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a8aa551..bacc9c9 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -69,14 +69,15 @@ namespace OpenSim.Region.Framework.Scenes
69 public ScriptControlled eventControls; 69 public ScriptControlled eventControls;
70 } 70 }
71 71
72 public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs); 72 public delegate void SendCoarseLocationsMethod(UUID scene, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs);
73 73
74 public class ScenePresence : EntityBase, IScenePresence 74 public class ScenePresence : EntityBase, IScenePresence
75 { 75 {
76// ~ScenePresence() 76// ~ScenePresence()
77// { 77// {
78// m_log.Debug("[SCENE PRESENCE] Destructor called"); 78// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
79// } 79// }
80
80 private void TriggerScenePresenceUpdated() 81 private void TriggerScenePresenceUpdated()
81 { 82 {
82 if (m_scene != null) 83 if (m_scene != null)
@@ -188,7 +189,7 @@ namespace OpenSim.Region.Framework.Scenes
188 /// </summary> 189 /// </summary>
189 public bool SitGround { get; private set; } 190 public bool SitGround { get; private set; }
190 191
191 private SendCourseLocationsMethod m_sendCourseLocationsMethod; 192 private SendCoarseLocationsMethod m_sendCoarseLocationsMethod;
192 193
193 //private Vector3 m_requestedSitOffset = new Vector3(); 194 //private Vector3 m_requestedSitOffset = new Vector3();
194 195
@@ -546,7 +547,7 @@ namespace OpenSim.Region.Framework.Scenes
546 { 547 {
547 try 548 try
548 { 549 {
549 PhysicsActor.Velocity = value; 550 PhysicsActor.TargetVelocity = value;
550 } 551 }
551 catch (Exception e) 552 catch (Exception e)
552 { 553 {
@@ -570,7 +571,18 @@ namespace OpenSim.Region.Framework.Scenes
570 set 571 set
571 { 572 {
572 m_bodyRot = value; 573 m_bodyRot = value;
573// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot); 574 // m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot);
575 if (PhysicsActor != null)
576 {
577 try
578 {
579 PhysicsActor.Orientation = value;
580 }
581 catch (Exception e)
582 {
583 m_log.Error("[SCENE PRESENCE]: Orientation " + e.Message);
584 }
585 }
574 } 586 }
575 } 587 }
576 588
@@ -711,7 +723,7 @@ namespace OpenSim.Region.Framework.Scenes
711 AttachmentsSyncLock = new Object(); 723 AttachmentsSyncLock = new Object();
712 AllowMovement = true; 724 AllowMovement = true;
713 IsChildAgent = true; 725 IsChildAgent = true;
714 m_sendCourseLocationsMethod = SendCoarseLocationsDefault; 726 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault;
715 Animator = new ScenePresenceAnimator(this); 727 Animator = new ScenePresenceAnimator(this);
716 PresenceType = type; 728 PresenceType = type;
717 DrawDistance = world.DefaultDrawDistance; 729 DrawDistance = world.DefaultDrawDistance;
@@ -793,6 +805,7 @@ namespace OpenSim.Region.Framework.Scenes
793 ControllingClient.OnChangeAnim += avnHandleChangeAnim; 805 ControllingClient.OnChangeAnim += avnHandleChangeAnim;
794 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; 806 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls;
795 ControllingClient.OnAutoPilotGo += MoveToTarget; 807 ControllingClient.OnAutoPilotGo += MoveToTarget;
808 ControllingClient.OnUpdateThrottles += RaiseUpdateThrottles;
796 809
797 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); 810 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
798 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); 811 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
@@ -974,7 +987,9 @@ namespace OpenSim.Region.Framework.Scenes
974 { 987 {
975 if (wasChild && HasAttachments()) 988 if (wasChild && HasAttachments())
976 { 989 {
977 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); 990 m_log.DebugFormat(
991 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
992
978 // Resume scripts 993 // Resume scripts
979 Util.FireAndForget(delegate(object x) { 994 Util.FireAndForget(delegate(object x) {
980 foreach (SceneObjectGroup sog in m_attachments) 995 foreach (SceneObjectGroup sog in m_attachments)
@@ -1530,17 +1545,22 @@ namespace OpenSim.Region.Framework.Scenes
1530 bool DCFlagKeyPressed = false; 1545 bool DCFlagKeyPressed = false;
1531 Vector3 agent_control_v3 = Vector3.Zero; 1546 Vector3 agent_control_v3 = Vector3.Zero;
1532 1547
1533 bool oldflying = Flying; 1548 bool newFlying = actor.Flying;
1534 1549
1535 if (ForceFly) 1550 if (ForceFly)
1536 actor.Flying = true; 1551 newFlying = true;
1537 else if (FlyDisabled) 1552 else if (FlyDisabled)
1538 actor.Flying = false; 1553 newFlying = false;
1539 else 1554 else
1540 actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1555 newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1541 1556
1542 if (actor.Flying != oldflying) 1557 if (actor.Flying != newFlying)
1558 {
1559 // Note: ScenePresence.Flying is actually fetched from the physical actor
1560 // so setting PhysActor.Flying here also sets the ScenePresence's value.
1561 actor.Flying = newFlying;
1543 update_movementflag = true; 1562 update_movementflag = true;
1563 }
1544 1564
1545 if (ParentID == 0) 1565 if (ParentID == 0)
1546 { 1566 {
@@ -1835,8 +1855,16 @@ namespace OpenSim.Region.Framework.Scenes
1835// "[SCENE PRESENCE]: Avatar {0} received request to move to position {1} in {2}", 1855// "[SCENE PRESENCE]: Avatar {0} received request to move to position {1} in {2}",
1836// Name, pos, m_scene.RegionInfo.RegionName); 1856// Name, pos, m_scene.RegionInfo.RegionName);
1837 1857
1838 if (pos.X < 0 || pos.X >= Constants.RegionSize 1858 // Allow move to another sub-region within a megaregion
1839 || pos.Y < 0 || pos.Y >= Constants.RegionSize 1859 Vector2 regionSize;
1860 IRegionCombinerModule regionCombinerModule = m_scene.RequestModuleInterface<IRegionCombinerModule>();
1861 if (regionCombinerModule != null)
1862 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
1863 else
1864 regionSize = new Vector2(Constants.RegionSize);
1865
1866 if (pos.X < 0 || pos.X >= regionSize.X
1867 || pos.Y < 0 || pos.Y >= regionSize.Y
1840 || pos.Z < 0) 1868 || pos.Z < 0)
1841 return; 1869 return;
1842 1870
@@ -1850,7 +1878,16 @@ namespace OpenSim.Region.Framework.Scenes
1850// pos.Z = AbsolutePosition.Z; 1878// pos.Z = AbsolutePosition.Z;
1851// } 1879// }
1852 1880
1853 float terrainHeight = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1881 // Get terrain height for sub-region in a megaregion if necessary
1882 int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X);
1883 int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y);
1884 UUID target_regionID = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y).RegionID;
1885 Scene targetScene = m_scene;
1886
1887 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
1888 targetScene = m_scene;
1889
1890 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)];
1854 pos.Z = Math.Max(terrainHeight, pos.Z); 1891 pos.Z = Math.Max(terrainHeight, pos.Z);
1855 1892
1856 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 1893 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -2622,17 +2659,17 @@ namespace OpenSim.Region.Framework.Scenes
2622 2659
2623 public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs) 2660 public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
2624 { 2661 {
2625 SendCourseLocationsMethod d = m_sendCourseLocationsMethod; 2662 SendCoarseLocationsMethod d = m_sendCoarseLocationsMethod;
2626 if (d != null) 2663 if (d != null)
2627 { 2664 {
2628 d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); 2665 d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs);
2629 } 2666 }
2630 } 2667 }
2631 2668
2632 public void SetSendCourseLocationMethod(SendCourseLocationsMethod d) 2669 public void SetSendCoarseLocationMethod(SendCoarseLocationsMethod d)
2633 { 2670 {
2634 if (d != null) 2671 if (d != null)
2635 m_sendCourseLocationsMethod = d; 2672 m_sendCoarseLocationsMethod = d;
2636 } 2673 }
2637 2674
2638 public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List<Vector3> coarseLocations, List<UUID> avatarUUIDs) 2675 public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
@@ -2836,7 +2873,7 @@ namespace OpenSim.Region.Framework.Scenes
2836 #region Significant Movement Method 2873 #region Significant Movement Method
2837 2874
2838 /// <summary> 2875 /// <summary>
2839 /// This checks for a significant movement and sends a courselocationchange update 2876 /// This checks for a significant movement and sends a coarselocationchange update
2840 /// </summary> 2877 /// </summary>
2841 protected void CheckForSignificantMovement() 2878 protected void CheckForSignificantMovement()
2842 { 2879 {
@@ -3166,6 +3203,10 @@ namespace OpenSim.Region.Framework.Scenes
3166 } 3203 }
3167 3204
3168 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 3205 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
3206 private void RaiseUpdateThrottles()
3207 {
3208 m_scene.EventManager.TriggerThrottleUpdate(this);
3209 }
3169 /// <summary> 3210 /// <summary>
3170 /// This updates important decision making data about a child agent 3211 /// This updates important decision making data about a child agent
3171 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region 3212 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
@@ -3269,6 +3310,7 @@ namespace OpenSim.Region.Framework.Scenes
3269 } 3310 }
3270 catch { } 3311 catch { }
3271 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; 3312 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
3313 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation;
3272 3314
3273 if (Scene.AttachmentsModule != null) 3315 if (Scene.AttachmentsModule != null)
3274 Scene.AttachmentsModule.CopyAttachments(this, cAgent); 3316 Scene.AttachmentsModule.CopyAttachments(this, cAgent);
@@ -3345,6 +3387,8 @@ namespace OpenSim.Region.Framework.Scenes
3345 Animator.Animations.FromArray(cAgent.Anims); 3387 Animator.Animations.FromArray(cAgent.Anims);
3346 if (cAgent.DefaultAnim != null) 3388 if (cAgent.DefaultAnim != null)
3347 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); 3389 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
3390 if (cAgent.AnimState != null)
3391 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
3348 3392
3349 if (Scene.AttachmentsModule != null) 3393 if (Scene.AttachmentsModule != null)
3350 Scene.AttachmentsModule.CopyAttachments(cAgent, this); 3394 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
@@ -3402,7 +3446,7 @@ namespace OpenSim.Region.Framework.Scenes
3402 3446
3403 PhysicsActor = scene.AddAvatar( 3447 PhysicsActor = scene.AddAvatar(
3404 LocalId, Firstname + "." + Lastname, pVec, 3448 LocalId, Firstname + "." + Lastname, pVec,
3405 new Vector3(0f, 0f, Appearance.AvatarHeight), isFlying); 3449 new Vector3(0.45f, 0.6f, Appearance.AvatarHeight), isFlying);
3406 3450
3407 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3451 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3408 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3452 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
@@ -3627,13 +3671,16 @@ namespace OpenSim.Region.Framework.Scenes
3627 public List<SceneObjectGroup> GetAttachments(uint attachmentPoint) 3671 public List<SceneObjectGroup> GetAttachments(uint attachmentPoint)
3628 { 3672 {
3629 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>(); 3673 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
3630 3674
3631 lock (m_attachments) 3675 if (attachmentPoint >= 0)
3632 { 3676 {
3633 foreach (SceneObjectGroup so in m_attachments) 3677 lock (m_attachments)
3634 { 3678 {
3635 if (attachmentPoint == so.AttachmentPoint) 3679 foreach (SceneObjectGroup so in m_attachments)
3636 attachments.Add(so); 3680 {
3681 if (attachmentPoint == so.AttachmentPoint)
3682 attachments.Add(so);
3683 }
3637 } 3684 }
3638 } 3685 }
3639 3686
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 756b1f4..5398ab9 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -47,6 +47,7 @@ namespace OpenSim.Region.Framework.Scenes
47 = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 47 = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates"; 49 public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates";
50 public const string SlowFramesStatName = "SlowFrames";
50 51
51 public delegate void SendStatResult(SimStats stats); 52 public delegate void SendStatResult(SimStats stats);
52 53
@@ -129,6 +130,16 @@ namespace OpenSim.Region.Framework.Scenes
129 } 130 }
130 131
131 /// <summary> 132 /// <summary>
133 /// Number of frames that have taken longer to process than Scene.MIN_FRAME_TIME
134 /// </summary>
135 public Stat SlowFramesStat { get; private set; }
136
137 /// <summary>
138 /// The threshold at which we log a slow frame.
139 /// </summary>
140 public int SlowFramesStatReportThreshold { get; private set; }
141
142 /// <summary>
132 /// Extra sim statistics that are used by monitors but not sent to the client. 143 /// Extra sim statistics that are used by monitors but not sent to the client.
133 /// </summary> 144 /// </summary>
134 /// <value> 145 /// <value>
@@ -226,6 +237,24 @@ namespace OpenSim.Region.Framework.Scenes
226 237
227 if (StatsManager.SimExtraStats != null) 238 if (StatsManager.SimExtraStats != null)
228 OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; 239 OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket;
240
241 /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit
242 /// longer than ideal (which in itself is a concern).
243 SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.MinFrameTime * 1000 * 1.2);
244
245 SlowFramesStat
246 = new Stat(
247 "SlowFrames",
248 "Slow Frames",
249 "Number of frames where frame time has been significantly longer than the desired frame time.",
250 " frames",
251 "scene",
252 m_scene.Name,
253 StatType.Push,
254 null,
255 StatVerbosity.Info);
256
257 StatsManager.RegisterStat(SlowFramesStat);
229 } 258 }
230 259
231 public void Close() 260 public void Close()
@@ -443,6 +472,7 @@ namespace OpenSim.Region.Framework.Scenes
443 lock (m_lastReportedExtraSimStats) 472 lock (m_lastReportedExtraSimStats)
444 { 473 {
445 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; 474 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor;
475 m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value;
446 476
447 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); 477 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
448 478
@@ -563,6 +593,11 @@ namespace OpenSim.Region.Framework.Scenes
563 public void addFrameMS(int ms) 593 public void addFrameMS(int ms)
564 { 594 {
565 m_frameMS += ms; 595 m_frameMS += ms;
596
597 // At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit
598 // longer than ideal due to the inaccuracy of the Sleep in Scene.Update() (which in itself is a concern).
599 if (ms > SlowFramesStatReportThreshold)
600 SlowFramesStat.Value++;
566 } 601 }
567 602
568 public void addNetMS(int ms) 603 public void addNetMS(int ms)
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs
index fcb544f..ab56f4e 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs
@@ -27,31 +27,32 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30 30using System.Reflection;
31using System.Threading;
32using NUnit.Framework;
33using OpenMetaverse;
31using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Communications;
32using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
33using OpenSim.Services.Interfaces; 37using OpenSim.Services.Interfaces;
34using OpenMetaverse; 38using OpenSim.Tests.Common;
39using OpenSim.Tests.Common.Mock;
35 40
36namespace OpenSim.Region.CoreModules.Framework.InventoryAccess 41namespace OpenSim.Region.Framework.Scenes.Tests
37{ 42{
38 public class HGUuidGatherer : UuidGatherer 43 [TestFixture]
44 public class SceneManagerTests
39 { 45 {
40 protected string m_assetServerURL; 46 [Test]
41 protected HGAssetMapper m_assetMapper; 47 public void TestClose()
42
43 public HGUuidGatherer(HGAssetMapper assMap, IAssetService assetCache, string assetServerURL) : base(assetCache)
44 { 48 {
45 m_assetMapper = assMap; 49 TestHelpers.InMethod();
46 m_assetServerURL = assetServerURL;
47 }
48 50
49 protected override AssetBase GetAsset(UUID uuid) 51 SceneHelpers sh = new SceneHelpers();
50 { 52 Scene scene = sh.SetupScene();
51 if (string.Empty == m_assetServerURL) 53
52 return m_assetCache.Get(uuid.ToString()); 54 sh.SceneManager.Close();
53 else 55 Assert.That(scene.ShuttingDown, Is.True);
54 return m_assetMapper.FetchAsset(m_assetServerURL, uuid);
55 } 56 }
56 } 57 }
57} 58} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
index 3398a53..5b334c6 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
30using System.Threading; 31using System.Threading;
31using NUnit.Framework; 32using NUnit.Framework;
@@ -33,6 +34,7 @@ using OpenMetaverse;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Communications; 35using OpenSim.Framework.Communications;
35using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Services.Interfaces;
36using OpenSim.Tests.Common; 38using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock; 39using OpenSim.Tests.Common.Mock;
38 40
@@ -42,7 +44,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
42 /// Basic scene object tests (create, read and delete but not update). 44 /// Basic scene object tests (create, read and delete but not update).
43 /// </summary> 45 /// </summary>
44 [TestFixture] 46 [TestFixture]
45 public class SceneObjectBasicTests 47 public class SceneObjectBasicTests : OpenSimTestCase
46 { 48 {
47// [TearDown] 49// [TearDown]
48// public void TearDown() 50// public void TearDown()
@@ -237,38 +239,60 @@ namespace OpenSim.Region.Framework.Scenes.Tests
237 /// <summary> 239 /// <summary>
238 /// Test deleting an object asynchronously to user inventory. 240 /// Test deleting an object asynchronously to user inventory.
239 /// </summary> 241 /// </summary>
240 //[Test] 242// [Test]
241 //public void TestDeleteSceneObjectAsyncToUserInventory() 243 public void TestDeleteSceneObjectAsyncToUserInventory()
242 //{ 244 {
243 // TestHelper.InMethod(); 245 TestHelpers.InMethod();
244 // //log4net.Config.XmlConfigurator.Configure(); 246 TestHelpers.EnableLogging();
245 247
246 // UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001"); 248 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001");
247 // string myObjectName = "Fred"; 249 string myObjectName = "Fred";
248 250
249 // TestScene scene = SceneSetupHelpers.SetupScene(); 251 TestScene scene = new SceneHelpers().SetupScene();
250 // SceneObjectPart part = SceneSetupHelpers.AddSceneObject(scene, myObjectName); 252
251 253 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
252 // Assert.That( 254 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
253 // scene.CommsManager.UserAdminService.AddUser( 255 sogd.Enabled = false;
254 // "Bob", "Hoskins", "test", "test@test.com", 1000, 1000, agentId), 256
255 // Is.EqualTo(agentId)); 257 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, myObjectName, agentId);
256 258
257 // IClientAPI client = SceneSetupHelpers.AddRootAgent(scene, agentId); 259// Assert.That(
258 260// scene.CommsManager.UserAdminService.AddUser(
259 // CachedUserInfo userInfo = scene.CommsManager.UserProfileCacheService.GetUserDetails(agentId); 261// "Bob", "Hoskins", "test", "test@test.com", 1000, 1000, agentId),
260 // Assert.That(userInfo, Is.Not.Null); 262// Is.EqualTo(agentId));
261 // Assert.That(userInfo.RootFolder, Is.Not.Null); 263
262 264 UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, agentId);
263 // SceneSetupHelpers.DeleteSceneObjectAsync(scene, part, DeRezAction.Take, userInfo.RootFolder.ID, client); 265 InventoryFolderBase folder1
264 266 = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, ua.PrincipalID, "folder1");
265 // // Check that we now have the taken part in our inventory 267
266 // Assert.That(myObjectName, Is.EqualTo(userInfo.RootFolder.FindItemByPath(myObjectName).Name)); 268 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient;
267 269 scene.DeRezObjects(client, new List<uint>() { so.LocalId }, UUID.Zero, DeRezAction.Take, folder1.ID);
268 // // Check that the taken part has actually disappeared 270
269 // SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 271 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
270 // Assert.That(retrievedPart, Is.Null); 272
271 //} 273 Assert.That(retrievedPart, Is.Not.Null);
274 Assert.That(so.IsDeleted, Is.False);
275
276 sogd.InventoryDeQueueAndDelete();
277
278 Assert.That(so.IsDeleted, Is.True);
279
280 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
281 Assert.That(retrievedPart2, Is.Null);
282
283// SceneSetupHelpers.DeleteSceneObjectAsync(scene, part, DeRezAction.Take, userInfo.RootFolder.ID, client);
284
285 InventoryItemBase retrievedItem
286 = UserInventoryHelpers.GetInventoryItem(
287 scene.InventoryService, ua.PrincipalID, "folder1/" + myObjectName);
288
289 // Check that we now have the taken part in our inventory
290 Assert.That(retrievedItem, Is.Not.Null);
291
292 // Check that the taken part has actually disappeared
293// SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
294// Assert.That(retrievedPart, Is.Null);
295 }
272 296
273 /// <summary> 297 /// <summary>
274 /// Changing a scene object uuid changes the root part uuid. This is a valid operation if the object is not 298 /// Changing a scene object uuid changes the root part uuid. This is a valid operation if the object is not
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index 5758869..5faf131 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -141,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
141 TestScene scene = new SceneHelpers().SetupScene(); 141 TestScene scene = new SceneHelpers().SetupScene();
142 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 142 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
143 143
144 scene.IncomingCloseAgent(sp.UUID); 144 scene.IncomingCloseAgent(sp.UUID, false);
145 145
146 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); 146 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
147 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); 147 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
index d722a09..ac3da1e 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
@@ -65,5 +65,22 @@ namespace OpenSim.Region.Framework.Scenes.Tests
65 65
66 Assert.That(scene.Frame, Is.EqualTo(1)); 66 Assert.That(scene.Frame, Is.EqualTo(1));
67 } 67 }
68
69 [Test]
70 public void TestShutdownScene()
71 {
72 TestHelpers.InMethod();
73
74 Scene scene = new SceneHelpers().SetupScene();
75 scene.Close();
76
77 Assert.That(scene.ShuttingDown, Is.True);
78 Assert.That(scene.Active, Is.False);
79
80 // Trying to update a shutdown scene should result in no update
81 scene.Update(1);
82
83 Assert.That(scene.Frame, Is.EqualTo(0));
84 }
68 } 85 }
69} \ No newline at end of file 86} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
index 44d2d45..9457ebb 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
@@ -50,9 +50,41 @@ using OpenSim.Tests.Common.Mock;
50namespace OpenSim.Region.Framework.Tests 50namespace OpenSim.Region.Framework.Tests
51{ 51{
52 [TestFixture] 52 [TestFixture]
53 public class UserInventoryTests 53 public class UserInventoryTests : OpenSimTestCase
54 { 54 {
55 [Test] 55 [Test]
56 public void TestCreateInventoryFolders()
57 {
58 TestHelpers.InMethod();
59// TestHelpers.EnableLogging();
60
61 // For this test both folders will have the same name which is legal in SL user inventories.
62 string foldersName = "f1";
63
64 Scene scene = new SceneHelpers().SetupScene();
65 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
66
67 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
68
69 List<InventoryFolderBase> oneFolder
70 = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
71
72 Assert.That(oneFolder.Count, Is.EqualTo(1));
73 InventoryFolderBase firstRetrievedFolder = oneFolder[0];
74 Assert.That(firstRetrievedFolder.Name, Is.EqualTo(foldersName));
75
76 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
77
78 List<InventoryFolderBase> twoFolders
79 = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
80
81 Assert.That(twoFolders.Count, Is.EqualTo(2));
82 Assert.That(twoFolders[0].Name, Is.EqualTo(foldersName));
83 Assert.That(twoFolders[1].Name, Is.EqualTo(foldersName));
84 Assert.That(twoFolders[0].ID, Is.Not.EqualTo(twoFolders[1].ID));
85 }
86
87 [Test]
56 public void TestGiveInventoryItem() 88 public void TestGiveInventoryItem()
57 { 89 {
58 TestHelpers.InMethod(); 90 TestHelpers.InMethod();
@@ -83,7 +115,7 @@ namespace OpenSim.Region.Framework.Tests
83 public void TestGiveInventoryFolder() 115 public void TestGiveInventoryFolder()
84 { 116 {
85 TestHelpers.InMethod(); 117 TestHelpers.InMethod();
86// log4net.Config.XmlConfigurator.Configure(); 118// TestHelpers.EnableLogging();
87 119
88 Scene scene = new SceneHelpers().SetupScene(); 120 Scene scene = new SceneHelpers().SetupScene();
89 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); 121 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 411e421..2279e62 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -52,26 +52,23 @@ namespace OpenSim.Region.Framework.Scenes
52 public class UuidGatherer 52 public class UuidGatherer
53 { 53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 /// <summary>
57 /// Asset cache used for gathering assets
58 /// </summary>
59 protected IAssetService m_assetCache;
60
61 /// <summary>
62 /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate
63 /// asset was found by the asset service.
64 /// </summary>
65 private AssetBase m_requestedObjectAsset;
66 55
67 /// <summary> 56 protected IAssetService m_assetService;
68 /// Signal whether we are currently waiting for the asset service to deliver an asset. 57
69 /// </summary> 58// /// <summary>
70 private bool m_waitingForObjectAsset; 59// /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate
60// /// asset was found by the asset service.
61// /// </summary>
62// private AssetBase m_requestedObjectAsset;
63//
64// /// <summary>
65// /// Signal whether we are currently waiting for the asset service to deliver an asset.
66// /// </summary>
67// private bool m_waitingForObjectAsset;
71 68
72 public UuidGatherer(IAssetService assetCache) 69 public UuidGatherer(IAssetService assetService)
73 { 70 {
74 m_assetCache = assetCache; 71 m_assetService = assetService;
75 } 72 }
76 73
77 /// <summary> 74 /// <summary>
@@ -191,18 +188,18 @@ namespace OpenSim.Region.Framework.Scenes
191 } 188 }
192 } 189 }
193 190
194 /// <summary> 191// /// <summary>
195 /// The callback made when we request the asset for an object from the asset service. 192// /// The callback made when we request the asset for an object from the asset service.
196 /// </summary> 193// /// </summary>
197 private void AssetReceived(string id, Object sender, AssetBase asset) 194// private void AssetReceived(string id, Object sender, AssetBase asset)
198 { 195// {
199 lock (this) 196// lock (this)
200 { 197// {
201 m_requestedObjectAsset = asset; 198// m_requestedObjectAsset = asset;
202 m_waitingForObjectAsset = false; 199// m_waitingForObjectAsset = false;
203 Monitor.Pulse(this); 200// Monitor.Pulse(this);
204 } 201// }
205 } 202// }
206 203
207 /// <summary> 204 /// <summary>
208 /// Get an asset synchronously, potentially using an asynchronous callback. If the 205 /// Get an asset synchronously, potentially using an asynchronous callback. If the
@@ -212,25 +209,29 @@ namespace OpenSim.Region.Framework.Scenes
212 /// <returns></returns> 209 /// <returns></returns>
213 protected virtual AssetBase GetAsset(UUID uuid) 210 protected virtual AssetBase GetAsset(UUID uuid)
214 { 211 {
215 m_waitingForObjectAsset = true; 212 return m_assetService.Get(uuid.ToString());
216 m_assetCache.Get(uuid.ToString(), this, AssetReceived);
217
218 // The asset cache callback can either
219 //
220 // 1. Complete on the same thread (if the asset is already in the cache) or
221 // 2. Come in via a different thread (if we need to go fetch it).
222 //
223 // The code below handles both these alternatives.
224 lock (this)
225 {
226 if (m_waitingForObjectAsset)
227 {
228 Monitor.Wait(this);
229 m_waitingForObjectAsset = false;
230 }
231 }
232 213
233 return m_requestedObjectAsset; 214 // XXX: Switching to do this synchronously where the call was async before but we always waited for it
215 // to complete anyway!
216// m_waitingForObjectAsset = true;
217// m_assetCache.Get(uuid.ToString(), this, AssetReceived);
218//
219// // The asset cache callback can either
220// //
221// // 1. Complete on the same thread (if the asset is already in the cache) or
222// // 2. Come in via a different thread (if we need to go fetch it).
223// //
224// // The code below handles both these alternatives.
225// lock (this)
226// {
227// if (m_waitingForObjectAsset)
228// {
229// Monitor.Wait(this);
230// m_waitingForObjectAsset = false;
231// }
232// }
233//
234// return m_requestedObjectAsset;
234 } 235 }
235 236
236 /// <summary> 237 /// <summary>
@@ -361,4 +362,47 @@ namespace OpenSim.Region.Framework.Scenes
361 } 362 }
362 } 363 }
363 } 364 }
365
366 public class HGUuidGatherer : UuidGatherer
367 {
368 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
369
370 protected string m_assetServerURL;
371
372 public HGUuidGatherer(IAssetService assetService, string assetServerURL)
373 : base(assetService)
374 {
375 m_assetServerURL = assetServerURL;
376 if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("="))
377 m_assetServerURL = m_assetServerURL + "/";
378 }
379
380 protected override AssetBase GetAsset(UUID uuid)
381 {
382 if (string.Empty == m_assetServerURL)
383 return base.GetAsset(uuid);
384 else
385 return FetchAsset(uuid);
386 }
387
388 public AssetBase FetchAsset(UUID assetID)
389 {
390
391 // Test if it's already here
392 AssetBase asset = m_assetService.Get(assetID.ToString());
393 if (asset == null)
394 {
395 // It's not, so fetch it from abroad
396 asset = m_assetService.Get(m_assetServerURL + assetID.ToString());
397 if (asset != null)
398 m_log.DebugFormat("[HGUUIDGatherer]: Copied asset {0} from {1} to local asset server", assetID, m_assetServerURL);
399 else
400 m_log.DebugFormat("[HGUUIDGatherer]: Failed to fetch asset {0} from {1}", assetID, m_assetServerURL);
401 }
402 //else
403 // m_log.DebugFormat("[HGUUIDGatherer]: Asset {0} from {1} was already here", assetID, m_assetServerURL);
404
405 return asset;
406 }
407 }
364} 408}
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs
index cfe1278..406b715 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs
@@ -25,6 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
28using System.Net; 29using System.Net;
29using System.Reflection; 30using System.Reflection;
30using log4net; 31using log4net;
@@ -33,49 +34,51 @@ using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
34using OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server; 35using OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server;
35 36
37using Mono.Addins;
38
36namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView 39namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView
37{ 40{
38 public class IRCStackModule : IRegionModule 41 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "IRCStackModule")]
42 public class IRCStackModule : INonSharedRegionModule
39 { 43 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41 45
42 private IRCServer m_server; 46 private IRCServer m_server;
47 private int m_Port;
43// private Scene m_scene; 48// private Scene m_scene;
49 private bool m_Enabled;
44 50
45 #region Implementation of IRegionModule 51 #region Implementation of INonSharedRegionModule
46 52
47 public void Initialise(Scene scene, IConfigSource source) 53 public void Initialise(IConfigSource source)
48 { 54 {
49 if (null != source.Configs["IRCd"] && 55 if (null != source.Configs["IRCd"] &&
50 source.Configs["IRCd"].GetBoolean("Enabled",false)) 56 source.Configs["IRCd"].GetBoolean("Enabled", false))
51 { 57 {
52 int portNo = source.Configs["IRCd"].GetInt("Port",6666); 58 m_Enabled = true;
53// m_scene = scene; 59 m_Port = source.Configs["IRCd"].GetInt("Port", 6666);
54 m_server = new IRCServer(IPAddress.Parse("0.0.0.0"), portNo, scene);
55 m_server.OnNewIRCClient += m_server_OnNewIRCClient;
56 } 60 }
57 } 61 }
58 62
59 void m_server_OnNewIRCClient(IRCClientView user) 63 public void AddRegion(Scene scene)
60 { 64 {
61 user.OnIRCReady += user_OnIRCReady; 65 if (!m_Enabled)
66 return;
67
68 m_server = new IRCServer(IPAddress.Parse("0.0.0.0"), m_Port, scene);
69 m_server.OnNewIRCClient += m_server_OnNewIRCClient;
62 } 70 }
63 71
64 void user_OnIRCReady(IRCClientView cv) 72 public void RegionLoaded(Scene scene)
65 { 73 {
66 m_log.Info("[IRCd] Adding user...");
67 cv.Start();
68 m_log.Info("[IRCd] Added user to Scene");
69 } 74 }
70 75
71 public void PostInitialise() 76 public void RemoveRegion(Scene scene)
72 { 77 {
73
74 } 78 }
75 79
76 public void Close() 80 public void Close()
77 { 81 {
78
79 } 82 }
80 83
81 public string Name 84 public string Name
@@ -83,11 +86,24 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView
83 get { return "IRCClientStackModule"; } 86 get { return "IRCClientStackModule"; }
84 } 87 }
85 88
86 public bool IsSharedModule 89 public Type ReplaceableInterface
87 { 90 {
88 get { return false; } 91 get { return null; }
89 } 92 }
90 93
91 #endregion 94 #endregion
95
96 void m_server_OnNewIRCClient(IRCClientView user)
97 {
98 user.OnIRCReady += user_OnIRCReady;
99 }
100
101 void user_OnIRCReady(IRCClientView cv)
102 {
103 m_log.Info("[IRCd] Adding user...");
104 cv.Start();
105 m_log.Info("[IRCd] Added user to Scene");
106 }
107
92 } 108 }
93} 109}
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index a484300..a31ccac 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -873,6 +873,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
873 public event MuteListEntryRemove OnRemoveMuteListEntry; 873 public event MuteListEntryRemove OnRemoveMuteListEntry;
874 public event GodlikeMessage onGodlikeMessage; 874 public event GodlikeMessage onGodlikeMessage;
875 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 875 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
876 public event GenericCall2 OnUpdateThrottles;
876 877
877#pragma warning restore 67 878#pragma warning restore 67
878 879
@@ -890,10 +891,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
890 891
891 public void Close() 892 public void Close()
892 { 893 {
893 Close(true); 894 Close(true, false);
894 } 895 }
895 896
896 public void Close(bool sendStop) 897 public void Close(bool sendStop, bool force)
897 { 898 {
898 Disconnect(); 899 Disconnect();
899 } 900 }
@@ -958,7 +959,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
958 959
959 } 960 }
960 961
961 public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, byte audible) 962 public void SendChatMessage(
963 string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source, byte audible)
962 { 964 {
963 if (audible > 0 && message.Length > 0) 965 if (audible > 0 && message.Length > 0)
964 IRC_SendChannelPrivmsg(fromName, message); 966 IRC_SendChannelPrivmsg(fromName, message);
@@ -1427,6 +1429,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1427 1429
1428 } 1430 }
1429 1431
1432 public void SetAgentThrottleSilent(int throttle, int setting)
1433 {
1434
1435
1436 }
1430 public byte[] GetThrottlesPacked(float multiplier) 1437 public byte[] GetThrottlesPacked(float multiplier)
1431 { 1438 {
1432 return new byte[0]; 1439 return new byte[0];
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
index 5fe5948..992f38e 100644
--- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
@@ -40,7 +40,7 @@ using OpenSim.Region.ClientStack.LindenUDP;
40using OpenSim.Region.Framework.Interfaces; 40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42 42
43namespace OpenSim.Region.CoreModules.UDP.Linden 43namespace OpenSim.Region.OptionalModules.UDP.Linden
44{ 44{
45 /// <summary> 45 /// <summary>
46 /// A module that just holds commands for inspecting the current state of the Linden UDP stack. 46 /// A module that just holds commands for inspecting the current state of the Linden UDP stack.
diff --git a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs
index 41ec14f..7639c6c 100644
--- a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs
@@ -127,6 +127,9 @@ namespace OpenSim.Region.OptionalModules.Asset
127 } 127 }
128 128
129 string fileName = rawAssetId; 129 string fileName = rawAssetId;
130
131 if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName))
132 return;
130 133
131 using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) 134 using (FileStream fs = new FileStream(fileName, FileMode.CreateNew))
132 { 135 {
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
index d68aabc..68bcb4a 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
@@ -146,7 +146,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
146 sb.AppendFormat("Attachments for {0}\n", sp.Name); 146 sb.AppendFormat("Attachments for {0}\n", sp.Name);
147 147
148 ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 }; 148 ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 };
149 ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 36)); 149 ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 50));
150 ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10)); 150 ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10));
151 ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36)); 151 ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36));
152 ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14)); 152 ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14));
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
index 31d0034..17971e3 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
@@ -130,37 +130,37 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
130 SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val)); 130 SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val));
131 } 131 }
132 132
133 private void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) 133 private int llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint)
134 { 134 {
135 SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host); 135 SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host);
136 136
137 if (hostPart == null) 137 if (hostPart == null)
138 return; 138 return 0;
139 139
140 if (hostPart.ParentGroup.IsAttachment) 140 if (hostPart.ParentGroup.IsAttachment)
141 return; 141 return 0;
142 142
143 IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface<IAttachmentsModule>(); 143 IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface<IAttachmentsModule>();
144 if (attachmentsModule == null) 144 if (attachmentsModule == null)
145 return; 145 return 0;
146 146
147 TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script); 147 TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script);
148 if (item == null) 148 if (item == null)
149 return; 149 return 0;
150 150
151 if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH 151 if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH
152 return; 152 return 0;
153 153
154 ScenePresence target; 154 ScenePresence target;
155 if (!m_scene.TryGetScenePresence(item.PermsGranter, out target)) 155 if (!m_scene.TryGetScenePresence(item.PermsGranter, out target))
156 return; 156 return 0;
157 157
158 if (target.UUID != hostPart.ParentGroup.OwnerID) 158 if (target.UUID != hostPart.ParentGroup.OwnerID)
159 { 159 {
160 uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions(); 160 uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions();
161 161
162 if ((effectivePerms & (uint)PermissionMask.Transfer) == 0) 162 if ((effectivePerms & (uint)PermissionMask.Transfer) == 0)
163 return; 163 return 0;
164 164
165 hostPart.ParentGroup.SetOwnerId(target.UUID); 165 hostPart.ParentGroup.SetOwnerId(target.UUID);
166 hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId); 166 hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId);
@@ -183,7 +183,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
183 hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); 183 hostPart.ParentGroup.RootPart.ScheduleFullUpdate();
184 } 184 }
185 185
186 attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true); 186 return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true) ? 1 : 0;
187 } 187 }
188 } 188 }
189} 189}
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs
index 913d934..2e1d03d 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCBridgeModule.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Net; 31using System.Net;
32using System.Reflection; 32using System.Reflection;
33using log4net; 33using log4net;
34using Mono.Addins;
34using Nini.Config; 35using Nini.Config;
35using Nwc.XmlRpc; 36using Nwc.XmlRpc;
36using OpenSim.Framework; 37using OpenSim.Framework;
@@ -40,6 +41,7 @@ using OpenSim.Region.Framework.Scenes;
40 41
41namespace OpenSim.Region.OptionalModules.Avatar.Chat 42namespace OpenSim.Region.OptionalModules.Avatar.Chat
42{ 43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "IRCBridgeModule")]
43 public class IRCBridgeModule : INonSharedRegionModule 45 public class IRCBridgeModule : INonSharedRegionModule
44 { 46 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
index ca956fb..a014798 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
@@ -231,12 +231,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
231 if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null) 231 if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null)
232 throw new Exception("Invalid connector configuration"); 232 throw new Exception("Invalid connector configuration");
233 233
234 // Generate an initial nickname if randomizing is enabled 234 // Generate an initial nickname
235 235
236 if (m_randomizeNick) 236 if (m_randomizeNick)
237 {
238 m_nick = m_baseNick + Util.RandomClass.Next(1, 99); 237 m_nick = m_baseNick + Util.RandomClass.Next(1, 99);
239 } 238 else
239 m_nick = m_baseNick;
240 240
241 m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); 241 m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn);
242 242
diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
index e22618d..018357a 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
@@ -36,6 +36,7 @@ using System.Text;
36using System.Text.RegularExpressions; 36using System.Text.RegularExpressions;
37using System.Threading; 37using System.Threading;
38using log4net; 38using log4net;
39using Mono.Addins;
39using Nini.Config; 40using Nini.Config;
40using Nwc.XmlRpc; 41using Nwc.XmlRpc;
41using OpenMetaverse; 42using OpenMetaverse;
@@ -47,6 +48,7 @@ using OpenSim.Region.CoreModules.Avatar.Chat;
47 48
48namespace OpenSim.Region.OptionalModules.Avatar.Concierge 49namespace OpenSim.Region.OptionalModules.Avatar.Concierge
49{ 50{
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ConciergeModule")]
50 public class ConciergeModule : ChatModule, ISharedRegionModule 52 public class ConciergeModule : ChatModule, ISharedRegionModule
51 { 53 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -546,8 +548,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge
546 c.SenderUUID = UUID.Zero; 548 c.SenderUUID = UUID.Zero;
547 c.Scene = agent.Scene; 549 c.Scene = agent.Scene;
548 550
549 agent.ControllingClient.SendChatMessage(msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, 551 agent.ControllingClient.SendChatMessage(
550 (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); 552 msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, UUID.Zero,
553 (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully);
551 } 554 }
552 555
553 private static void checkStringParameters(XmlRpcRequest request, string[] param) 556 private static void checkStringParameters(XmlRpcRequest request, string[] param)
diff --git a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
index 4e84364..026ceca 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
@@ -107,7 +107,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends
107 m_scene.AddCommand( 107 m_scene.AddCommand(
108 "Friends", this, "friends show", 108 "Friends", this, "friends show",
109 "friends show [--cache] <first-name> <last-name>", 109 "friends show [--cache] <first-name> <last-name>",
110 "Show the friends for the given user if they exist.\n", 110 "Show the friends for the given user if they exist.",
111 "The --cache option will show locally cached information for that user.", 111 "The --cache option will show locally cached information for that user.",
112 HandleFriendsShowCommand); 112 HandleFriendsShowCommand);
113 } 113 }
@@ -197,4 +197,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends
197 } 197 }
198 } 198 }
199 } 199 }
200} \ No newline at end of file 200}
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
index 7b20446..f292a75 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
@@ -447,7 +447,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
447 // settings allow voice, then whether parcel allows 447 // settings allow voice, then whether parcel allows
448 // voice, if all do retrieve or obtain the parcel 448 // voice, if all do retrieve or obtain the parcel
449 // voice channel 449 // voice channel
450 LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 450 LandData land = scene.GetLandData(avatar.AbsolutePosition);
451 451
452 //m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", 452 //m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}",
453 // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); 453 // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param);
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
index a30a38d..7da1de6 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
@@ -36,6 +36,7 @@ using System.Reflection;
36using System.Threading; 36using System.Threading;
37using OpenMetaverse; 37using OpenMetaverse;
38using log4net; 38using log4net;
39using Mono.Addins;
39using Nini.Config; 40using Nini.Config;
40using Nwc.XmlRpc; 41using Nwc.XmlRpc;
41using OpenSim.Framework; 42using OpenSim.Framework;
@@ -49,6 +50,7 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
49 50
50namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice 51namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
51{ 52{
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "VivoxVoiceModule")]
52 public class VivoxVoiceModule : ISharedRegionModule 54 public class VivoxVoiceModule : ISharedRegionModule
53 { 55 {
54 56
@@ -623,7 +625,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
623 // settings allow voice, then whether parcel allows 625 // settings allow voice, then whether parcel allows
624 // voice, if all do retrieve or obtain the parcel 626 // voice, if all do retrieve or obtain the parcel
625 // voice channel 627 // voice channel
626 LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 628 LandData land = scene.GetLandData(avatar.AbsolutePosition);
627 629
628// m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", 630// m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}",
629// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); 631// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param);
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
index 10b83e6..2802e2f 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
30using System.Reflection; 31using System.Reflection;
31using log4net; 32using log4net;
32using Mono.Addins; 33using Mono.Addins;
@@ -36,15 +37,18 @@ using OpenMetaverse.StructuredData;
36using OpenSim.Framework; 37using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
39 42
40namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups 43namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
41{ 44{
42 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsMessagingModule")]
43 public class GroupsMessagingModule : ISharedRegionModule, IGroupsMessagingModule 46 public class GroupsMessagingModule : ISharedRegionModule, IGroupsMessagingModule
44 { 47 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 49
47 private List<Scene> m_sceneList = new List<Scene>(); 50 private List<Scene> m_sceneList = new List<Scene>();
51 private IPresenceService m_presenceService;
48 52
49 private IMessageTransferModule m_msgTransferModule = null; 53 private IMessageTransferModule m_msgTransferModule = null;
50 54
@@ -54,7 +58,28 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
54 private bool m_groupMessagingEnabled = false; 58 private bool m_groupMessagingEnabled = false;
55 private bool m_debugEnabled = true; 59 private bool m_debugEnabled = true;
56 60
57 #region IRegionModuleBase Members 61 /// <summary>
62 /// If enabled, module only tries to send group IMs to online users by querying cached presence information.
63 /// </summary>
64 private bool m_messageOnlineAgentsOnly;
65
66 /// <summary>
67 /// Cache for online users.
68 /// </summary>
69 /// <remarks>
70 /// Group ID is key, presence information for online members is value.
71 /// Will only be non-null if m_messageOnlineAgentsOnly = true
72 /// We cache here so that group messages don't constantly have to re-request the online user list to avoid
73 /// attempted expensive sending of messages to offline users.
74 /// The tradeoff is that a user that comes online will not receive messages consistently from all other users
75 /// until caches have updated.
76 /// Therefore, we set the cache expiry to just 20 seconds.
77 /// </remarks>
78 private ExpiringCache<UUID, PresenceInfo[]> m_usersOnlineCache;
79
80 private int m_usersOnlineCacheExpirySeconds = 20;
81
82 #region Region Module interfaceBase Members
58 83
59 public void Initialise(IConfigSource config) 84 public void Initialise(IConfigSource config)
60 { 85 {
@@ -83,10 +108,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
83 return; 108 return;
84 } 109 }
85 110
111 m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false);
112
113 if (m_messageOnlineAgentsOnly)
114 m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>();
115
86 m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); 116 m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true);
87 } 117 }
88 118
89 m_log.Info("[GROUPS-MESSAGING]: GroupsMessagingModule starting up"); 119 m_log.InfoFormat(
120 "[GROUPS-MESSAGING]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}",
121 m_messageOnlineAgentsOnly, m_debugEnabled);
90 } 122 }
91 123
92 public void AddRegion(Scene scene) 124 public void AddRegion(Scene scene)
@@ -126,6 +158,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
126 return; 158 return;
127 } 159 }
128 160
161 if (m_presenceService == null)
162 m_presenceService = scene.PresenceService;
129 163
130 m_sceneList.Add(scene); 164 m_sceneList.Add(scene);
131 165
@@ -207,12 +241,42 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
207 public void SendMessageToGroup(GridInstantMessage im, UUID groupID) 241 public void SendMessageToGroup(GridInstantMessage im, UUID groupID)
208 { 242 {
209 List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); 243 List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID);
210 244 int groupMembersCount = groupMembers.Count;
211 if (m_debugEnabled) 245
212 m_log.DebugFormat( 246 if (m_messageOnlineAgentsOnly)
213 "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", 247 {
214 groupID, groupMembers.Count); 248 string[] t1 = groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()).ToArray();
215 249
250 // We cache in order not to overwhlem the presence service on large grids with many groups. This does
251 // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed.
252 // (assuming this is the same across all grid simulators).
253 PresenceInfo[] onlineAgents;
254 if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents))
255 {
256 onlineAgents = m_presenceService.GetAgents(t1);
257 m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds);
258 }
259
260 HashSet<string> onlineAgentsUuidSet = new HashSet<string>();
261 Array.ForEach<PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID));
262
263 groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList();
264
265 // if (m_debugEnabled)
266// m_log.DebugFormat(
267// "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online",
268// groupID, groupMembersCount, groupMembers.Count());
269 }
270 else
271 {
272 if (m_debugEnabled)
273 m_log.DebugFormat(
274 "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members",
275 groupID, groupMembers.Count);
276 }
277
278 int requestStartTick = Environment.TickCount;
279
216 foreach (GroupMembersData member in groupMembers) 280 foreach (GroupMembersData member in groupMembers)
217 { 281 {
218 if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) 282 if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID))
@@ -254,6 +318,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
254 ProcessMessageFromGroupSession(msg); 318 ProcessMessageFromGroupSession(msg);
255 } 319 }
256 } 320 }
321
322 // Temporary for assessing how long it still takes to send messages to large online groups.
323 if (m_messageOnlineAgentsOnly)
324 m_log.DebugFormat(
325 "[GROUPS-MESSAGING]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms",
326 groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick);
257 } 327 }
258 328
259 #region SimGridEventHandlers 329 #region SimGridEventHandlers
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index 65bd26c..ae0ad02 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -43,7 +43,7 @@ using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
43 43
44namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups 44namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
45{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GroupsModule")]
47 public class GroupsModule : ISharedRegionModule, IGroupsModule 47 public class GroupsModule : ISharedRegionModule, IGroupsModule
48 { 48 {
49 /// <summary> 49 /// <summary>
@@ -86,7 +86,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
86 private bool m_debugEnabled = false; 86 private bool m_debugEnabled = false;
87 private int m_levelGroupCreate = 0; 87 private int m_levelGroupCreate = 0;
88 88
89 #region IRegionModuleBase Members 89 #region Region Module interfaceBase Members
90 90
91 public void Initialise(IConfigSource config) 91 public void Initialise(IConfigSource config)
92 { 92 {
@@ -123,7 +123,36 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
123 public void AddRegion(Scene scene) 123 public void AddRegion(Scene scene)
124 { 124 {
125 if (m_groupsEnabled) 125 if (m_groupsEnabled)
126 {
126 scene.RegisterModuleInterface<IGroupsModule>(this); 127 scene.RegisterModuleInterface<IGroupsModule>(this);
128 scene.AddCommand(
129 "debug",
130 this,
131 "debug groups verbose",
132 "debug groups verbose <true|false>",
133 "This setting turns on very verbose groups debugging",
134 HandleDebugGroupsVerbose);
135 }
136 }
137
138 private void HandleDebugGroupsVerbose(object modules, string[] args)
139 {
140 if (args.Length < 4)
141 {
142 MainConsole.Instance.Output("Usage: debug groups verbose <true|false>");
143 return;
144 }
145
146 bool verbose = false;
147 if (!bool.TryParse(args[3], out verbose))
148 {
149 MainConsole.Instance.Output("Usage: debug groups verbose <true|false>");
150 return;
151 }
152
153 m_debugEnabled = verbose;
154
155 MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled);
127 } 156 }
128 157
129 public void RegionLoaded(Scene scene) 158 public void RegionLoaded(Scene scene)
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
index 5d57f70..7bae8f7 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
@@ -102,7 +102,7 @@ using OpenSim.Services.Interfaces;
102 102
103namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups 103namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
104{ 104{
105 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 105 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianGroupsServicesConnectorModule")]
106 public class SimianGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector 106 public class SimianGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector
107 { 107 {
108 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 108 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -176,7 +176,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
176 // private IUserAccountService m_accountService = null; 176 // private IUserAccountService m_accountService = null;
177 177
178 178
179 #region IRegionModuleBase Members 179 #region Region Module interfaceBase Members
180 180
181 public string Name 181 public string Name
182 { 182 {
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
index d412cd1..d0c3ea5 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
@@ -47,7 +47,7 @@ using OpenSim.Services.Interfaces;
47 47
48namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups 48namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
49{ 49{
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XmlRpcGroupsServicesConnectorModule")]
51 public class XmlRpcGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector 51 public class XmlRpcGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector
52 { 52 {
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -83,7 +83,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
83 private Dictionary<UUID, List<UUID>> m_groupsAgentsDroppedFromChatSession = new Dictionary<UUID, List<UUID>>(); 83 private Dictionary<UUID, List<UUID>> m_groupsAgentsDroppedFromChatSession = new Dictionary<UUID, List<UUID>>();
84 private Dictionary<UUID, List<UUID>> m_groupsAgentsInvitedToChatSession = new Dictionary<UUID, List<UUID>>(); 84 private Dictionary<UUID, List<UUID>> m_groupsAgentsInvitedToChatSession = new Dictionary<UUID, List<UUID>>();
85 85
86 #region IRegionModuleBase Members 86 #region Region Module interfaceBase Members
87 87
88 public string Name 88 public string Name
89 { 89 {
diff --git a/OpenSim/Region/OptionalModules/Example/BareBonesShared/BareBonesSharedModule.cs b/OpenSim/Region/OptionalModules/Example/BareBonesShared/BareBonesSharedModule.cs
index dddea3e..781fe95 100644
--- a/OpenSim/Region/OptionalModules/Example/BareBonesShared/BareBonesSharedModule.cs
+++ b/OpenSim/Region/OptionalModules/Example/BareBonesShared/BareBonesSharedModule.cs
@@ -33,9 +33,6 @@ using Nini.Config;
33using OpenSim.Region.Framework.Interfaces; 33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
35 35
36[assembly: Addin("BareBonesSharedModule", "0.1")]
37[assembly: AddinDependency("OpenSim", "0.5")]
38
39namespace OpenSim.Region.OptionalModules.Example.BareBonesShared 36namespace OpenSim.Region.OptionalModules.Example.BareBonesShared
40{ 37{
41 /// <summary> 38 /// <summary>
diff --git a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..217b2d5
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
@@ -0,0 +1,37 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4using Mono.Addins;
5
6// General Information about an assembly is controlled through the following
7// set of attributes. Change these attribute values to modify the information
8// associated with an assembly.
9[assembly: AssemblyTitle("OpenSim.Region.OptionalModules")]
10[assembly: AssemblyDescription("Optional modules for OpenSim")]
11[assembly: AssemblyConfiguration("")]
12[assembly: AssemblyCompany("")]
13[assembly: AssemblyProduct("OpenSim.Region.OptionalModules.Properties")]
14[assembly: AssemblyCopyright("Copyright © 2012")]
15[assembly: AssemblyTrademark("")]
16[assembly: AssemblyCulture("")]
17
18// Setting ComVisible to false makes the types in this assembly not visible
19// to COM components. If you need to access a type in this assembly from
20// COM, set the ComVisible attribute to true on that type.
21[assembly: ComVisible(false)]
22
23// The following GUID is for the ID of the typelib if this project is exposed to COM
24[assembly: Guid("84a3082d-3011-4c13-835c-c7d93f97ac79")]
25
26// Version information for an assembly consists of the following four values:
27//
28// Major Version
29// Minor Version
30// Build Number
31// Revision
32//
33[assembly: AssemblyVersion("0.7.5.*")]
34[assembly: AssemblyFileVersion("1.0.0.0")]
35
36[assembly: Addin("OpenSim.Region.OptionalModules", "0.1")]
37[assembly: AddinDependency("OpenSim", "0.5")]
diff --git a/OpenSim/Region/OptionalModules/Resources/OptionalModules.addin.xml b/OpenSim/Region/OptionalModules/Resources/OptionalModules.addin.xml
deleted file mode 100644
index 8691343..0000000
--- a/OpenSim/Region/OptionalModules/Resources/OptionalModules.addin.xml
+++ /dev/null
@@ -1,18 +0,0 @@
1<Addin id="OpenSim.Region.OptionalModules" version="0.2">
2 <Runtime>
3 <Import assembly="OpenSim.Region.OptionalModules.dll"/>
4 </Runtime>
5
6 <Dependencies>
7 <Addin id="OpenSim" version="0.5" />
8 </Dependencies>
9
10 <Extension path = "/OpenSim/RegionModules">
11 <RegionModule id="RegionReady" type="OpenSim.Region.OptionalModules.Scripting.RegionReady.RegionReadyModule" />
12 <RegionModule id="IRCBridge" type="OpenSim.Region.OptionalModules.Avatar.Chat.IRCBridgeModule" />
13 <RegionModule id="Concierge" type="OpenSim.Region.OptionalModules.Avatar.Concierge.ConciergeModule" />
14 <RegionModule id="VivoxVoice" type="OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice.VivoxVoiceModule" />
15 <RegionModule id="WorldViewModule" type="OpenSim.Region.OptionalModules.World.WorldView.WorldViewModule" />
16 <RegionModule id="AutoBackupModule" type="OpenSim.Region.OptionalModules.World.AutoBackup.AutoBackupModule" />
17 </Extension>
18</Addin>
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
index 311531c..e68764a 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
@@ -59,7 +59,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
59 private Dictionary<UUID,JsonStore> m_JsonValueStore; 59 private Dictionary<UUID,JsonStore> m_JsonValueStore;
60 private UUID m_sharedStore; 60 private UUID m_sharedStore;
61 61
62#region IRegionModule Members 62#region Region Module interface
63 63
64 // ----------------------------------------------------------------- 64 // -----------------------------------------------------------------
65 /// <summary> 65 /// <summary>
@@ -175,14 +175,15 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
175 /// 175 ///
176 /// </summary> 176 /// </summary>
177 // ----------------------------------------------------------------- 177 // -----------------------------------------------------------------
178 public bool CreateStore(string value, out UUID result) 178 public bool CreateStore(string value, ref UUID result)
179 { 179 {
180 result = UUID.Zero; 180 if (result == UUID.Zero)
181 result = UUID.Random();
182
183 JsonStore map = null;
181 184
182 if (! m_enabled) return false; 185 if (! m_enabled) return false;
183 186
184 UUID uuid = UUID.Random();
185 JsonStore map = null;
186 187
187 try 188 try
188 { 189 {
@@ -195,9 +196,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
195 } 196 }
196 197
197 lock (m_JsonValueStore) 198 lock (m_JsonValueStore)
198 m_JsonValueStore.Add(uuid,map); 199 m_JsonValueStore.Add(result,map);
199 200
200 result = uuid;
201 return true; 201 return true;
202 } 202 }
203 203
@@ -231,7 +231,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
231 if (! m_JsonValueStore.TryGetValue(storeID,out map)) 231 if (! m_JsonValueStore.TryGetValue(storeID,out map))
232 { 232 {
233 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID); 233 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
234 return true; 234 return false;
235 } 235 }
236 } 236 }
237 237
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
index eaba816..0c175ca 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
@@ -58,7 +58,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
58 private IScriptModuleComms m_comms; 58 private IScriptModuleComms m_comms;
59 private IJsonStoreModule m_store; 59 private IJsonStoreModule m_store;
60 60
61#region IRegionModule Members 61#region Region Module interface
62 62
63 // ----------------------------------------------------------------- 63 // -----------------------------------------------------------------
64 /// <summary> 64 /// <summary>
@@ -227,7 +227,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
227 protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value) 227 protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value)
228 { 228 {
229 UUID uuid = UUID.Zero; 229 UUID uuid = UUID.Zero;
230 if (! m_store.CreateStore(value, out uuid)) 230 if (! m_store.CreateStore(value, ref uuid))
231 GenerateRuntimeError("Failed to create Json store"); 231 GenerateRuntimeError("Failed to create Json store");
232 232
233 return uuid; 233 return uuid;
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
index 03481d2..6fb28e2 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
@@ -43,13 +43,17 @@ using OpenMetaverse;
43using OpenSim.Framework; 43using OpenSim.Framework;
44using OpenSim.Region.Framework.Interfaces; 44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes; 45using OpenSim.Region.Framework.Scenes;
46using Mono.Addins;
46 47
47namespace OpenSim.Region.OptionalModules.Scripting.Minimodule 48namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
48{ 49{
49 public class MRMModule : IRegionModule, IMRMModule 50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MRMModule")]
51 public class MRMModule : INonSharedRegionModule, IMRMModule
50 { 52 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 private Scene m_scene; 54 private Scene m_scene;
55 private bool m_Enabled;
56 private bool m_Hidden;
53 57
54 private readonly Dictionary<UUID,MRMBase> m_scripts = new Dictionary<UUID, MRMBase>(); 58 private readonly Dictionary<UUID,MRMBase> m_scripts = new Dictionary<UUID, MRMBase>();
55 59
@@ -67,7 +71,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
67 m_extensions[typeof (T)] = instance; 71 m_extensions[typeof (T)] = instance;
68 } 72 }
69 73
70 public void Initialise(Scene scene, IConfigSource source) 74 #region INonSharedRegionModule
75
76 public void Initialise(IConfigSource source)
71 { 77 {
72 if (source.Configs["MRM"] != null) 78 if (source.Configs["MRM"] != null)
73 { 79 {
@@ -76,23 +82,60 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
76 if (source.Configs["MRM"].GetBoolean("Enabled", false)) 82 if (source.Configs["MRM"].GetBoolean("Enabled", false))
77 { 83 {
78 m_log.Info("[MRM]: Enabling MRM Module"); 84 m_log.Info("[MRM]: Enabling MRM Module");
79 m_scene = scene; 85 m_Enabled = true;
86 m_Hidden = source.Configs["MRM"].GetBoolean("Hidden", false);
87 }
88 }
89 }
80 90
81 // when hidden, we don't listen for client initiated script events 91 public void AddRegion(Scene scene)
82 // only making the MRM engine available for region modules 92 {
83 if (!source.Configs["MRM"].GetBoolean("Hidden", false)) 93 if (!m_Enabled)
84 { 94 return;
85 scene.EventManager.OnRezScript += EventManager_OnRezScript;
86 scene.EventManager.OnStopScript += EventManager_OnStopScript;
87 }
88 95
89 scene.EventManager.OnFrame += EventManager_OnFrame; 96 m_scene = scene;
90 97
91 scene.RegisterModuleInterface<IMRMModule>(this); 98 // when hidden, we don't listen for client initiated script events
92 } 99 // only making the MRM engine available for region modules
100 if (!m_Hidden)
101 {
102 scene.EventManager.OnRezScript += EventManager_OnRezScript;
103 scene.EventManager.OnStopScript += EventManager_OnStopScript;
93 } 104 }
105
106 scene.EventManager.OnFrame += EventManager_OnFrame;
107
108 scene.RegisterModuleInterface<IMRMModule>(this);
109 }
110
111 public void RegionLoaded(Scene scene)
112 {
94 } 113 }
95 114
115 public void RemoveRegion(Scene scene)
116 {
117 }
118
119 public void Close()
120 {
121 foreach (KeyValuePair<UUID, MRMBase> pair in m_scripts)
122 {
123 pair.Value.Stop();
124 }
125 }
126
127 public string Name
128 {
129 get { return "MiniRegionModule"; }
130 }
131
132 public Type ReplaceableInterface
133 {
134 get { return null; }
135 }
136
137 #endregion
138
96 void EventManager_OnStopScript(uint localID, UUID itemID) 139 void EventManager_OnStopScript(uint localID, UUID itemID)
97 { 140 {
98 if (m_scripts.ContainsKey(itemID)) 141 if (m_scripts.ContainsKey(itemID))
@@ -293,28 +336,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
293 mmb.InitMiniModule(world, host, itemID); 336 mmb.InitMiniModule(world, host, itemID);
294 } 337 }
295 338
296 public void PostInitialise()
297 {
298 }
299
300 public void Close()
301 {
302 foreach (KeyValuePair<UUID, MRMBase> pair in m_scripts)
303 {
304 pair.Value.Stop();
305 }
306 }
307
308 public string Name
309 {
310 get { return "MiniRegionModule"; }
311 }
312
313 public bool IsSharedModule
314 {
315 get { return false; }
316 }
317
318 /// <summary> 339 /// <summary>
319 /// Stolen from ScriptEngine Common 340 /// Stolen from ScriptEngine Common
320 /// </summary> 341 /// </summary>
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
index aa23fee..5ed1514 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
@@ -821,8 +821,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
821 { 821 {
822 if (!CanEdit()) 822 if (!CanEdit())
823 return; 823 return;
824 824 ISoundModule module = m_rootScene.RequestModuleInterface<ISoundModule>();
825 GetSOP().SendSound(asset.ToString(), volume, true, 0, 0, false, false); 825 if (module != null)
826 {
827 module.SendSound(GetSOP().UUID, asset, volume, true, 0, 0, false, false);
828 }
826 } 829 }
827 830
828 #endregion 831 #endregion
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
index fff3a32..c550c44 100644
--- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
@@ -32,6 +32,7 @@ using System.Net;
32using System.IO; 32using System.IO;
33using System.Text; 33using System.Text;
34using log4net; 34using log4net;
35using Mono.Addins;
35using Nini.Config; 36using Nini.Config;
36using OpenMetaverse; 37using OpenMetaverse;
37using OpenMetaverse.StructuredData; 38using OpenMetaverse.StructuredData;
@@ -42,6 +43,7 @@ using OpenSim.Services.Interfaces;
42 43
43namespace OpenSim.Region.OptionalModules.Scripting.RegionReady 44namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
44{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RegionReadyModule")]
45 public class RegionReadyModule : IRegionReadyModule, INonSharedRegionModule 47 public class RegionReadyModule : IRegionReadyModule, INonSharedRegionModule
46 { 48 {
47 private static readonly ILog m_log = 49 private static readonly ILog m_log =
@@ -181,7 +183,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
181 } 183 }
182 } 184 }
183 185
184 void OnOarFileLoaded(Guid requestId, string message) 186 void OnOarFileLoaded(Guid requestId, List<UUID> loadedScenes, string message)
185 { 187 {
186 m_oarFileLoading = true; 188 m_oarFileLoading = true;
187 189
diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs
index 2187449..6120a81 100644
--- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs
@@ -32,6 +32,7 @@ using System.Reflection;
32using log4net; 32using log4net;
33using Nini.Config; 33using Nini.Config;
34using OpenMetaverse; 34using OpenMetaverse;
35using Mono.Addins;
35 36
36using OpenSim.Framework; 37using OpenSim.Framework;
37using OpenSim.Framework.Communications; 38using OpenSim.Framework.Communications;
@@ -49,7 +50,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
49 public string uri; 50 public string uri;
50 } 51 }
51 52
52 public class XmlRpcGridRouter : IRegionModule, IXmlRpcRouter 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XmlRpcGridRouter")]
54 public class XmlRpcGridRouter : INonSharedRegionModule, IXmlRpcRouter
53 { 55 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 57
@@ -59,9 +61,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
59 private bool m_Enabled = false; 61 private bool m_Enabled = false;
60 private string m_ServerURI = String.Empty; 62 private string m_ServerURI = String.Empty;
61 63
62 public void Initialise(Scene scene, IConfigSource config) 64 #region INonSharedRegionModule
65
66 public void Initialise(IConfigSource config)
63 { 67 {
64 IConfig startupConfig = config.Configs["Startup"]; 68 IConfig startupConfig = config.Configs["XMLRPC"];
65 if (startupConfig == null) 69 if (startupConfig == null)
66 return; 70 return;
67 71
@@ -74,16 +78,30 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
74 m_log.Error("[XMLRPC GRID ROUTER] Module configured but no URI given. Disabling"); 78 m_log.Error("[XMLRPC GRID ROUTER] Module configured but no URI given. Disabling");
75 return; 79 return;
76 } 80 }
77
78 scene.RegisterModuleInterface<IXmlRpcRouter>(this);
79 m_Enabled = true; 81 m_Enabled = true;
80 } 82 }
81 } 83 }
82 84
83 public void PostInitialise() 85 public void AddRegion(Scene scene)
86 {
87 if (!m_Enabled)
88 return;
89
90 scene.RegisterModuleInterface<IXmlRpcRouter>(this);
91 }
92
93 public void RegionLoaded(Scene scene)
84 { 94 {
85 } 95 }
86 96
97 public void RemoveRegion(Scene scene)
98 {
99 if (!m_Enabled)
100 return;
101
102 scene.UnregisterModuleInterface<IXmlRpcRouter>(this);
103 }
104
87 public void Close() 105 public void Close()
88 { 106 {
89 } 107 }
@@ -93,11 +111,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule
93 get { return "XmlRpcGridRouterModule"; } 111 get { return "XmlRpcGridRouterModule"; }
94 } 112 }
95 113
96 public bool IsSharedModule 114 public Type ReplaceableInterface
97 { 115 {
98 get { return false; } 116 get { return null; }
99 } 117 }
100 118
119 #endregion
120
101 public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri) 121 public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri)
102 { 122 {
103 if (!m_Channels.ContainsKey(itemID)) 123 if (!m_Channels.ContainsKey(itemID))
diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
index 11c87f8..4bde52a 100644
--- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs
@@ -31,6 +31,7 @@ using System.Reflection;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse; 33using OpenMetaverse;
34using Mono.Addins;
34 35
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
@@ -39,32 +40,46 @@ using OpenSim.Region.Framework.Scenes;
39 40
40namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule 41namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule
41{ 42{
42 public class XmlRpcRouter : IRegionModule, IXmlRpcRouter 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XmlRpcRouter")]
44 public class XmlRpcRouter : INonSharedRegionModule, IXmlRpcRouter
43 { 45 {
44 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 private bool m_enabled = false; 47
46 public void Initialise(Scene scene, IConfigSource config) 48 private bool m_Enabled;
49
50 #region INonSharedRegionModule
51
52 public void Initialise(IConfigSource config)
47 { 53 {
48 IConfig startupConfig = config.Configs["XMLRPC"]; 54 IConfig startupConfig = config.Configs["XMLRPC"];
49 if (startupConfig == null) 55 if (startupConfig == null)
50 return; 56 return;
51 57
52 if (startupConfig.GetString("XmlRpcRouterModule", 58 if (startupConfig.GetString("XmlRpcRouterModule",
53 "") == "XmlRpcRouterModule") 59 "XmlRpcRouterModule") == "XmlRpcRouterModule")
54 { 60 m_Enabled = true;
55 scene.RegisterModuleInterface<IXmlRpcRouter>(this); 61 }
56 m_enabled = true; 62
57 } 63 public void AddRegion(Scene scene)
58 else 64 {
59 { 65 if (!m_Enabled)
60 m_enabled = false; 66 return;
61 } 67
68 scene.RegisterModuleInterface<IXmlRpcRouter>(this);
62 } 69 }
63 70
64 public void PostInitialise() 71 public void RegionLoaded(Scene scene)
65 { 72 {
66 } 73 }
67 74
75 public void RemoveRegion(Scene scene)
76 {
77 if (!m_Enabled)
78 return;
79
80 scene.UnregisterModuleInterface<IXmlRpcRouter>(this);
81 }
82
68 public void Close() 83 public void Close()
69 { 84 {
70 } 85 }
@@ -74,14 +89,16 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule
74 get { return "XmlRpcRouterModule"; } 89 get { return "XmlRpcRouterModule"; }
75 } 90 }
76 91
77 public bool IsSharedModule 92 public Type ReplaceableInterface
78 { 93 {
79 get { return false; } 94 get { return null; }
80 } 95 }
81 96
97 #endregion
98
82 public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri) 99 public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri)
83 { 100 {
84 if (m_enabled) 101 if (m_Enabled)
85 { 102 {
86 scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] { uri }); 103 scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] { uri });
87 } 104 }
diff --git a/OpenSim/Region/OptionalModules/ServiceConnectorsIn/Freeswitch/FreeswitchServiceInConnectorModule.cs b/OpenSim/Region/OptionalModules/ServiceConnectorsIn/Freeswitch/FreeswitchServiceInConnectorModule.cs
index 74c5139..78c870a 100644
--- a/OpenSim/Region/OptionalModules/ServiceConnectorsIn/Freeswitch/FreeswitchServiceInConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/ServiceConnectorsIn/Freeswitch/FreeswitchServiceInConnectorModule.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Freeswitch
48 private IConfigSource m_Config; 48 private IConfigSource m_Config;
49 bool m_Registered = false; 49 bool m_Registered = false;
50 50
51 #region IRegionModule interface 51 #region Region Module interface
52 52
53 public void Initialise(IConfigSource config) 53 public void Initialise(IConfigSource config)
54 { 54 {
diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
index ec9f157..1d35c54 100644
--- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
+++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs
@@ -33,6 +33,7 @@ using System.Reflection;
33using System.Timers; 33using System.Timers;
34using System.Text.RegularExpressions; 34using System.Text.RegularExpressions;
35using log4net; 35using log4net;
36using Mono.Addins;
36using Nini.Config; 37using Nini.Config;
37using OpenSim.Framework; 38using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
@@ -95,6 +96,7 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup
95 /// Save memory by setting low initial capacities. Minimizes impact in common cases of all regions using same interval, and instances hosting 1 ~ 4 regions. 96 /// Save memory by setting low initial capacities. Minimizes impact in common cases of all regions using same interval, and instances hosting 1 ~ 4 regions.
96 /// Also helps if you don't want AutoBackup at all. 97 /// Also helps if you don't want AutoBackup at all.
97 /// </remarks> 98 /// </remarks>
99 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AutoBackupModule")]
98 public class AutoBackupModule : ISharedRegionModule 100 public class AutoBackupModule : ISharedRegionModule
99 { 101 {
100 private static readonly ILog m_log = 102 private static readonly ILog m_log =
diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
index d206f69..c7e3a7a 100644
--- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
+++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
55 /// 55 ///
56 /// </summary> 56 /// </summary>
57 57
58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SampleMoneyModule")]
59 public class SampleMoneyModule : IMoneyModule, ISharedRegionModule 59 public class SampleMoneyModule : IMoneyModule, ISharedRegionModule
60 { 60 {
61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -199,7 +199,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
199 { 199 {
200 } 200 }
201 201
202 public bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, int amount) 202 public bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, int amount, UUID txn)
203 { 203 {
204 string description = String.Format("Object {0} pays {1}", resolveObjectName(objectID), resolveAgentName(toID)); 204 string description = String.Format("Object {0} pays {1}", resolveObjectName(objectID), resolveAgentName(toID));
205 205
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 7c693b6..d665126 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -148,7 +148,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
148 OnInstantMessage(this, new GridInstantMessage(m_scene, 148 OnInstantMessage(this, new GridInstantMessage(m_scene,
149 m_uuid, m_firstname + " " + m_lastname, 149 m_uuid, m_firstname + " " + m_lastname,
150 target, 0, false, message, 150 target, 0, false, message,
151 UUID.Zero, false, Position, new byte[0])); 151 UUID.Zero, false, Position, new byte[0], true));
152 } 152 }
153 153
154 public void SendAgentOffline(UUID[] agentIDs) 154 public void SendAgentOffline(UUID[] agentIDs)
@@ -473,7 +473,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
473 public event MuteListEntryRemove OnRemoveMuteListEntry; 473 public event MuteListEntryRemove OnRemoveMuteListEntry;
474 public event GodlikeMessage onGodlikeMessage; 474 public event GodlikeMessage onGodlikeMessage;
475 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 475 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
476 476 public event GenericCall2 OnUpdateThrottles;
477#pragma warning restore 67 477#pragma warning restore 67
478 478
479 #endregion 479 #endregion
@@ -597,6 +597,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC
597 public virtual void SetChildAgentThrottle(byte[] throttle) 597 public virtual void SetChildAgentThrottle(byte[] throttle)
598 { 598 {
599 } 599 }
600
601 public void SetAgentThrottleSilent(int throttle, int setting)
602 {
603
604
605 }
600 public byte[] GetThrottlesPacked(float multiplier) 606 public byte[] GetThrottlesPacked(float multiplier)
601 { 607 {
602 return new byte[0]; 608 return new byte[0];
@@ -607,13 +613,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
607 { 613 {
608 } 614 }
609 615
610 public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, 616 public virtual void SendChatMessage(
611 UUID fromAgentID, byte source, byte audible) 617 string message, byte type, Vector3 fromPos, string fromName,
618 UUID fromAgentID, UUID ownerID, byte source, byte audible)
612 { 619 {
613 } 620 }
614 621
615 public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName, 622 public virtual void SendChatMessage(
616 UUID fromAgentID, byte source, byte audible) 623 byte[] message, byte type, Vector3 fromPos, string fromName,
624 UUID fromAgentID, UUID ownerID, byte source, byte audible)
617 { 625 {
618 } 626 }
619 627
@@ -909,11 +917,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
909 917
910 public void Close() 918 public void Close()
911 { 919 {
912 Close(true); 920 Close(true, false);
913 } 921 }
914 922
915 public void Close(bool sendStop) 923 public void Close(bool sendStop, bool force)
916 { 924 {
925 // Remove ourselves from the scene
926 m_scene.RemoveClient(AgentId, false);
917 } 927 }
918 928
919 public void Start() 929 public void Start()
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index f16927c..8c9c006 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -29,37 +29,57 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Threading; 31using System.Threading;
32using Timer = System.Timers.Timer;
33
32using log4net; 34using log4net;
33using Nini.Config; 35using Nini.Config;
36using Mono.Addins;
34using OpenMetaverse; 37using OpenMetaverse;
38
35using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
37using OpenSim.Framework; 41using OpenSim.Framework;
38using Timer=System.Timers.Timer;
39using OpenSim.Services.Interfaces; 42using OpenSim.Services.Interfaces;
40 43
41namespace OpenSim.Region.OptionalModules.World.NPC 44namespace OpenSim.Region.OptionalModules.World.NPC
42{ 45{
43 public class NPCModule : IRegionModule, INPCModule 46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "NPCModule")]
47 public class NPCModule : INPCModule, ISharedRegionModule
44 { 48 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(
50 MethodBase.GetCurrentMethod().DeclaringType);
51
52 private Dictionary<UUID, NPCAvatar> m_avatars =
53 new Dictionary<UUID, NPCAvatar>();
46 54
47 private Dictionary<UUID, NPCAvatar> m_avatars = new Dictionary<UUID, NPCAvatar>(); 55 public bool Enabled { get; private set; }
48 56
49 public void Initialise(Scene scene, IConfigSource source) 57 public void Initialise(IConfigSource source)
50 { 58 {
51 IConfig config = source.Configs["NPC"]; 59 IConfig config = source.Configs["NPC"];
52 60
53 if (config != null && config.GetBoolean("Enabled", false)) 61 Enabled = (config != null && config.GetBoolean("Enabled", false));
54 { 62 }
63
64 public void AddRegion(Scene scene)
65 {
66 if (Enabled)
55 scene.RegisterModuleInterface<INPCModule>(this); 67 scene.RegisterModuleInterface<INPCModule>(this);
56 } 68 }
69
70 public void RegionLoaded(Scene scene)
71 {
57 } 72 }
58 73
59 public void PostInitialise() 74 public void PostInitialise()
60 { 75 {
61 } 76 }
62 77
78 public void RemoveRegion(Scene scene)
79 {
80 scene.UnregisterModuleInterface<INPCModule>(this);
81 }
82
63 public void Close() 83 public void Close()
64 { 84 {
65 } 85 }
@@ -69,15 +89,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
69 get { return "NPCModule"; } 89 get { return "NPCModule"; }
70 } 90 }
71 91
72 public bool IsSharedModule 92 public Type ReplaceableInterface { get { return null; } }
73 {
74 get { return true; }
75 }
76 93
77 public bool IsNPC(UUID agentId, Scene scene) 94 public bool IsNPC(UUID agentId, Scene scene)
78 { 95 {
79 // FIXME: This implementation could not just use the ScenePresence.PresenceType (and callers could inspect 96 // FIXME: This implementation could not just use the
80 // that directly). 97 // ScenePresence.PresenceType (and callers could inspect that
98 // directly).
81 ScenePresence sp = scene.GetScenePresence(agentId); 99 ScenePresence sp = scene.GetScenePresence(agentId);
82 if (sp == null || sp.IsChildAgent) 100 if (sp == null || sp.IsChildAgent)
83 return false; 101 return false;
@@ -86,7 +104,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
86 return m_avatars.ContainsKey(agentId); 104 return m_avatars.ContainsKey(agentId);
87 } 105 }
88 106
89 public bool SetNPCAppearance(UUID agentId, AvatarAppearance appearance, Scene scene) 107 public bool SetNPCAppearance(UUID agentId,
108 AvatarAppearance appearance, Scene scene)
90 { 109 {
91 ScenePresence npc = scene.GetScenePresence(agentId); 110 ScenePresence npc = scene.GetScenePresence(agentId);
92 if (npc == null || npc.IsChildAgent) 111 if (npc == null || npc.IsChildAgent)
@@ -99,30 +118,30 @@ namespace OpenSim.Region.OptionalModules.World.NPC
99 // Delete existing npc attachments 118 // Delete existing npc attachments
100 scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false); 119 scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false);
101 120
102 // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet since it doesn't transfer attachments 121 // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet
103 AvatarAppearance npcAppearance = new AvatarAppearance(appearance, true); 122 // since it doesn't transfer attachments
123 AvatarAppearance npcAppearance = new AvatarAppearance(appearance,
124 true);
104 npc.Appearance = npcAppearance; 125 npc.Appearance = npcAppearance;
105 126
106 // Rez needed npc attachments 127 // Rez needed npc attachments
107 scene.AttachmentsModule.RezAttachments(npc); 128 scene.AttachmentsModule.RezAttachments(npc);
108 129
109 IAvatarFactoryModule module = scene.RequestModuleInterface<IAvatarFactoryModule>(); 130 IAvatarFactoryModule module =
131 scene.RequestModuleInterface<IAvatarFactoryModule>();
110 module.SendAppearance(npc.UUID); 132 module.SendAppearance(npc.UUID);
111 133
112 return true; 134 return true;
113 } 135 }
114 136
115 public UUID CreateNPC( 137 public UUID CreateNPC(string firstname, string lastname,
116 string firstname, 138 Vector3 position, UUID owner, bool senseAsAgent, Scene scene,
117 string lastname, 139 AvatarAppearance appearance)
118 Vector3 position,
119 UUID owner,
120 bool senseAsAgent,
121 Scene scene,
122 AvatarAppearance appearance)
123 { 140 {
124 NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, owner, senseAsAgent, scene); 141 NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position,
125 npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, int.MaxValue); 142 owner, senseAsAgent, scene);
143 npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0,
144 int.MaxValue);
126 145
127// m_log.DebugFormat( 146// m_log.DebugFormat(
128// "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}", 147// "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}",
@@ -134,15 +153,20 @@ namespace OpenSim.Region.OptionalModules.World.NPC
134 acd.lastname = lastname; 153 acd.lastname = lastname;
135 acd.ServiceURLs = new Dictionary<string, object>(); 154 acd.ServiceURLs = new Dictionary<string, object>();
136 155
137 AvatarAppearance npcAppearance = new AvatarAppearance(appearance, true); 156 AvatarAppearance npcAppearance = new AvatarAppearance(appearance,
157 true);
138 acd.Appearance = npcAppearance; 158 acd.Appearance = npcAppearance;
139 159
140// for (int i = 0; i < acd.Appearance.Texture.FaceTextures.Length; i++) 160 /*
141// { 161 for (int i = 0;
142// m_log.DebugFormat( 162 i < acd.Appearance.Texture.FaceTextures.Length; i++)
143// "[NPC MODULE]: NPC avatar {0} has texture id {1} : {2}", 163 {
144// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]); 164 m_log.DebugFormat(
145// } 165 "[NPC MODULE]: NPC avatar {0} has texture id {1} : {2}",
166 acd.AgentID, i,
167 acd.Appearance.Texture.FaceTextures[i]);
168 }
169 */
146 170
147 ManualResetEvent ev = new ManualResetEvent(false); 171 ManualResetEvent ev = new ManualResetEvent(false);
148 172
@@ -170,7 +194,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
170 return npcAvatar.AgentId; 194 return npcAvatar.AgentId;
171 } 195 }
172 196
173 public bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, bool noFly, bool landAtTarget, bool running) 197 public bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos,
198 bool noFly, bool landAtTarget, bool running)
174 { 199 {
175 lock (m_avatars) 200 lock (m_avatars)
176 { 201 {
@@ -185,7 +210,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
185 210
186 sp.MoveToTarget(pos, noFly, landAtTarget); 211 sp.MoveToTarget(pos, noFly, landAtTarget);
187 sp.SetAlwaysRun = running; 212 sp.SetAlwaysRun = running;
188 213
189 return true; 214 return true;
190 } 215 }
191 } 216 }
@@ -258,9 +283,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
258 ScenePresence sp; 283 ScenePresence sp;
259 if (scene.TryGetScenePresence(agentID, out sp)) 284 if (scene.TryGetScenePresence(agentID, out sp))
260 { 285 {
261 sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero); 286 sp.HandleAgentRequestSit(m_avatars[agentID], agentID,
262 // sp.HandleAgentSit(m_avatars[agentID], agentID); 287 partID, Vector3.Zero);
263 288 //sp.HandleAgentSit(m_avatars[agentID], agentID);
289
264 return true; 290 return true;
265 } 291 }
266 } 292 }
@@ -269,7 +295,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
269 return false; 295 return false;
270 } 296 }
271 297
272 public bool Whisper(UUID agentID, Scene scene, string text, int channel) 298 public bool Whisper(UUID agentID, Scene scene, string text,
299 int channel)
273 { 300 {
274 lock (m_avatars) 301 lock (m_avatars)
275 { 302 {
@@ -344,7 +371,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
344 NPCAvatar av; 371 NPCAvatar av;
345 if (m_avatars.TryGetValue(agentID, out av)) 372 if (m_avatars.TryGetValue(agentID, out av))
346 { 373 {
347// m_log.DebugFormat("[NPC MODULE]: Found {0} {1} to remove", agentID, av.Name); 374 /*
375 m_log.DebugFormat("[NPC MODULE]: Found {0} {1} to remove",
376 agentID, av.Name);
377 */
348 scene.RemoveClient(agentID, false); 378 scene.RemoveClient(agentID, false);
349 m_avatars.Remove(agentID); 379 m_avatars.Remove(agentID);
350 380
@@ -352,8 +382,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC
352 return true; 382 return true;
353 } 383 }
354 } 384 }
355 385 /*
356// m_log.DebugFormat("[NPC MODULE]: Could not find {0} to remove", agentID); 386 m_log.DebugFormat("[NPC MODULE]: Could not find {0} to remove",
387 agentID);
388 */
357 return false; 389 return false;
358 } 390 }
359 391
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index 9179966..52ed846 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -117,6 +117,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
117 Assert.That(npc, Is.Not.Null); 117 Assert.That(npc, Is.Not.Null);
118 Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId)); 118 Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId));
119 Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname))); 119 Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname)));
120
121 IClientAPI client;
122 Assert.That(m_scene.TryGetClient(npcId, out client), Is.True);
123
124 // Have to account for both SP and NPC.
125 Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(2));
120 } 126 }
121 127
122 [Test] 128 [Test]
@@ -136,6 +142,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
136 ScenePresence deletedNpc = m_scene.GetScenePresence(npcId); 142 ScenePresence deletedNpc = m_scene.GetScenePresence(npcId);
137 143
138 Assert.That(deletedNpc, Is.Null); 144 Assert.That(deletedNpc, Is.Null);
145 IClientAPI client;
146 Assert.That(m_scene.TryGetClient(npcId, out client), Is.False);
147
148 // Have to account for SP still present.
149 Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
139 } 150 }
140 151
141 [Test] 152 [Test]
diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
index 51b0592..8144870 100644
--- a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
+++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs
@@ -31,6 +31,7 @@ using System.Reflection;
31using System.Timers; 31using System.Timers;
32using OpenMetaverse; 32using OpenMetaverse;
33using log4net; 33using log4net;
34using Mono.Addins;
34using Nini.Config; 35using Nini.Config;
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Region.CoreModules.Framework.InterfaceCommander; 37using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
@@ -46,7 +47,8 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
46 /// <summary> 47 /// <summary>
47 /// Version 2.02 - Still hacky 48 /// Version 2.02 - Still hacky
48 /// </summary> 49 /// </summary>
49 public class TreePopulatorModule : IRegionModule, ICommandableModule, IVegetationModule 50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TreePopulatorModule")]
51 public class TreePopulatorModule : INonSharedRegionModule, ICommandableModule, IVegetationModule
50 { 52 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 private readonly Commander m_commander = new Commander("tree"); 54 private readonly Commander m_commander = new Commander("tree");
@@ -168,15 +170,11 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
168 170
169 #endregion 171 #endregion
170 172
171 #region IRegionModule Members 173 #region Region Module interface
172 174
173 public void Initialise(Scene scene, IConfigSource config) 175 public void Initialise(IConfigSource config)
174 { 176 {
175 177
176 m_scene = scene;
177 m_scene.RegisterModuleInterface<IRegionModule>(this);
178 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
179
180 // ini file settings 178 // ini file settings
181 try 179 try
182 { 180 {
@@ -201,7 +199,19 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
201 m_log.Debug("[TREES]: Initialised tree module"); 199 m_log.Debug("[TREES]: Initialised tree module");
202 } 200 }
203 201
204 public void PostInitialise() 202 public void AddRegion(Scene scene)
203 {
204 m_scene = scene;
205 m_scene.RegisterModuleCommander(m_commander);
206 m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole;
207
208 }
209
210 public void RemoveRegion(Scene scene)
211 {
212 }
213
214 public void RegionLoaded(Scene scene)
205 { 215 {
206 ReloadCopse(); 216 ReloadCopse();
207 if (m_copse.Count > 0) 217 if (m_copse.Count > 0)
@@ -220,11 +230,12 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
220 get { return "TreePopulatorModule"; } 230 get { return "TreePopulatorModule"; }
221 } 231 }
222 232
223 public bool IsSharedModule 233 public Type ReplaceableInterface
224 { 234 {
225 get { return false; } 235 get { return null; }
226 } 236 }
227 237
238
228 #endregion 239 #endregion
229 240
230 //-------------------------------------------------------------- 241 //--------------------------------------------------------------
@@ -448,8 +459,6 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator
448 m_commander.RegisterCommand("reload", treeReloadCommand); 459 m_commander.RegisterCommand("reload", treeReloadCommand);
449 m_commander.RegisterCommand("remove", treeRemoveCommand); 460 m_commander.RegisterCommand("remove", treeRemoveCommand);
450 m_commander.RegisterCommand("statistics", treeStatisticsCommand); 461 m_commander.RegisterCommand("statistics", treeStatisticsCommand);
451
452 m_scene.RegisterModuleCommander(m_commander);
453 } 462 }
454 463
455 /// <summary> 464 /// <summary>
diff --git a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs
index 1aee39a..baf55c3 100644
--- a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs
+++ b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewModule.cs
@@ -32,6 +32,7 @@ using System.Drawing.Imaging;
32using System.Reflection; 32using System.Reflection;
33using System.IO; 33using System.IO;
34using log4net; 34using log4net;
35using Mono.Addins;
35using Nini.Config; 36using Nini.Config;
36using OpenMetaverse; 37using OpenMetaverse;
37using OpenMetaverse.Imaging; 38using OpenMetaverse.Imaging;
@@ -45,6 +46,7 @@ using OpenSim.Services.Interfaces;
45 46
46namespace OpenSim.Region.OptionalModules.World.WorldView 47namespace OpenSim.Region.OptionalModules.World.WorldView
47{ 48{
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WorldViewModule")]
48 public class WorldViewModule : INonSharedRegionModule 50 public class WorldViewModule : INonSharedRegionModule
49 { 51 {
50 private static readonly ILog m_log = 52 private static readonly ILog m_log =
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs
index 063eb54..fb9cb66 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs
@@ -39,7 +39,7 @@ using System.Runtime.InteropServices;
39[assembly : AssemblyConfiguration("")] 39[assembly : AssemblyConfiguration("")]
40[assembly : AssemblyCompany("http://opensimulator.org")] 40[assembly : AssemblyCompany("http://opensimulator.org")]
41[assembly : AssemblyProduct("BasicPhysicsPlugin")] 41[assembly : AssemblyProduct("BasicPhysicsPlugin")]
42[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")] 42[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")]
43[assembly : AssemblyTrademark("")] 43[assembly : AssemblyTrademark("")]
44[assembly : AssemblyCulture("")] 44[assembly : AssemblyCulture("")]
45 45
@@ -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.6.5.*")] 58[assembly : AssemblyVersion("0.7.5.*")]
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index e2f7af9..4c195e1 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -28,62 +28,48 @@ using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using log4net; 30using log4net;
31using OpenMetaverse; 31using OMV = OpenMetaverse;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager; 33using OpenSim.Region.Physics.Manager;
34 34
35namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37public class BSCharacter : PhysicsActor 37public sealed class BSCharacter : BSPhysObject
38{ 38{
39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 private static readonly string LogHeader = "[BULLETS CHAR]"; 40 private static readonly string LogHeader = "[BULLETS CHAR]";
41 41
42 private BSScene _scene;
43 public BSScene Scene { get { return _scene; } }
44 private String _avName;
45 // private bool _stopped; 42 // private bool _stopped;
46 private Vector3 _size; 43 private OMV.Vector3 _size;
47 private Vector3 _scale;
48 private PrimitiveBaseShape _pbs;
49 private uint _localID = 0;
50 private bool _grabbed; 44 private bool _grabbed;
51 private bool _selected; 45 private bool _selected;
52 private Vector3 _position; 46 private OMV.Vector3 _position;
53 private float _mass; 47 private float _mass;
54 public float _density; 48 private float _avatarDensity;
55 public float _avatarVolume; 49 private float _avatarVolume;
56 private Vector3 _force; 50 private OMV.Vector3 _force;
57 private Vector3 _velocity; 51 private OMV.Vector3 _velocity;
58 private Vector3 _torque; 52 private OMV.Vector3 _torque;
59 private float _collisionScore; 53 private float _collisionScore;
60 private Vector3 _acceleration; 54 private OMV.Vector3 _acceleration;
61 private Quaternion _orientation; 55 private OMV.Quaternion _orientation;
62 private int _physicsActorType; 56 private int _physicsActorType;
63 private bool _isPhysical; 57 private bool _isPhysical;
64 private bool _flying; 58 private bool _flying;
65 private bool _setAlwaysRun; 59 private bool _setAlwaysRun;
66 private bool _throttleUpdates; 60 private bool _throttleUpdates;
67 private bool _isColliding; 61 private bool _isColliding;
68 private long _collidingStep;
69 private bool _collidingGround;
70 private long _collidingGroundStep;
71 private bool _collidingObj; 62 private bool _collidingObj;
72 private bool _floatOnWater; 63 private bool _floatOnWater;
73 private Vector3 _rotationalVelocity; 64 private OMV.Vector3 _rotationalVelocity;
74 private bool _kinematic; 65 private bool _kinematic;
75 private float _buoyancy; 66 private float _buoyancy;
76 67
77 private BulletBody m_body; 68 // The friction and velocity of the avatar is modified depending on whether walking or not.
78 public BulletBody Body { 69 private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar
79 get { return m_body; } 70 private float _currentFriction; // the friction currently being used (changed by setVelocity).
80 set { m_body = value; }
81 }
82
83 private int _subscribedEventsMs = 0;
84 private int _nextCollisionOkTime = 0;
85 71
86 private Vector3 _PIDTarget; 72 private OMV.Vector3 _PIDTarget;
87 private bool _usePID; 73 private bool _usePID;
88 private float _PIDTau; 74 private float _PIDTau;
89 private bool _useHoverPID; 75 private bool _useHoverPID;
@@ -91,332 +77,529 @@ public class BSCharacter : PhysicsActor
91 private PIDHoverType _PIDHoverType; 77 private PIDHoverType _PIDHoverType;
92 private float _PIDHoverTao; 78 private float _PIDHoverTao;
93 79
94 public BSCharacter(uint localID, String avName, BSScene parent_scene, Vector3 pos, Vector3 size, bool isFlying) 80 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
81 : base(parent_scene, localID, avName, "BSCharacter")
95 { 82 {
96 _localID = localID; 83 _physicsActorType = (int)ActorTypes.Agent;
97 _avName = avName;
98 _scene = parent_scene;
99 _position = pos; 84 _position = pos;
85
86 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
87 // replace with the default values.
100 _size = size; 88 _size = size;
89 if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth;
90 if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth;
91
101 _flying = isFlying; 92 _flying = isFlying;
102 _orientation = Quaternion.Identity; 93 _orientation = OMV.Quaternion.Identity;
103 _velocity = Vector3.Zero; 94 _velocity = OMV.Vector3.Zero;
95 _appliedVelocity = OMV.Vector3.Zero;
104 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 96 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
97 _currentFriction = PhysicsScene.Params.avatarStandingFriction;
98 _avatarDensity = PhysicsScene.Params.avatarDensity;
99
105 // The dimensions of the avatar capsule are kept in the scale. 100 // The dimensions of the avatar capsule are kept in the scale.
106 // Physics creates a unit capsule which is scaled by the physics engine. 101 // Physics creates a unit capsule which is scaled by the physics engine.
107 _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z); 102 ComputeAvatarScale(_size);
108 _density = _scene.Params.avatarDensity; 103 // set _avatarVolume and _mass based on capsule size, _density and Scale
109 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale 104 ComputeAvatarVolumeAndMass();
110 105 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
111 ShapeData shapeData = new ShapeData(); 106 LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
112 shapeData.ID = _localID;
113 shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
114 shapeData.Position = _position;
115 shapeData.Rotation = _orientation;
116 shapeData.Velocity = _velocity;
117 shapeData.Scale = _scale;
118 shapeData.Mass = _mass;
119 shapeData.Buoyancy = _buoyancy;
120 shapeData.Static = ShapeData.numericFalse;
121 shapeData.Friction = _scene.Params.avatarFriction;
122 shapeData.Restitution = _scene.Params.avatarRestitution;
123 107
124 // do actual create at taint time 108 // do actual create at taint time
125 _scene.TaintedObject("BSCharacter.create", delegate() 109 PhysicsScene.TaintedObject("BSCharacter.create", delegate()
126 { 110 {
127 BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); 111 DetailLog("{0},BSCharacter.create,taint", LocalID);
112 // New body and shape into PhysBody and PhysShape
113 PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null);
128 114
129 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); 115 SetPhysicalProperties();
130 // avatars get all collisions no matter what
131 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
132 }); 116 });
133
134 return; 117 return;
135 } 118 }
136 119
137 // called when this character is being destroyed and the resources should be released 120 // called when this character is being destroyed and the resources should be released
138 public void Destroy() 121 public override void Destroy()
139 { 122 {
140 // DetailLog("{0},BSCharacter.Destroy", LocalID); 123 DetailLog("{0},BSCharacter.Destroy", LocalID);
141 _scene.TaintedObject("BSCharacter.destroy", delegate() 124 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
142 { 125 {
143 BulletSimAPI.DestroyObject(_scene.WorldID, _localID); 126 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
127 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
144 }); 128 });
145 } 129 }
146 130
131 private void SetPhysicalProperties()
132 {
133 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
134
135 ZeroMotion(true);
136 ForcePosition = _position;
137 // Set the velocity and compute the proper friction
138 ForceVelocity = _velocity;
139
140 // This will enable or disable the flying buoyancy of the avatar.
141 // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
142 Flying = _flying;
143
144 BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution);
145 BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin);
146 BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
147 BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
148 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
149 {
150 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
151 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
152 }
153
154 UpdatePhysicalMassProperties(RawMass);
155
156 // Make so capsule does not fall over
157 BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero);
158
159 BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT);
160
161 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
162
163 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG);
164 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_DEACTIVATION);
165 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
166
167 // Do this after the object has been added to the world
168 BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr,
169 (uint)CollisionFilterGroups.AvatarFilter,
170 (uint)CollisionFilterGroups.AvatarMask);
171 }
172
147 public override void RequestPhysicsterseUpdate() 173 public override void RequestPhysicsterseUpdate()
148 { 174 {
149 base.RequestPhysicsterseUpdate(); 175 base.RequestPhysicsterseUpdate();
150 } 176 }
151 // No one calls this method so I don't know what it could possibly mean 177 // No one calls this method so I don't know what it could possibly mean
152 public override bool Stopped { 178 public override bool Stopped { get { return false; } }
153 get { return false; } 179
154 } 180 public override OMV.Vector3 Size {
155 public override Vector3 Size {
156 get 181 get
157 { 182 {
158 // Avatar capsule size is kept in the scale parameter. 183 // Avatar capsule size is kept in the scale parameter.
159 return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); 184 return _size;
160 } 185 }
161 186
162 set { 187 set {
163 // When an avatar's size is set, only the height is changed 188 // When an avatar's size is set, only the height is changed.
164 // and that really only depends on the radius.
165 _size = value; 189 _size = value;
166 _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); 190 ComputeAvatarScale(_size);
167
168 // TODO: something has to be done with the avatar's vertical position
169
170 ComputeAvatarVolumeAndMass(); 191 ComputeAvatarVolumeAndMass();
192 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
193 LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
171 194
172 _scene.TaintedObject("BSCharacter.setSize", delegate() 195 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
173 { 196 {
174 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true); 197 BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
198 UpdatePhysicalMassProperties(RawMass);
175 }); 199 });
176 200
177 } 201 }
178 } 202 }
179 public override PrimitiveBaseShape Shape { 203
180 set { _pbs = value; 204 public override OMV.Vector3 Scale { get; set; }
181 } 205
206 public override PrimitiveBaseShape Shape
207 {
208 set { BaseShape = value; }
182 } 209 }
183 public override uint LocalID { 210 // I want the physics engine to make an avatar capsule
184 set { _localID = value; 211 public override BSPhysicsShapeType PreferredPhysicalShape
185 } 212 {
186 get { return _localID; } 213 get {return BSPhysicsShapeType.SHAPE_CAPSULE; }
187 } 214 }
188 public override bool Grabbed { 215
189 set { _grabbed = value; 216 public override bool Grabbed {
190 } 217 set { _grabbed = value; }
191 } 218 }
192 public override bool Selected { 219 public override bool Selected {
193 set { _selected = value; 220 set { _selected = value; }
194 }
195 } 221 }
196 public override void CrossingFailure() { return; } 222 public override void CrossingFailure() { return; }
197 public override void link(PhysicsActor obj) { return; } 223 public override void link(PhysicsActor obj) { return; }
198 public override void delink() { return; } 224 public override void delink() { return; }
199 public override void LockAngularMotion(Vector3 axis) { return; }
200 225
201 public override Vector3 Position { 226 // Set motion values to zero.
227 // Do it to the properties so the values get set in the physics engine.
228 // Push the setting of the values to the viewer.
229 // Called at taint time!
230 public override void ZeroMotion(bool inTaintTime)
231 {
232 _velocity = OMV.Vector3.Zero;
233 _acceleration = OMV.Vector3.Zero;
234 _rotationalVelocity = OMV.Vector3.Zero;
235
236 // Zero some other properties directly into the physics engine
237 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
238 {
239 BulletSimAPI.ClearAllForces2(PhysBody.ptr);
240 });
241 }
242 public override void ZeroAngularMotion(bool inTaintTime)
243 {
244 _rotationalVelocity = OMV.Vector3.Zero;
245
246 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
247 {
248 BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
249 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
250 // The next also get rid of applied linear force but the linear velocity is untouched.
251 BulletSimAPI.ClearForces2(PhysBody.ptr);
252 });
253 }
254
255
256 public override void LockAngularMotion(OMV.Vector3 axis) { return; }
257
258 public override OMV.Vector3 RawPosition
259 {
260 get { return _position; }
261 set { _position = value; }
262 }
263 public override OMV.Vector3 Position {
202 get { 264 get {
203 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 265 // Don't refetch the position because this function is called a zillion times
204 return _position; 266 // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID);
205 } 267 return _position;
268 }
206 set { 269 set {
207 _position = value; 270 _position = value;
208 PositionSanityCheck(); 271 PositionSanityCheck();
209 272
210 _scene.TaintedObject("BSCharacter.setPosition", delegate() 273 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
211 { 274 {
212 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 275 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
213 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 276 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
214 }); 277 });
215 } 278 }
279 }
280 public override OMV.Vector3 ForcePosition {
281 get {
282 _position = BulletSimAPI.GetPosition2(PhysBody.ptr);
283 return _position;
284 }
285 set {
286 _position = value;
287 PositionSanityCheck();
288 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
289 }
216 } 290 }
217 291
292
218 // Check that the current position is sane and, if not, modify the position to make it so. 293 // Check that the current position is sane and, if not, modify the position to make it so.
219 // Check for being below terrain and being out of bounds. 294 // Check for being below terrain or on water.
220 // Returns 'true' of the position was made sane by some action. 295 // Returns 'true' of the position was made sane by some action.
221 private bool PositionSanityCheck() 296 private bool PositionSanityCheck()
222 { 297 {
223 bool ret = false; 298 bool ret = false;
224 299
225 // If below the ground, move the avatar up 300 // If below the ground, move the avatar up
226 float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); 301 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
227 if (_position.Z < terrainHeight) 302 if (Position.Z < terrainHeight)
228 { 303 {
229 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); 304 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
230 _position.Z = terrainHeight + 2.0f; 305 _position.Z = terrainHeight + 2.0f;
231 ret = true; 306 ret = true;
232 } 307 }
308 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
309 {
310 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
311 if (Position.Z < waterHeight)
312 {
313 _position.Z = waterHeight;
314 ret = true;
315 }
316 }
233 317
234 // TODO: check for out of bounds 318 // TODO: check for out of bounds
319 return ret;
320 }
235 321
322 // A version of the sanity check that also makes sure a new position value is
323 // pushed back to the physics engine. This routine would be used by anyone
324 // who is not already pushing the value.
325 private bool PositionSanityCheck(bool inTaintTime)
326 {
327 bool ret = false;
328 if (PositionSanityCheck())
329 {
330 // The new position value must be pushed into the physics engine but we can't
331 // just assign to "Position" because of potential call loops.
332 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
333 {
334 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
335 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
336 });
337 ret = true;
338 }
236 return ret; 339 return ret;
237 } 340 }
238 341
239 public override float Mass { 342 public override float Mass { get { return _mass; } }
240 get { 343
241 return _mass; 344 // used when we only want this prim's mass and not the linkset thing
242 } 345 public override float RawMass {
346 get {return _mass; }
243 } 347 }
244 public override Vector3 Force { 348 public override void UpdatePhysicalMassProperties(float physMass)
245 get { return _force; } 349 {
350 OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
351 BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia);
352 }
353
354 public override OMV.Vector3 Force {
355 get { return _force; }
246 set { 356 set {
247 _force = value; 357 _force = value;
248 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 358 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
249 Scene.TaintedObject("BSCharacter.SetForce", delegate() 359 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
250 { 360 {
251 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); 361 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
252 BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force); 362 BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
253 }); 363 });
254 } 364 }
255 } 365 }
256 366
257 public override int VehicleType { 367 // Avatars don't do vehicles
258 get { return 0; } 368 public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } }
259 set { return; }
260 }
261 public override void VehicleFloatParam(int param, float value) { } 369 public override void VehicleFloatParam(int param, float value) { }
262 public override void VehicleVectorParam(int param, Vector3 value) {} 370 public override void VehicleVectorParam(int param, OMV.Vector3 value) {}
263 public override void VehicleRotationParam(int param, Quaternion rotation) { } 371 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { }
264 public override void VehicleFlags(int param, bool remove) { } 372 public override void VehicleFlags(int param, bool remove) { }
265 373
266 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 374 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
267 public override void SetVolumeDetect(int param) { return; } 375 public override void SetVolumeDetect(int param) { return; }
268 376
269 public override Vector3 GeometricCenter { get { return Vector3.Zero; } } 377 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
270 public override Vector3 CenterOfMass { get { return Vector3.Zero; } } 378 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
271 public override Vector3 Velocity { 379 public override OMV.Vector3 Velocity {
272 get { return _velocity; } 380 get { return _velocity; }
273 set { 381 set {
274 _velocity = value; 382 _velocity = value;
275 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 383 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
276 _scene.TaintedObject("BSCharacter.setVelocity", delegate() 384 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
277 { 385 {
278 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); 386 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
279 BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); 387 ForceVelocity = _velocity;
280 }); 388 });
281 } 389 }
282 } 390 }
283 public override Vector3 Torque { 391 public override OMV.Vector3 ForceVelocity {
284 get { return _torque; } 392 get { return _velocity; }
285 set { _torque = value; 393 set {
286 } 394 // Depending on whether the avatar is moving or not, change the friction
395 // to keep the avatar from slipping around
396 if (_velocity.Length() == 0)
397 {
398 if (_currentFriction != PhysicsScene.Params.avatarStandingFriction)
399 {
400 _currentFriction = PhysicsScene.Params.avatarStandingFriction;
401 BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
402 }
403 }
404 else
405 {
406 if (_currentFriction != PhysicsScene.Params.avatarFriction)
407 {
408 _currentFriction = PhysicsScene.Params.avatarFriction;
409 BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
410 }
411 }
412 _velocity = value;
413 // Remember the set velocity so we can suppress the reduction by friction, ...
414 _appliedVelocity = value;
415
416 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
417 BulletSimAPI.Activate2(PhysBody.ptr, true);
418 }
287 } 419 }
288 public override float CollisionScore { 420 public override OMV.Vector3 Torque {
289 get { return _collisionScore; } 421 get { return _torque; }
290 set { _collisionScore = value; 422 set { _torque = value;
291 } 423 }
424 }
425 public override float CollisionScore {
426 get { return _collisionScore; }
427 set { _collisionScore = value;
428 }
292 } 429 }
293 public override Vector3 Acceleration { 430 public override OMV.Vector3 Acceleration {
294 get { return _acceleration; } 431 get { return _acceleration; }
295 set { _acceleration = value; } 432 set { _acceleration = value; }
296 } 433 }
297 public override Quaternion Orientation { 434 public override OMV.Quaternion RawOrientation
298 get { return _orientation; } 435 {
436 get { return _orientation; }
437 set { _orientation = value; }
438 }
439 public override OMV.Quaternion Orientation {
440 get { return _orientation; }
299 set { 441 set {
300 _orientation = value; 442 _orientation = value;
301 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); 443 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
302 _scene.TaintedObject("BSCharacter.setOrientation", delegate() 444 PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate()
303 { 445 {
304 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 446 // _position = BulletSimAPI.GetPosition2(BSBody.ptr);
305 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 447 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
306 }); 448 });
307 } 449 }
308 } 450 }
309 public override int PhysicsActorType { 451 // Go directly to Bullet to get/set the value.
310 get { return _physicsActorType; } 452 public override OMV.Quaternion ForceOrientation
311 set { _physicsActorType = value; 453 {
312 } 454 get
455 {
456 _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr);
457 return _orientation;
458 }
459 set
460 {
461 _orientation = value;
462 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
463 }
313 } 464 }
314 public override bool IsPhysical { 465 public override int PhysicsActorType {
315 get { return _isPhysical; } 466 get { return _physicsActorType; }
467 set { _physicsActorType = value;
468 }
469 }
470 public override bool IsPhysical {
471 get { return _isPhysical; }
316 set { _isPhysical = value; 472 set { _isPhysical = value;
317 } 473 }
474 }
475 public override bool IsSolid {
476 get { return true; }
318 } 477 }
319 public override bool Flying { 478 public override bool IsStatic {
320 get { return _flying; } 479 get { return false; }
480 }
481 public override bool Flying {
482 get { return _flying; }
321 set { 483 set {
322 if (_flying != value) 484 _flying = value;
323 { 485 // simulate flying by changing the effect of gravity
324 _flying = value; 486 Buoyancy = ComputeBuoyancyFromFlying(_flying);
325 // simulate flying by changing the effect of gravity 487 }
326 this.Buoyancy = ComputeBuoyancyFromFlying(_flying);
327 }
328 }
329 } 488 }
489 // Flying is implimented by changing the avatar's buoyancy.
490 // Would this be done better with a vehicle type?
330 private float ComputeBuoyancyFromFlying(bool ifFlying) { 491 private float ComputeBuoyancyFromFlying(bool ifFlying) {
331 return ifFlying ? 1f : 0f; 492 return ifFlying ? 1f : 0f;
332 } 493 }
333 public override bool 494 public override bool
334 SetAlwaysRun { 495 SetAlwaysRun {
335 get { return _setAlwaysRun; } 496 get { return _setAlwaysRun; }
336 set { _setAlwaysRun = value; } 497 set { _setAlwaysRun = value; }
337 } 498 }
338 public override bool ThrottleUpdates { 499 public override bool ThrottleUpdates {
339 get { return _throttleUpdates; } 500 get { return _throttleUpdates; }
340 set { _throttleUpdates = value; } 501 set { _throttleUpdates = value; }
341 } 502 }
342 public override bool IsColliding { 503 public override bool IsColliding {
343 get { return (_collidingStep == _scene.SimulationStep); } 504 get { return (CollidingStep == PhysicsScene.SimulationStep); }
344 set { _isColliding = value; } 505 set { _isColliding = value; }
345 } 506 }
346 public override bool CollidingGround { 507 public override bool CollidingGround {
347 get { return (_collidingGroundStep == _scene.SimulationStep); } 508 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
348 set { _collidingGround = value; } 509 set { CollidingGround = value; }
349 } 510 }
350 public override bool CollidingObj { 511 public override bool CollidingObj {
351 get { return _collidingObj; } 512 get { return _collidingObj; }
352 set { _collidingObj = value; } 513 set { _collidingObj = value; }
353 } 514 }
354 public override bool FloatOnWater { 515 public override bool FloatOnWater {
355 set { _floatOnWater = value; } 516 set {
517 _floatOnWater = value;
518 PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
519 {
520 if (_floatOnWater)
521 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
522 else
523 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
524 });
525 }
526 }
527 public override OMV.Vector3 RotationalVelocity {
528 get { return _rotationalVelocity; }
529 set { _rotationalVelocity = value; }
356 } 530 }
357 public override Vector3 RotationalVelocity { 531 public override OMV.Vector3 ForceRotationalVelocity {
358 get { return _rotationalVelocity; } 532 get { return _rotationalVelocity; }
359 set { _rotationalVelocity = value; } 533 set { _rotationalVelocity = value; }
360 } 534 }
361 public override bool Kinematic { 535 public override bool Kinematic {
362 get { return _kinematic; } 536 get { return _kinematic; }
363 set { _kinematic = value; } 537 set { _kinematic = value; }
364 } 538 }
365 // neg=fall quickly, 0=1g, 1=0g, pos=float up 539 // neg=fall quickly, 0=1g, 1=0g, pos=float up
366 public override float Buoyancy { 540 public override float Buoyancy {
367 get { return _buoyancy; } 541 get { return _buoyancy; }
368 set { _buoyancy = value; 542 set { _buoyancy = value;
369 _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() 543 PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate()
370 { 544 {
371 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 545 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
372 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); 546 ForceBuoyancy = _buoyancy;
373 }); 547 });
374 } 548 }
549 }
550 public override float ForceBuoyancy {
551 get { return _buoyancy; }
552 set { _buoyancy = value;
553 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
554 // Buoyancy is faked by changing the gravity applied to the object
555 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
556 BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
557 }
375 } 558 }
376 559
377 // Used for MoveTo 560 // Used for MoveTo
378 public override Vector3 PIDTarget { 561 public override OMV.Vector3 PIDTarget {
379 set { _PIDTarget = value; } 562 set { _PIDTarget = value; }
380 } 563 }
381 public override bool PIDActive { 564 public override bool PIDActive {
382 set { _usePID = value; } 565 set { _usePID = value; }
383 } 566 }
384 public override float PIDTau { 567 public override float PIDTau {
385 set { _PIDTau = value; } 568 set { _PIDTau = value; }
386 } 569 }
387 570
388 // Used for llSetHoverHeight and maybe vehicle height 571 // Used for llSetHoverHeight and maybe vehicle height
389 // Hover Height will override MoveTo target's Z 572 // Hover Height will override MoveTo target's Z
390 public override bool PIDHoverActive { 573 public override bool PIDHoverActive {
391 set { _useHoverPID = value; } 574 set { _useHoverPID = value; }
392 } 575 }
393 public override float PIDHoverHeight { 576 public override float PIDHoverHeight {
394 set { _PIDHoverHeight = value; } 577 set { _PIDHoverHeight = value; }
395 } 578 }
396 public override PIDHoverType PIDHoverType { 579 public override PIDHoverType PIDHoverType {
397 set { _PIDHoverType = value; } 580 set { _PIDHoverType = value; }
398 } 581 }
399 public override float PIDHoverTau { 582 public override float PIDHoverTau {
400 set { _PIDHoverTao = value; } 583 set { _PIDHoverTao = value; }
401 } 584 }
402 585
403 // For RotLookAt 586 // For RotLookAt
404 public override Quaternion APIDTarget { set { return; } } 587 public override OMV.Quaternion APIDTarget { set { return; } }
405 public override bool APIDActive { set { return; } } 588 public override bool APIDActive { set { return; } }
406 public override float APIDStrength { set { return; } } 589 public override float APIDStrength { set { return; } }
407 public override float APIDDamping { set { return; } } 590 public override float APIDDamping { set { return; } }
408 591
409 public override void AddForce(Vector3 force, bool pushforce) { 592 public override void AddForce(OMV.Vector3 force, bool pushforce) {
410 if (force.IsFinite()) 593 if (force.IsFinite())
411 { 594 {
412 _force.X += force.X; 595 _force.X += force.X;
413 _force.Y += force.Y; 596 _force.Y += force.Y;
414 _force.Z += force.Z; 597 _force.Z += force.Z;
415 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); 598 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
416 _scene.TaintedObject("BSCharacter.AddForce", delegate() 599 PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate()
417 { 600 {
418 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); 601 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
419 BulletSimAPI.AddObjectForce2(Body.Ptr, _force); 602 BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
420 }); 603 });
421 } 604 }
422 else 605 else
@@ -426,129 +609,81 @@ public class BSCharacter : PhysicsActor
426 //m_lastUpdateSent = false; 609 //m_lastUpdateSent = false;
427 } 610 }
428 611
429 public override void AddAngularForce(Vector3 force, bool pushforce) { 612 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
430 } 613 }
431 public override void SetMomentum(Vector3 momentum) { 614 public override void SetMomentum(OMV.Vector3 momentum) {
432 } 615 }
433 616
434 // Turn on collision events at a rate no faster than one every the given milliseconds 617 private void ComputeAvatarScale(OMV.Vector3 size)
435 public override void SubscribeEvents(int ms) { 618 {
436 _subscribedEventsMs = ms; 619 // The 'size' given by the simulator is the mid-point of the avatar
437 if (ms > 0) 620 // and X and Y are unspecified.
438 {
439 // make sure first collision happens
440 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
441 621
442 Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate() 622 OMV.Vector3 newScale = size;
443 { 623 // newScale.X = PhysicsScene.Params.avatarCapsuleWidth;
444 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 624 // newScale.Y = PhysicsScene.Params.avatarCapsuleDepth;
445 }); 625
446 } 626 // From the total height, remove the capsule half spheres that are at each end
447 } 627 // The 1.15f came from ODE. Not sure what this factors in.
448 // Stop collision events 628 // newScale.Z = (size.Z * 1.15f) - (newScale.X + newScale.Y);
449 public override void UnSubscribeEvents() { 629
450 _subscribedEventsMs = 0; 630 // The total scale height is the central cylindar plus the caps on the two ends.
451 // Avatars get all their collision events 631 newScale.Z = size.Z + (Math.Min(size.X, size.Y) * 2f);
452 // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate() 632
453 // { 633 // Convert diameters to radii and height to half height -- the way Bullet expects it.
454 // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 634 Scale = newScale / 2f;
455 // });
456 }
457 // Return 'true' if someone has subscribed to events
458 public override bool SubscribedEvents() {
459 return (_subscribedEventsMs > 0);
460 } 635 }
461 636
462 // set _avatarVolume and _mass based on capsule size, _density and _scale 637 // set _avatarVolume and _mass based on capsule size, _density and Scale
463 private void ComputeAvatarVolumeAndMass() 638 private void ComputeAvatarVolumeAndMass()
464 { 639 {
465 _avatarVolume = (float)( 640 _avatarVolume = (float)(
466 Math.PI 641 Math.PI
467 * _scale.X 642 * Scale.X
468 * _scale.Y // the area of capsule cylinder 643 * Scale.Y // the area of capsule cylinder
469 * _scale.Z // times height of capsule cylinder 644 * Scale.Z // times height of capsule cylinder
470 + 1.33333333f 645 + 1.33333333f
471 * Math.PI 646 * Math.PI
472 * _scale.X 647 * Scale.X
473 * Math.Min(_scale.X, _scale.Y) 648 * Math.Min(Scale.X, Scale.Y)
474 * _scale.Y // plus the volume of the capsule end caps 649 * Scale.Y // plus the volume of the capsule end caps
475 ); 650 );
476 _mass = _density * _avatarVolume; 651 _mass = _avatarDensity * _avatarVolume;
477 } 652 }
478 653
479 // The physics engine says that properties have updated. Update same and inform 654 // The physics engine says that properties have updated. Update same and inform
480 // the world that things have changed. 655 // the world that things have changed.
481 public void UpdateProperties(EntityProperties entprop) 656 public override void UpdateProperties(EntityProperties entprop)
482 { 657 {
483 _position = entprop.Position; 658 _position = entprop.Position;
484 _orientation = entprop.Rotation; 659 _orientation = entprop.Rotation;
485 _velocity = entprop.Velocity; 660 _velocity = entprop.Velocity;
486 _acceleration = entprop.Acceleration; 661 _acceleration = entprop.Acceleration;
487 _rotationalVelocity = entprop.RotationalVelocity; 662 _rotationalVelocity = entprop.RotationalVelocity;
488 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. 663 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
489 // base.RequestPhysicsterseUpdate(); 664 PositionSanityCheck(true);
490 665
491 /* 666 // remember the current and last set values
492 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 667 LastEntityProperties = CurrentEntityProperties;
493 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 668 CurrentEntityProperties = entprop;
494 entprop.Acceleration, entprop.RotationalVelocity);
495 */
496 }
497 669
498 // Called by the scene when a collision with this object is reported 670 if (entprop.Velocity != LastEntityProperties.Velocity)
499 // The collision, if it should be reported to the character, is placed in a collection
500 // that will later be sent to the simulator when SendCollisions() is called.
501 CollisionEventUpdate collisionCollection = null;
502 public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
503 {
504 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
505
506 // The following makes IsColliding() and IsCollidingGround() work
507 _collidingStep = _scene.SimulationStep;
508 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
509 { 671 {
510 _collidingGroundStep = _scene.SimulationStep; 672 // Changes in the velocity are suppressed in avatars.
673 // That's just the way they are defined.
674 OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z);
675 _velocity = avVel;
676 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel);
511 } 677 }
512 // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
513 678
514 // throttle collisions to the rate specified in the subscription 679 // Tell the linkset about value changes
515 if (_subscribedEventsMs != 0) { 680 Linkset.UpdateProperties(this);
516 int nowTime = _scene.SimulationNowTime;
517 if (nowTime >= _nextCollisionOkTime) {
518 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
519 681
520 if (collisionCollection == null) 682 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
521 collisionCollection = new CollisionEventUpdate(); 683 // base.RequestPhysicsterseUpdate();
522 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
523 }
524 }
525 }
526 684
527 public void SendCollisions() 685 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
528 { 686 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
529 /*
530 if (collisionCollection != null && collisionCollection.Count > 0)
531 {
532 base.SendCollisionUpdate(collisionCollection);
533 collisionCollection = null;
534 }
535 */
536 // Kludge to make a collision call even if there are no collisions.
537 // This causes the avatar animation to get updated.
538 if (collisionCollection == null)
539 collisionCollection = new CollisionEventUpdate();
540 base.SendCollisionUpdate(collisionCollection);
541 // If there were any collisions in the collection, make sure we don't use the
542 // same instance next time.
543 if (collisionCollection.Count > 0)
544 collisionCollection = null;
545 // End kludge
546 }
547
548 // Invoke the detailed logger and output something if it's enabled.
549 private void DetailLog(string msg, params Object[] args)
550 {
551 Scene.PhysicsLogging.Write(msg, args);
552 } 687 }
553} 688}
554} 689}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index 25084d8..65fac00 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -34,12 +34,20 @@ namespace OpenSim.Region.Physics.BulletSPlugin
34 34
35public abstract class BSConstraint : IDisposable 35public abstract class BSConstraint : IDisposable
36{ 36{
37 private static string LogHeader = "[BULLETSIM CONSTRAINT]";
38
37 protected BulletSim m_world; 39 protected BulletSim m_world;
38 protected BulletBody m_body1; 40 protected BulletBody m_body1;
39 protected BulletBody m_body2; 41 protected BulletBody m_body2;
40 protected BulletConstraint m_constraint; 42 protected BulletConstraint m_constraint;
41 protected bool m_enabled = false; 43 protected bool m_enabled = false;
42 44
45 public BulletBody Body1 { get { return m_body1; } }
46 public BulletBody Body2 { get { return m_body2; } }
47 public BulletConstraint Constraint { get { return m_constraint; } }
48 public abstract ConstraintType Type { get; }
49 public bool IsEnabled { get { return m_enabled; } }
50
43 public BSConstraint() 51 public BSConstraint()
44 { 52 {
45 } 53 }
@@ -48,22 +56,25 @@ public abstract class BSConstraint : IDisposable
48 { 56 {
49 if (m_enabled) 57 if (m_enabled)
50 { 58 {
51 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
52 bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
53 m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success);
54 m_constraint.Ptr = System.IntPtr.Zero;
55 m_enabled = false; 59 m_enabled = false;
60 if (m_constraint.ptr != IntPtr.Zero)
61 {
62 bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr);
63 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
64 BSScene.DetailLogZero,
65 m_body1.ID, m_body1.ptr.ToString("X"),
66 m_body2.ID, m_body2.ptr.ToString("X"),
67 success);
68 m_constraint.ptr = System.IntPtr.Zero;
69 }
56 } 70 }
57 } 71 }
58 72
59 public BulletBody Body1 { get { return m_body1; } }
60 public BulletBody Body2 { get { return m_body2; } }
61
62 public virtual bool SetLinearLimits(Vector3 low, Vector3 high) 73 public virtual bool SetLinearLimits(Vector3 low, Vector3 high)
63 { 74 {
64 bool ret = false; 75 bool ret = false;
65 if (m_enabled) 76 if (m_enabled)
66 ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high); 77 ret = BulletSimAPI.SetLinearLimits2(m_constraint.ptr, low, high);
67 return ret; 78 return ret;
68 } 79 }
69 80
@@ -71,7 +82,18 @@ public abstract class BSConstraint : IDisposable
71 { 82 {
72 bool ret = false; 83 bool ret = false;
73 if (m_enabled) 84 if (m_enabled)
74 ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high); 85 ret = BulletSimAPI.SetAngularLimits2(m_constraint.ptr, low, high);
86 return ret;
87 }
88
89 public virtual bool SetSolverIterations(float cnt)
90 {
91 bool ret = false;
92 if (m_enabled)
93 {
94 BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.ptr, cnt);
95 ret = true;
96 }
75 return ret; 97 return ret;
76 } 98 }
77 99
@@ -81,7 +103,7 @@ public abstract class BSConstraint : IDisposable
81 if (m_enabled) 103 if (m_enabled)
82 { 104 {
83 // Recompute the internal transforms 105 // Recompute the internal transforms
84 BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); 106 BulletSimAPI.CalculateTransforms2(m_constraint.ptr);
85 ret = true; 107 ret = true;
86 } 108 }
87 return ret; 109 return ret;
@@ -97,13 +119,14 @@ public abstract class BSConstraint : IDisposable
97 ret = CalculateTransforms(); 119 ret = CalculateTransforms();
98 if (ret) 120 if (ret)
99 { 121 {
100 // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}", 122 // Setting an object's mass to zero (making it static like when it's selected)
101 // BSScene.DetailLogZero, Body1.ID, Body2.ID); 123 // automatically disables the constraints.
102 BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); 124 // If the link is enabled, be sure to set the constraint itself to enabled.
125 BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, m_world.physicsScene.NumericBool(true));
103 } 126 }
104 else 127 else
105 { 128 {
106 m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID); 129 m_world.physicsScene.Logger.ErrorFormat("{0} CalculateTransforms failed. A={1}, B={2}", LogHeader, Body1.ID, Body2.ID);
107 } 130 }
108 } 131 }
109 return ret; 132 return ret;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
index 683bc51..23ef052 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
@@ -32,10 +32,14 @@ using OpenMetaverse;
32namespace OpenSim.Region.Physics.BulletSPlugin 32namespace OpenSim.Region.Physics.BulletSPlugin
33{ 33{
34 34
35public class BS6DofConstraint : BSConstraint 35public sealed class BSConstraint6Dof : BSConstraint
36{ 36{
37 private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]";
38
39 public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } }
40
37 // Create a btGeneric6DofConstraint 41 // Create a btGeneric6DofConstraint
38 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, 42 public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2,
39 Vector3 frame1, Quaternion frame1rot, 43 Vector3 frame1, Quaternion frame1rot,
40 Vector3 frame2, Quaternion frame2rot, 44 Vector3 frame2, Quaternion frame2rot,
41 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) 45 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
@@ -44,25 +48,52 @@ public class BS6DofConstraint : BSConstraint
44 m_body1 = obj1; 48 m_body1 = obj1;
45 m_body2 = obj2; 49 m_body2 = obj2;
46 m_constraint = new BulletConstraint( 50 m_constraint = new BulletConstraint(
47 BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, 51 BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr,
48 frame1, frame1rot, 52 frame1, frame1rot,
49 frame2, frame2rot, 53 frame2, frame2rot,
50 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); 54 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
51 m_enabled = true; 55 m_enabled = true;
56 world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
57 BSScene.DetailLogZero, world.worldID,
58 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X"));
52 } 59 }
53 60
54 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, 61 public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2,
55 Vector3 joinPoint, 62 Vector3 joinPoint,
56 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) 63 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
57 { 64 {
58 m_world = world; 65 m_world = world;
59 m_body1 = obj1; 66 m_body1 = obj1;
60 m_body2 = obj2; 67 m_body2 = obj2;
61 m_constraint = new BulletConstraint( 68 if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero)
62 BulletSimAPI.Create6DofConstraintToPoint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, 69 {
63 joinPoint, 70 world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
64 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); 71 BSScene.DetailLogZero, world.worldID,
65 m_enabled = true; 72 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X"));
73 world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
74 LogHeader, world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X"));
75 m_enabled = false;
76 }
77 else
78 {
79 m_constraint = new BulletConstraint(
80 BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr,
81 joinPoint,
82 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
83 world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}",
84 BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"),
85 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X"));
86 if (m_constraint.ptr == IntPtr.Zero)
87 {
88 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}",
89 LogHeader, obj1.ID, obj2.ID);
90 m_enabled = false;
91 }
92 else
93 {
94 m_enabled = true;
95 }
96 }
66 } 97 }
67 98
68 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) 99 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
@@ -70,7 +101,7 @@ public class BS6DofConstraint : BSConstraint
70 bool ret = false; 101 bool ret = false;
71 if (m_enabled) 102 if (m_enabled)
72 { 103 {
73 BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot); 104 BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot);
74 ret = true; 105 ret = true;
75 } 106 }
76 return ret; 107 return ret;
@@ -81,9 +112,9 @@ public class BS6DofConstraint : BSConstraint
81 bool ret = false; 112 bool ret = false;
82 if (m_enabled) 113 if (m_enabled)
83 { 114 {
84 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); 115 BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
85 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); 116 BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
86 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); 117 BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
87 ret = true; 118 ret = true;
88 } 119 }
89 return ret; 120 return ret;
@@ -94,7 +125,7 @@ public class BS6DofConstraint : BSConstraint
94 bool ret = false; 125 bool ret = false;
95 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; 126 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
96 if (m_enabled) 127 if (m_enabled)
97 ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff); 128 ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff);
98 return ret; 129 return ret;
99 } 130 }
100 131
@@ -103,7 +134,11 @@ public class BS6DofConstraint : BSConstraint
103 bool ret = false; 134 bool ret = false;
104 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; 135 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
105 if (m_enabled) 136 if (m_enabled)
106 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); 137 {
138 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce);
139 m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}",
140 BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce);
141 }
107 return ret; 142 return ret;
108 } 143 }
109 144
@@ -111,7 +146,7 @@ public class BS6DofConstraint : BSConstraint
111 { 146 {
112 bool ret = false; 147 bool ret = false;
113 if (m_enabled) 148 if (m_enabled)
114 ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold); 149 ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold);
115 return ret; 150 return ret;
116 } 151 }
117} 152}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
index 22ea367..a9fd826 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
@@ -33,7 +33,7 @@ using OpenMetaverse;
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35 35
36public class BSConstraintCollection : IDisposable 36public sealed class BSConstraintCollection : IDisposable
37{ 37{
38 // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 38 // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
39 // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; 39 // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]";
@@ -143,8 +143,6 @@ public class BSConstraintCollection : IDisposable
143 // Return 'true' if any constraints were destroyed. 143 // Return 'true' if any constraints were destroyed.
144 public bool RemoveAndDestroyConstraint(BulletBody body1) 144 public bool RemoveAndDestroyConstraint(BulletBody body1)
145 { 145 {
146 // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID);
147
148 List<BSConstraint> toRemove = new List<BSConstraint>(); 146 List<BSConstraint> toRemove = new List<BSConstraint>();
149 uint lookingID = body1.ID; 147 uint lookingID = body1.ID;
150 lock (m_constraints) 148 lock (m_constraints)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
index d68048b..ed3ffa7 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
@@ -1,55 +1,57 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD 9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Text; 29using System.Text;
30using OpenMetaverse; 30using OpenMetaverse;
31 31
32namespace OpenSim.Region.Physics.BulletSPlugin 32namespace OpenSim.Region.Physics.BulletSPlugin
33{ 33{
34 34
35class BSHingeConstraint : BSConstraint 35public sealed class BSConstraintHinge : BSConstraint
36{ 36{
37 public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, 37 public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } }
38 Vector3 pivotInA, Vector3 pivotInB, 38
39 Vector3 axisInA, Vector3 axisInB, 39 public BSConstraintHinge(BulletSim world, BulletBody obj1, BulletBody obj2,
40 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) 40 Vector3 pivotInA, Vector3 pivotInB,
41 { 41 Vector3 axisInA, Vector3 axisInB,
42 m_world = world; 42 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
43 m_body1 = obj1; 43 {
44 m_body2 = obj2; 44 m_world = world;
45 m_constraint = new BulletConstraint( 45 m_body1 = obj1;
46 BulletSimAPI.CreateHingeConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, 46 m_body2 = obj2;
47 pivotInA, pivotInB, 47 m_constraint = new BulletConstraint(
48 axisInA, axisInB, 48 BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr,
49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); 49 pivotInA, pivotInB,
50 m_enabled = true; 50 axisInA, axisInB,
51 } 51 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
52 52 m_enabled = true;
53} 53 }
54 54
55} 55}
56
57}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 5a9f135..dbc9039 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -23,7 +23,7 @@
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 *
27 27
28/* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to 28/* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to
29 * call the BulletSim system. 29 * call the BulletSim system.
@@ -52,19 +52,20 @@ using OpenSim.Region.Physics.Manager;
52 52
53namespace OpenSim.Region.Physics.BulletSPlugin 53namespace OpenSim.Region.Physics.BulletSPlugin
54{ 54{
55 public class BSDynamics 55 public sealed class BSDynamics
56 { 56 {
57 private int frcount = 0; // Used to limit dynamics debug output to 57 private static string LogHeader = "[BULLETSIM VEHICLE]";
58 // every 100th frame 58
59 private BSScene PhysicsScene { get; set; }
60 // the prim this dynamic controller belongs to
61 private BSPrim Prim { get; set; }
59 62
60 private BSPrim m_prim; // the prim this dynamic controller belongs to 63 // mass of the vehicle fetched each time we're calles
64 private float m_vehicleMass;
61 65
62 // Vehicle properties 66 // Vehicle properties
63 private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind 67 public Vehicle Type { get; set; }
64 public Vehicle Type 68
65 {
66 get { return m_type; }
67 }
68 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier 69 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
69 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: 70 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
70 // HOVER_TERRAIN_ONLY 71 // HOVER_TERRAIN_ONLY
@@ -74,13 +75,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin
74 // HOVER_UP_ONLY 75 // HOVER_UP_ONLY
75 // LIMIT_MOTOR_UP 76 // LIMIT_MOTOR_UP
76 // LIMIT_ROLL_ONLY 77 // LIMIT_ROLL_ONLY
77 private VehicleFlag m_Hoverflags = (VehicleFlag)0;
78 private Vector3 m_BlockingEndPoint = Vector3.Zero; 78 private Vector3 m_BlockingEndPoint = Vector3.Zero;
79 private Quaternion m_RollreferenceFrame = Quaternion.Identity; 79 private Quaternion m_RollreferenceFrame = Quaternion.Identity;
80 private Quaternion m_referenceFrame = Quaternion.Identity;
81
80 // Linear properties 82 // Linear properties
81 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time 83 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
84 private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center
82 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL 85 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
83 private Vector3 m_dir = Vector3.Zero; // velocity applied to body 86 private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body
84 private Vector3 m_linearFrictionTimescale = Vector3.Zero; 87 private Vector3 m_linearFrictionTimescale = Vector3.Zero;
85 private float m_linearMotorDecayTimescale = 0; 88 private float m_linearMotorDecayTimescale = 0;
86 private float m_linearMotorTimescale = 0; 89 private float m_linearMotorTimescale = 0;
@@ -91,28 +94,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin
91 94
92 //Angular properties 95 //Angular properties
93 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor 96 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
94 private int m_angularMotorApply = 0; // application frame counter 97 // private int m_angularMotorApply = 0; // application frame counter
95 private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity 98 private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity
96 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate 99 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
97 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate 100 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
98 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate 101 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
99 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body 102 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
100 // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body 103 private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
101 104
102 //Deflection properties 105 //Deflection properties
103 // private float m_angularDeflectionEfficiency = 0; 106 private float m_angularDeflectionEfficiency = 0;
104 // private float m_angularDeflectionTimescale = 0; 107 private float m_angularDeflectionTimescale = 0;
105 // private float m_linearDeflectionEfficiency = 0; 108 private float m_linearDeflectionEfficiency = 0;
106 // private float m_linearDeflectionTimescale = 0; 109 private float m_linearDeflectionTimescale = 0;
107 110
108 //Banking properties 111 //Banking properties
109 // private float m_bankingEfficiency = 0; 112 private float m_bankingEfficiency = 0;
110 // private float m_bankingMix = 0; 113 private float m_bankingMix = 0;
111 // private float m_bankingTimescale = 0; 114 private float m_bankingTimescale = 0;
112 115
113 //Hover and Buoyancy properties 116 //Hover and Buoyancy properties
114 private float m_VhoverHeight = 0f; 117 private float m_VhoverHeight = 0f;
115// private float m_VhoverEfficiency = 0f; 118 private float m_VhoverEfficiency = 0f;
116 private float m_VhoverTimescale = 0f; 119 private float m_VhoverTimescale = 0f;
117 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height 120 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
118 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. 121 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
@@ -124,86 +127,74 @@ namespace OpenSim.Region.Physics.BulletSPlugin
124 private float m_verticalAttractionEfficiency = 1.0f; // damped 127 private float m_verticalAttractionEfficiency = 1.0f; // damped
125 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. 128 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
126 129
127 public BSDynamics(BSPrim myPrim) 130 public BSDynamics(BSScene myScene, BSPrim myPrim)
131 {
132 PhysicsScene = myScene;
133 Prim = myPrim;
134 Type = Vehicle.TYPE_NONE;
135 }
136
137 // Return 'true' if this vehicle is doing vehicle things
138 public bool IsActive
128 { 139 {
129 m_prim = myPrim; 140 get { return Type != Vehicle.TYPE_NONE; }
130 m_type = Vehicle.TYPE_NONE;
131 } 141 }
132 142
133 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) 143 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
134 { 144 {
135 DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 145 VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue);
136 switch (pParam) 146 switch (pParam)
137 { 147 {
138 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: 148 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
139 if (pValue < 0.01f) pValue = 0.01f; 149 m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f);
140 // m_angularDeflectionEfficiency = pValue;
141 break; 150 break;
142 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: 151 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
143 if (pValue < 0.01f) pValue = 0.01f; 152 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
144 // m_angularDeflectionTimescale = pValue;
145 break; 153 break;
146 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: 154 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
147 if (pValue < 0.01f) pValue = 0.01f; 155 m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f);
148 m_angularMotorDecayTimescale = pValue;
149 break; 156 break;
150 case Vehicle.ANGULAR_MOTOR_TIMESCALE: 157 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
151 if (pValue < 0.01f) pValue = 0.01f; 158 m_angularMotorTimescale = Math.Max(pValue, 0.01f);
152 m_angularMotorTimescale = pValue;
153 break; 159 break;
154 case Vehicle.BANKING_EFFICIENCY: 160 case Vehicle.BANKING_EFFICIENCY:
155 if (pValue < 0.01f) pValue = 0.01f; 161 m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f));
156 // m_bankingEfficiency = pValue;
157 break; 162 break;
158 case Vehicle.BANKING_MIX: 163 case Vehicle.BANKING_MIX:
159 if (pValue < 0.01f) pValue = 0.01f; 164 m_bankingMix = Math.Max(pValue, 0.01f);
160 // m_bankingMix = pValue;
161 break; 165 break;
162 case Vehicle.BANKING_TIMESCALE: 166 case Vehicle.BANKING_TIMESCALE:
163 if (pValue < 0.01f) pValue = 0.01f; 167 m_bankingTimescale = Math.Max(pValue, 0.01f);
164 // m_bankingTimescale = pValue;
165 break; 168 break;
166 case Vehicle.BUOYANCY: 169 case Vehicle.BUOYANCY:
167 if (pValue < -1f) pValue = -1f; 170 m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f));
168 if (pValue > 1f) pValue = 1f; 171 break;
169 m_VehicleBuoyancy = pValue; 172 case Vehicle.HOVER_EFFICIENCY:
170 break; 173 m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f));
171// case Vehicle.HOVER_EFFICIENCY: 174 break;
172// if (pValue < 0f) pValue = 0f;
173// if (pValue > 1f) pValue = 1f;
174// m_VhoverEfficiency = pValue;
175// break;
176 case Vehicle.HOVER_HEIGHT: 175 case Vehicle.HOVER_HEIGHT:
177 m_VhoverHeight = pValue; 176 m_VhoverHeight = pValue;
178 break; 177 break;
179 case Vehicle.HOVER_TIMESCALE: 178 case Vehicle.HOVER_TIMESCALE:
180 if (pValue < 0.01f) pValue = 0.01f; 179 m_VhoverTimescale = Math.Max(pValue, 0.01f);
181 m_VhoverTimescale = pValue;
182 break; 180 break;
183 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: 181 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
184 if (pValue < 0.01f) pValue = 0.01f; 182 m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f);
185 // m_linearDeflectionEfficiency = pValue;
186 break; 183 break;
187 case Vehicle.LINEAR_DEFLECTION_TIMESCALE: 184 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
188 if (pValue < 0.01f) pValue = 0.01f; 185 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
189 // m_linearDeflectionTimescale = pValue;
190 break; 186 break;
191 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: 187 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
192 if (pValue < 0.01f) pValue = 0.01f; 188 m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f);
193 m_linearMotorDecayTimescale = pValue;
194 break; 189 break;
195 case Vehicle.LINEAR_MOTOR_TIMESCALE: 190 case Vehicle.LINEAR_MOTOR_TIMESCALE:
196 if (pValue < 0.01f) pValue = 0.01f; 191 m_linearMotorTimescale = Math.Max(pValue, 0.01f);
197 m_linearMotorTimescale = pValue;
198 break; 192 break;
199 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: 193 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
200 if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable 194 m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f));
201 if (pValue > 1.0f) pValue = 1.0f;
202 m_verticalAttractionEfficiency = pValue;
203 break; 195 break;
204 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: 196 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
205 if (pValue < 0.01f) pValue = 0.01f; 197 m_verticalAttractionTimescale = Math.Max(pValue, 0.01f);
206 m_verticalAttractionTimescale = pValue;
207 break; 198 break;
208 199
209 // These are vector properties but the engine lets you use a single float value to 200 // These are vector properties but the engine lets you use a single float value to
@@ -213,7 +204,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
213 break; 204 break;
214 case Vehicle.ANGULAR_MOTOR_DIRECTION: 205 case Vehicle.ANGULAR_MOTOR_DIRECTION:
215 m_angularMotorDirection = new Vector3(pValue, pValue, pValue); 206 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
216 m_angularMotorApply = 10; 207 // m_angularMotorApply = 100;
217 break; 208 break;
218 case Vehicle.LINEAR_FRICTION_TIMESCALE: 209 case Vehicle.LINEAR_FRICTION_TIMESCALE:
219 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); 210 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
@@ -223,30 +214,27 @@ namespace OpenSim.Region.Physics.BulletSPlugin
223 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); 214 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
224 break; 215 break;
225 case Vehicle.LINEAR_MOTOR_OFFSET: 216 case Vehicle.LINEAR_MOTOR_OFFSET:
226 // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); 217 m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
227 break; 218 break;
228 219
229 } 220 }
230 }//end ProcessFloatVehicleParam 221 }//end ProcessFloatVehicleParam
231 222
232 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) 223 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
233 { 224 {
234 DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 225 VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue);
235 switch (pParam) 226 switch (pParam)
236 { 227 {
237 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 228 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
238 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 229 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
239 break; 230 break;
240 case Vehicle.ANGULAR_MOTOR_DIRECTION: 231 case Vehicle.ANGULAR_MOTOR_DIRECTION:
241 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
242 // Limit requested angular speed to 2 rps= 4 pi rads/sec 232 // Limit requested angular speed to 2 rps= 4 pi rads/sec
243 if (m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f; 233 pValue.X = Math.Max(-12.56f, Math.Min(pValue.X, 12.56f));
244 if (m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f; 234 pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f));
245 if (m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f; 235 pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f));
246 if (m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; 236 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
247 if (m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; 237 // m_angularMotorApply = 100;
248 if (m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f;
249 m_angularMotorApply = 10;
250 break; 238 break;
251 case Vehicle.LINEAR_FRICTION_TIMESCALE: 239 case Vehicle.LINEAR_FRICTION_TIMESCALE:
252 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 240 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
@@ -256,7 +244,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
256 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); 244 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
257 break; 245 break;
258 case Vehicle.LINEAR_MOTOR_OFFSET: 246 case Vehicle.LINEAR_MOTOR_OFFSET:
259 // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); 247 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
260 break; 248 break;
261 case Vehicle.BLOCK_EXIT: 249 case Vehicle.BLOCK_EXIT:
262 m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); 250 m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z);
@@ -266,11 +254,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
266 254
267 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) 255 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
268 { 256 {
269 DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 257 VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue);
270 switch (pParam) 258 switch (pParam)
271 { 259 {
272 case Vehicle.REFERENCE_FRAME: 260 case Vehicle.REFERENCE_FRAME:
273 // m_referenceFrame = pValue; 261 m_referenceFrame = pValue;
274 break; 262 break;
275 case Vehicle.ROLL_FRAME: 263 case Vehicle.ROLL_FRAME:
276 m_RollreferenceFrame = pValue; 264 m_RollreferenceFrame = pValue;
@@ -280,575 +268,545 @@ namespace OpenSim.Region.Physics.BulletSPlugin
280 268
281 internal void ProcessVehicleFlags(int pParam, bool remove) 269 internal void ProcessVehicleFlags(int pParam, bool remove)
282 { 270 {
283 DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); 271 VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove);
284 if (remove) 272 VehicleFlag parm = (VehicleFlag)pParam;
285 { 273 if (pParam == -1)
286 if (pParam == -1) 274 m_flags = (VehicleFlag)0;
287 {
288 m_flags = (VehicleFlag)0;
289 m_Hoverflags = (VehicleFlag)0;
290 return;
291 }
292 if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT)
293 {
294 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != (VehicleFlag)0)
295 m_Hoverflags &= ~(VehicleFlag.HOVER_GLOBAL_HEIGHT);
296 }
297 if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY)
298 {
299 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != (VehicleFlag)0)
300 m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY);
301 }
302 if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY)
303 {
304 if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != (VehicleFlag)0)
305 m_Hoverflags &= ~(VehicleFlag.HOVER_UP_ONLY);
306 }
307 if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY)
308 {
309 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != (VehicleFlag)0)
310 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY);
311 }
312 if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP)
313 {
314 if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != (VehicleFlag)0)
315 m_flags &= ~(VehicleFlag.LIMIT_MOTOR_UP);
316 }
317 if ((pParam & (int)VehicleFlag.LIMIT_ROLL_ONLY) == (int)VehicleFlag.LIMIT_ROLL_ONLY)
318 {
319 if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != (VehicleFlag)0)
320 m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
321 }
322 if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK)
323 {
324 if ((m_flags & VehicleFlag.MOUSELOOK_BANK) != (VehicleFlag)0)
325 m_flags &= ~(VehicleFlag.MOUSELOOK_BANK);
326 }
327 if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER)
328 {
329 if ((m_flags & VehicleFlag.MOUSELOOK_STEER) != (VehicleFlag)0)
330 m_flags &= ~(VehicleFlag.MOUSELOOK_STEER);
331 }
332 if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP)
333 {
334 if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) != (VehicleFlag)0)
335 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP);
336 }
337 if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED)
338 {
339 if ((m_flags & VehicleFlag.CAMERA_DECOUPLED) != (VehicleFlag)0)
340 m_flags &= ~(VehicleFlag.CAMERA_DECOUPLED);
341 }
342 if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X)
343 {
344 if ((m_flags & VehicleFlag.NO_X) != (VehicleFlag)0)
345 m_flags &= ~(VehicleFlag.NO_X);
346 }
347 if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y)
348 {
349 if ((m_flags & VehicleFlag.NO_Y) != (VehicleFlag)0)
350 m_flags &= ~(VehicleFlag.NO_Y);
351 }
352 if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z)
353 {
354 if ((m_flags & VehicleFlag.NO_Z) != (VehicleFlag)0)
355 m_flags &= ~(VehicleFlag.NO_Z);
356 }
357 if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT)
358 {
359 if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != (VehicleFlag)0)
360 m_Hoverflags &= ~(VehicleFlag.LOCK_HOVER_HEIGHT);
361 }
362 if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION)
363 {
364 if ((m_flags & VehicleFlag.NO_DEFLECTION) != (VehicleFlag)0)
365 m_flags &= ~(VehicleFlag.NO_DEFLECTION);
366 }
367 if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION)
368 {
369 if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0)
370 m_flags &= ~(VehicleFlag.LOCK_ROTATION);
371 }
372 }
373 else 275 else
374 { 276 {
375 if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) 277 if (remove)
376 { 278 m_flags &= ~parm;
377 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags); 279 else
378 } 280 m_flags |= parm;
379 if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY)
380 {
381 m_Hoverflags |= (VehicleFlag.HOVER_TERRAIN_ONLY | m_flags);
382 }
383 if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY)
384 {
385 m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY | m_flags);
386 }
387 if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY)
388 {
389 m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY | m_flags);
390 }
391 if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP)
392 {
393 m_flags |= (VehicleFlag.LIMIT_MOTOR_UP | m_flags);
394 }
395 if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK)
396 {
397 m_flags |= (VehicleFlag.MOUSELOOK_BANK | m_flags);
398 }
399 if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER)
400 {
401 m_flags |= (VehicleFlag.MOUSELOOK_STEER | m_flags);
402 }
403 if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP)
404 {
405 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags);
406 }
407 if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED)
408 {
409 m_flags |= (VehicleFlag.CAMERA_DECOUPLED | m_flags);
410 }
411 if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X)
412 {
413 m_flags |= (VehicleFlag.NO_X);
414 }
415 if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y)
416 {
417 m_flags |= (VehicleFlag.NO_Y);
418 }
419 if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z)
420 {
421 m_flags |= (VehicleFlag.NO_Z);
422 }
423 if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT)
424 {
425 m_Hoverflags |= (VehicleFlag.LOCK_HOVER_HEIGHT);
426 }
427 if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION)
428 {
429 m_flags |= (VehicleFlag.NO_DEFLECTION);
430 }
431 if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION)
432 {
433 m_flags |= (VehicleFlag.LOCK_ROTATION);
434 }
435 } 281 }
436 }//end ProcessVehicleFlags 282 }
437 283
438 internal void ProcessTypeChange(Vehicle pType) 284 internal void ProcessTypeChange(Vehicle pType)
439 { 285 {
440 DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); 286 VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType);
441 // Set Defaults For Type 287 // Set Defaults For Type
442 m_type = pType; 288 Type = pType;
443 switch (pType) 289 switch (pType)
444 { 290 {
445 case Vehicle.TYPE_NONE: 291 case Vehicle.TYPE_NONE:
446 m_linearFrictionTimescale = new Vector3(0, 0, 0);
447 m_angularFrictionTimescale = new Vector3(0, 0, 0);
448 m_linearMotorDirection = Vector3.Zero; 292 m_linearMotorDirection = Vector3.Zero;
449 m_linearMotorTimescale = 0; 293 m_linearMotorTimescale = 0;
450 m_linearMotorDecayTimescale = 0; 294 m_linearMotorDecayTimescale = 0;
295 m_linearFrictionTimescale = new Vector3(0, 0, 0);
296
451 m_angularMotorDirection = Vector3.Zero; 297 m_angularMotorDirection = Vector3.Zero;
452 m_angularMotorTimescale = 0;
453 m_angularMotorDecayTimescale = 0; 298 m_angularMotorDecayTimescale = 0;
299 m_angularMotorTimescale = 0;
300 m_angularFrictionTimescale = new Vector3(0, 0, 0);
301
454 m_VhoverHeight = 0; 302 m_VhoverHeight = 0;
303 m_VhoverEfficiency = 0;
455 m_VhoverTimescale = 0; 304 m_VhoverTimescale = 0;
456 m_VehicleBuoyancy = 0; 305 m_VehicleBuoyancy = 0;
306
307 m_linearDeflectionEfficiency = 1;
308 m_linearDeflectionTimescale = 1;
309
310 m_angularDeflectionEfficiency = 0;
311 m_angularDeflectionTimescale = 1000;
312
313 m_verticalAttractionEfficiency = 0;
314 m_verticalAttractionTimescale = 0;
315
316 m_bankingEfficiency = 0;
317 m_bankingTimescale = 1000;
318 m_bankingMix = 1;
319
320 m_referenceFrame = Quaternion.Identity;
457 m_flags = (VehicleFlag)0; 321 m_flags = (VehicleFlag)0;
458 break; 322 break;
459 323
460 case Vehicle.TYPE_SLED: 324 case Vehicle.TYPE_SLED:
461 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
462 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
463 m_linearMotorDirection = Vector3.Zero; 325 m_linearMotorDirection = Vector3.Zero;
464 m_linearMotorTimescale = 1000; 326 m_linearMotorTimescale = 1000;
465 m_linearMotorDecayTimescale = 120; 327 m_linearMotorDecayTimescale = 120;
328 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
329
466 m_angularMotorDirection = Vector3.Zero; 330 m_angularMotorDirection = Vector3.Zero;
467 m_angularMotorTimescale = 1000; 331 m_angularMotorTimescale = 1000;
468 m_angularMotorDecayTimescale = 120; 332 m_angularMotorDecayTimescale = 120;
333 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
334
469 m_VhoverHeight = 0; 335 m_VhoverHeight = 0;
470// m_VhoverEfficiency = 1; 336 m_VhoverEfficiency = 10; // TODO: this looks wrong!!
471 m_VhoverTimescale = 10; 337 m_VhoverTimescale = 10;
472 m_VehicleBuoyancy = 0; 338 m_VehicleBuoyancy = 0;
473 // m_linearDeflectionEfficiency = 1; 339
474 // m_linearDeflectionTimescale = 1; 340 m_linearDeflectionEfficiency = 1;
475 // m_angularDeflectionEfficiency = 1; 341 m_linearDeflectionTimescale = 1;
476 // m_angularDeflectionTimescale = 1000; 342
477 // m_bankingEfficiency = 0; 343 m_angularDeflectionEfficiency = 1;
478 // m_bankingMix = 1; 344 m_angularDeflectionTimescale = 1000;
479 // m_bankingTimescale = 10; 345
480 // m_referenceFrame = Quaternion.Identity; 346 m_verticalAttractionEfficiency = 0;
481 m_Hoverflags &= 347 m_verticalAttractionTimescale = 0;
348
349 m_bankingEfficiency = 0;
350 m_bankingTimescale = 10;
351 m_bankingMix = 1;
352
353 m_referenceFrame = Quaternion.Identity;
354 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
355 m_flags &=
482 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 356 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
483 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 357 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
484 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
485 break; 358 break;
486 case Vehicle.TYPE_CAR: 359 case Vehicle.TYPE_CAR:
487 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
488 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
489 m_linearMotorDirection = Vector3.Zero; 360 m_linearMotorDirection = Vector3.Zero;
490 m_linearMotorTimescale = 1; 361 m_linearMotorTimescale = 1;
491 m_linearMotorDecayTimescale = 60; 362 m_linearMotorDecayTimescale = 60;
363 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
364
492 m_angularMotorDirection = Vector3.Zero; 365 m_angularMotorDirection = Vector3.Zero;
493 m_angularMotorTimescale = 1; 366 m_angularMotorTimescale = 1;
494 m_angularMotorDecayTimescale = 0.8f; 367 m_angularMotorDecayTimescale = 0.8f;
368 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
369
495 m_VhoverHeight = 0; 370 m_VhoverHeight = 0;
496// m_VhoverEfficiency = 0; 371 m_VhoverEfficiency = 0;
497 m_VhoverTimescale = 1000; 372 m_VhoverTimescale = 1000;
498 m_VehicleBuoyancy = 0; 373 m_VehicleBuoyancy = 0;
499 // // m_linearDeflectionEfficiency = 1; 374
500 // // m_linearDeflectionTimescale = 2; 375 m_linearDeflectionEfficiency = 1;
501 // // m_angularDeflectionEfficiency = 0; 376 m_linearDeflectionTimescale = 2;
502 // m_angularDeflectionTimescale = 10; 377
378 m_angularDeflectionEfficiency = 0;
379 m_angularDeflectionTimescale = 10;
380
503 m_verticalAttractionEfficiency = 1f; 381 m_verticalAttractionEfficiency = 1f;
504 m_verticalAttractionTimescale = 10f; 382 m_verticalAttractionTimescale = 10f;
505 // m_bankingEfficiency = -0.2f; 383
506 // m_bankingMix = 1; 384 m_bankingEfficiency = -0.2f;
507 // m_bankingTimescale = 1; 385 m_bankingMix = 1;
508 // m_referenceFrame = Quaternion.Identity; 386 m_bankingTimescale = 1;
509 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); 387
510 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | 388 m_referenceFrame = Quaternion.Identity;
511 VehicleFlag.LIMIT_MOTOR_UP); 389 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
512 m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY); 390 | VehicleFlag.HOVER_TERRAIN_ONLY
391 | VehicleFlag.HOVER_GLOBAL_HEIGHT);
392 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
393 | VehicleFlag.LIMIT_ROLL_ONLY
394 | VehicleFlag.LIMIT_MOTOR_UP
395 | VehicleFlag.HOVER_UP_ONLY);
513 break; 396 break;
514 case Vehicle.TYPE_BOAT: 397 case Vehicle.TYPE_BOAT:
515 m_linearFrictionTimescale = new Vector3(10, 3, 2);
516 m_angularFrictionTimescale = new Vector3(10,10,10);
517 m_linearMotorDirection = Vector3.Zero; 398 m_linearMotorDirection = Vector3.Zero;
518 m_linearMotorTimescale = 5; 399 m_linearMotorTimescale = 5;
519 m_linearMotorDecayTimescale = 60; 400 m_linearMotorDecayTimescale = 60;
401 m_linearFrictionTimescale = new Vector3(10, 3, 2);
402
520 m_angularMotorDirection = Vector3.Zero; 403 m_angularMotorDirection = Vector3.Zero;
521 m_angularMotorTimescale = 4; 404 m_angularMotorTimescale = 4;
522 m_angularMotorDecayTimescale = 4; 405 m_angularMotorDecayTimescale = 4;
406 m_angularFrictionTimescale = new Vector3(10,10,10);
407
523 m_VhoverHeight = 0; 408 m_VhoverHeight = 0;
524// m_VhoverEfficiency = 0.5f; 409 m_VhoverEfficiency = 0.5f;
525 m_VhoverTimescale = 2; 410 m_VhoverTimescale = 2;
526 m_VehicleBuoyancy = 1; 411 m_VehicleBuoyancy = 1;
527 // m_linearDeflectionEfficiency = 0.5f; 412
528 // m_linearDeflectionTimescale = 3; 413 m_linearDeflectionEfficiency = 0.5f;
529 // m_angularDeflectionEfficiency = 0.5f; 414 m_linearDeflectionTimescale = 3;
530 // m_angularDeflectionTimescale = 5; 415
416 m_angularDeflectionEfficiency = 0.5f;
417 m_angularDeflectionTimescale = 5;
418
531 m_verticalAttractionEfficiency = 0.5f; 419 m_verticalAttractionEfficiency = 0.5f;
532 m_verticalAttractionTimescale = 5f; 420 m_verticalAttractionTimescale = 5f;
533 // m_bankingEfficiency = -0.3f; 421
534 // m_bankingMix = 0.8f; 422 m_bankingEfficiency = -0.3f;
535 // m_bankingTimescale = 1; 423 m_bankingMix = 0.8f;
536 // m_referenceFrame = Quaternion.Identity; 424 m_bankingTimescale = 1;
537 m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | 425
538 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 426 m_referenceFrame = Quaternion.Identity;
539 m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); 427 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY
540 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | 428 | VehicleFlag.HOVER_GLOBAL_HEIGHT
541 VehicleFlag.LIMIT_MOTOR_UP); 429 | VehicleFlag.LIMIT_ROLL_ONLY
542 m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY); 430 | VehicleFlag.HOVER_UP_ONLY);
431 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
432 | VehicleFlag.LIMIT_MOTOR_UP
433 | VehicleFlag.HOVER_WATER_ONLY);
543 break; 434 break;
544 case Vehicle.TYPE_AIRPLANE: 435 case Vehicle.TYPE_AIRPLANE:
545 m_linearFrictionTimescale = new Vector3(200, 10, 5);
546 m_angularFrictionTimescale = new Vector3(20, 20, 20);
547 m_linearMotorDirection = Vector3.Zero; 436 m_linearMotorDirection = Vector3.Zero;
548 m_linearMotorTimescale = 2; 437 m_linearMotorTimescale = 2;
549 m_linearMotorDecayTimescale = 60; 438 m_linearMotorDecayTimescale = 60;
439 m_linearFrictionTimescale = new Vector3(200, 10, 5);
440
550 m_angularMotorDirection = Vector3.Zero; 441 m_angularMotorDirection = Vector3.Zero;
551 m_angularMotorTimescale = 4; 442 m_angularMotorTimescale = 4;
552 m_angularMotorDecayTimescale = 4; 443 m_angularMotorDecayTimescale = 4;
444 m_angularFrictionTimescale = new Vector3(20, 20, 20);
445
553 m_VhoverHeight = 0; 446 m_VhoverHeight = 0;
554// m_VhoverEfficiency = 0.5f; 447 m_VhoverEfficiency = 0.5f;
555 m_VhoverTimescale = 1000; 448 m_VhoverTimescale = 1000;
556 m_VehicleBuoyancy = 0; 449 m_VehicleBuoyancy = 0;
557 // m_linearDeflectionEfficiency = 0.5f; 450
558 // m_linearDeflectionTimescale = 3; 451 m_linearDeflectionEfficiency = 0.5f;
559 // m_angularDeflectionEfficiency = 1; 452 m_linearDeflectionTimescale = 3;
560 // m_angularDeflectionTimescale = 2; 453
454 m_angularDeflectionEfficiency = 1;
455 m_angularDeflectionTimescale = 2;
456
561 m_verticalAttractionEfficiency = 0.9f; 457 m_verticalAttractionEfficiency = 0.9f;
562 m_verticalAttractionTimescale = 2f; 458 m_verticalAttractionTimescale = 2f;
563 // m_bankingEfficiency = 1; 459
564 // m_bankingMix = 0.7f; 460 m_bankingEfficiency = 1;
565 // m_bankingTimescale = 2; 461 m_bankingMix = 0.7f;
566 // m_referenceFrame = Quaternion.Identity; 462 m_bankingTimescale = 2;
567 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 463
568 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 464 m_referenceFrame = Quaternion.Identity;
569 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); 465 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
466 | VehicleFlag.HOVER_TERRAIN_ONLY
467 | VehicleFlag.HOVER_GLOBAL_HEIGHT
468 | VehicleFlag.HOVER_UP_ONLY
469 | VehicleFlag.NO_DEFLECTION_UP
470 | VehicleFlag.LIMIT_MOTOR_UP);
570 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); 471 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
571 break; 472 break;
572 case Vehicle.TYPE_BALLOON: 473 case Vehicle.TYPE_BALLOON:
573 m_linearFrictionTimescale = new Vector3(5, 5, 5);
574 m_angularFrictionTimescale = new Vector3(10, 10, 10);
575 m_linearMotorDirection = Vector3.Zero; 474 m_linearMotorDirection = Vector3.Zero;
576 m_linearMotorTimescale = 5; 475 m_linearMotorTimescale = 5;
476 m_linearFrictionTimescale = new Vector3(5, 5, 5);
577 m_linearMotorDecayTimescale = 60; 477 m_linearMotorDecayTimescale = 60;
478
578 m_angularMotorDirection = Vector3.Zero; 479 m_angularMotorDirection = Vector3.Zero;
579 m_angularMotorTimescale = 6; 480 m_angularMotorTimescale = 6;
481 m_angularFrictionTimescale = new Vector3(10, 10, 10);
580 m_angularMotorDecayTimescale = 10; 482 m_angularMotorDecayTimescale = 10;
483
581 m_VhoverHeight = 5; 484 m_VhoverHeight = 5;
582// m_VhoverEfficiency = 0.8f; 485 m_VhoverEfficiency = 0.8f;
583 m_VhoverTimescale = 10; 486 m_VhoverTimescale = 10;
584 m_VehicleBuoyancy = 1; 487 m_VehicleBuoyancy = 1;
585 // m_linearDeflectionEfficiency = 0; 488
586 // m_linearDeflectionTimescale = 5; 489 m_linearDeflectionEfficiency = 0;
587 // m_angularDeflectionEfficiency = 0; 490 m_linearDeflectionTimescale = 5;
588 // m_angularDeflectionTimescale = 5; 491
492 m_angularDeflectionEfficiency = 0;
493 m_angularDeflectionTimescale = 5;
494
589 m_verticalAttractionEfficiency = 1f; 495 m_verticalAttractionEfficiency = 1f;
590 m_verticalAttractionTimescale = 100f; 496 m_verticalAttractionTimescale = 100f;
591 // m_bankingEfficiency = 0; 497
592 // m_bankingMix = 0.7f; 498 m_bankingEfficiency = 0;
593 // m_bankingTimescale = 5; 499 m_bankingMix = 0.7f;
594 // m_referenceFrame = Quaternion.Identity; 500 m_bankingTimescale = 5;
595 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 501 m_referenceFrame = Quaternion.Identity;
596 VehicleFlag.HOVER_UP_ONLY); 502
597 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); 503 m_referenceFrame = Quaternion.Identity;
598 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); 504 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
599 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); 505 | VehicleFlag.HOVER_TERRAIN_ONLY
506 | VehicleFlag.HOVER_UP_ONLY
507 | VehicleFlag.NO_DEFLECTION_UP
508 | VehicleFlag.LIMIT_MOTOR_UP);
509 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY
510 | VehicleFlag.HOVER_GLOBAL_HEIGHT);
600 break; 511 break;
601 } 512 }
602 }//end SetDefaultsForType 513 }
514
515 // Some of the properties of this prim may have changed.
516 // Do any updating needed for a vehicle
517 public void Refresh()
518 {
519 if (IsActive)
520 {
521 // Friction effects are handled by this vehicle code
522 BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f);
523 BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f);
524
525 // BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, 0.8f);
526
527 VDetailLog("{0},BSDynamics.Refresh,zeroingFriction and adding damping", Prim.LocalID);
528 }
529 }
530
531 public bool RemoveBodyDependencies(BSPhysObject prim)
532 {
533 // If active, we need to add our properties back when the body is rebuilt.
534 return IsActive;
535 }
536
537 public void RestoreBodyDependencies(BSPhysObject prim)
538 {
539 if (Prim.LocalID != prim.LocalID)
540 {
541 // The call should be on us by our prim. Error if not.
542 PhysicsScene.Logger.ErrorFormat("{0} RestoreBodyDependencies: called by not my prim. passedLocalID={1}, vehiclePrimLocalID={2}",
543 LogHeader, prim.LocalID, Prim.LocalID);
544 return;
545 }
546 Refresh();
547 }
603 548
549 // One step of the vehicle properties for the next 'pTimestep' seconds.
604 internal void Step(float pTimestep) 550 internal void Step(float pTimestep)
605 { 551 {
606 if (m_type == Vehicle.TYPE_NONE) return; 552 if (!IsActive) return;
607 553
608 frcount++; // used to limit debug comment output 554 // DEBUG
609 if (frcount > 100) 555 // Because Bullet does apply forces to the vehicle, our last computed
610 frcount = 0; 556 // linear and angular velocities are not what is happening now.
557 // Vector3 externalAngularVelocity = Prim.ForceRotationalVelocity - m_lastAngularVelocity;
558 // m_lastAngularVelocity += (externalAngularVelocity * 0.5f) * pTimestep;
559 // m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time
560 // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG:
561 // END DEBUG
562
563 m_vehicleMass = Prim.Linkset.LinksetMass;
611 564
612 MoveLinear(pTimestep); 565 MoveLinear(pTimestep);
566 // Commented out for debug
613 MoveAngular(pTimestep); 567 MoveAngular(pTimestep);
568 // Prim.ApplyTorqueImpulse(-Prim.RotationalVelocity * m_vehicleMass, false); // DEBUG DEBUG
569 // Prim.ForceRotationalVelocity = -Prim.RotationalVelocity; // DEBUG DEBUG
570
614 LimitRotation(pTimestep); 571 LimitRotation(pTimestep);
615 572
616 DetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", 573 // remember the position so next step we can limit absolute movement effects
617 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); 574 m_lastPositionVector = Prim.ForcePosition;
575
576 VDetailLog("{0},BSDynamics.Step,frict={1},grav={2},inertia={3},mass={4}", // DEBUG DEBUG
577 Prim.LocalID,
578 BulletSimAPI.GetFriction2(Prim.PhysBody.ptr),
579 BulletSimAPI.GetGravity2(Prim.PhysBody.ptr),
580 Prim.Inertia,
581 m_vehicleMass
582 );
583 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
584 Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity);
618 }// end Step 585 }// end Step
619 586
587 // Apply the effect of the linear motor.
588 // Also does hover and float.
620 private void MoveLinear(float pTimestep) 589 private void MoveLinear(float pTimestep)
621 { 590 {
622 // requested m_linearMotorDirection is significant 591 // m_linearMotorDirection is the target direction we are moving relative to the vehicle coordinates
623 // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) 592 // m_lastLinearVelocityVector is the current speed we are moving in that direction
624 if (m_linearMotorDirection.LengthSquared() > 0.0001f) 593 if (m_linearMotorDirection.LengthSquared() > 0.001f)
625 { 594 {
626 Vector3 origDir = m_linearMotorDirection; 595 Vector3 origDir = m_linearMotorDirection; // DEBUG
627 Vector3 origVel = m_lastLinearVelocityVector; 596 Vector3 origVel = m_lastLinearVelocityVector; // DEBUG
628 597 // DEBUG: the vehicle velocity rotated to be relative to vehicle coordinates for comparison
629 // add drive to body 598 Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG
630 // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); 599
631 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale); 600 // Add (desiredVelocity - lastAppliedVelocity) / howLongItShouldTakeToComplete
632 // lastLinearVelocityVector is the current body velocity vector? 601 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep;
633 // RA: Not sure what the *10 is for. A correction for pTimestep?
634 // m_lastLinearVelocityVector += (addAmount*10);
635 m_lastLinearVelocityVector += addAmount;
636
637 // This will work temporarily, but we really need to compare speed on an axis
638 // KF: Limit body velocity to applied velocity?
639 // Limit the velocity vector to less than the last set linear motor direction
640 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
641 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
642 if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
643 m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y;
644 if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
645 m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
646
647 // decay applied velocity
648 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
649 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
650
651 /*
652 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale;
653 m_lastLinearVelocityVector += addAmount; 602 m_lastLinearVelocityVector += addAmount;
654 603
655 float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale); 604 float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep;
656 m_linearMotorDirection *= decayfraction; 605 m_linearMotorDirection *= (1f - decayFactor);
606
607 // Rotate new object velocity from vehicle relative to world coordinates
608 m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation;
657 609
658 */ 610 // Apply friction for next time
611 Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep;
612 m_lastLinearVelocityVector *= (Vector3.One - frictionFactor);
659 613
660 DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", 614 VDetailLog("{0},MoveLinear,nonZero,origlmDir={1},origlvVel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lvVec={8},newVel={9}",
661 m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); 615 Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor,
616 m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity);
662 } 617 }
663 else 618 else
664 { 619 {
665 // if what remains of applied is small, zero it. 620 // if what remains of direction is very small, zero it.
666 // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
667 // m_lastLinearVelocityVector = Vector3.Zero;
668 m_linearMotorDirection = Vector3.Zero; 621 m_linearMotorDirection = Vector3.Zero;
669 m_lastLinearVelocityVector = Vector3.Zero; 622 m_lastLinearVelocityVector = Vector3.Zero;
670 } 623 m_newVelocity = Vector3.Zero;
671 624
672 // convert requested object velocity to world-referenced vector 625 VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID);
673 Quaternion rotq = m_prim.Orientation; 626 }
674 m_dir = m_lastLinearVelocityVector * rotq;
675 627
676 // Add the various forces into m_dir which will be our new direction vector (velocity) 628 // m_newVelocity is velocity computed from linear motor in world coordinates
677 629
678 // add Gravity and Buoyancy 630 // Gravity and Buoyancy
679 // KF: So far I have found no good method to combine a script-requested
680 // .Z velocity and gravity. Therefore only 0g will used script-requested
681 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
682 Vector3 grav = Vector3.Zero;
683 // There is some gravity, make a gravity force vector that is applied after object velocity. 631 // There is some gravity, make a gravity force vector that is applied after object velocity.
684 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 632 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
685 grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); 633 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy);
634
635 /*
636 * RA: Not sure why one would do this unless we are hoping external forces are doing gravity, ...
686 // Preserve the current Z velocity 637 // Preserve the current Z velocity
687 Vector3 vel_now = m_prim.Velocity; 638 Vector3 vel_now = m_prim.Velocity;
688 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity 639 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
640 */
689 641
690 Vector3 pos = m_prim.Position; 642 Vector3 pos = Prim.ForcePosition;
691 Vector3 posChange = pos;
692// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); 643// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
693 double Zchange = Math.Abs(posChange.Z);
694 if (m_BlockingEndPoint != Vector3.Zero)
695 {
696 bool changed = false;
697 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
698 {
699 pos.X -= posChange.X + 1;
700 changed = true;
701 }
702 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
703 {
704 pos.Y -= posChange.Y + 1;
705 changed = true;
706 }
707 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
708 {
709 pos.Z -= posChange.Z + 1;
710 changed = true;
711 }
712 if (pos.X <= 0)
713 {
714 pos.X += posChange.X + 1;
715 changed = true;
716 }
717 if (pos.Y <= 0)
718 {
719 pos.Y += posChange.Y + 1;
720 changed = true;
721 }
722 if (changed)
723 {
724 m_prim.Position = pos;
725 DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
726 m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
727 }
728 }
729 644
730 // If below the terrain, move us above the ground a little. 645 // If below the terrain, move us above the ground a little.
731 if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos)) 646 float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
647 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
648 // TODO: Add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
649 // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation;
650 // if (rotatedSize.Z < terrainHeight)
651 if (pos.Z < terrainHeight)
732 { 652 {
733 pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2; 653 pos.Z = terrainHeight + 2;
734 m_prim.Position = pos; 654 Prim.ForcePosition = pos;
735 DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); 655 VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos);
736 } 656 }
737 657
738 // Check if hovering 658 // Check if hovering
739 if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) 659 // m_VhoverEfficiency: 0=bouncy, 1=totally damped
660 // m_VhoverTimescale: time to achieve height
661 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
740 { 662 {
741 // We should hover, get the target height 663 // We should hover, get the target height
742 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) 664 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
743 { 665 {
744 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; 666 m_VhoverTargetHeight = Prim.PhysicsScene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight;
745 } 667 }
746 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) 668 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
747 { 669 {
748 m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; 670 m_VhoverTargetHeight = terrainHeight + m_VhoverHeight;
749 } 671 }
750 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) 672 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
751 { 673 {
752 m_VhoverTargetHeight = m_VhoverHeight; 674 m_VhoverTargetHeight = m_VhoverHeight;
753 } 675 }
754 676
755 if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0) 677 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
756 { 678 {
757 // If body is aready heigher, use its height as target height 679 // If body is already heigher, use its height as target height
758 if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; 680 if (pos.Z > m_VhoverTargetHeight)
681 m_VhoverTargetHeight = pos.Z;
759 } 682 }
760 if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 683 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
761 { 684 {
762 if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) 685 if (Math.Abs(pos.Z - m_VhoverTargetHeight) > 0.2f)
763 { 686 {
764 m_prim.Position = pos; 687 pos.Z = m_VhoverTargetHeight;
688 Prim.ForcePosition = pos;
765 } 689 }
766 } 690 }
767 else 691 else
768 { 692 {
769 float herr0 = pos.Z - m_VhoverTargetHeight; 693 float verticalError = pos.Z - m_VhoverTargetHeight;
694 // RA: where does the 50 come from?
695 float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale);
770 // Replace Vertical speed with correction figure if significant 696 // Replace Vertical speed with correction figure if significant
771 if (Math.Abs(herr0) > 0.01f) 697 if (Math.Abs(verticalError) > 0.01f)
772 { 698 {
773 m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); 699 m_newVelocity.Z += verticalCorrectionVelocity;
774 //KF: m_VhoverEfficiency is not yet implemented 700 //KF: m_VhoverEfficiency is not yet implemented
775 } 701 }
702 else if (verticalError < -0.01)
703 {
704 m_newVelocity.Z -= verticalCorrectionVelocity;
705 }
776 else 706 else
777 { 707 {
778 m_dir.Z = 0f; 708 m_newVelocity.Z = 0f;
779 } 709 }
780 } 710 }
781 711
782 DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); 712 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", Prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight);
783
784// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
785// m_VhoverTimescale = 0f; // time to acheive height
786// pTimestep is time since last frame,in secs
787 } 713 }
788 714
789 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 715 Vector3 posChange = pos - m_lastPositionVector;
716 if (m_BlockingEndPoint != Vector3.Zero)
790 { 717 {
791 //Start Experimental Values 718 bool changed = false;
792 if (Zchange > .3) 719 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
793 { 720 {
794 grav.Z = (float)(grav.Z * 3); 721 pos.X -= posChange.X + 1;
722 changed = true;
795 } 723 }
796 if (Zchange > .15) 724 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
797 { 725 {
798 grav.Z = (float)(grav.Z * 2); 726 pos.Y -= posChange.Y + 1;
727 changed = true;
799 } 728 }
800 if (Zchange > .75) 729 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
801 { 730 {
802 grav.Z = (float)(grav.Z * 1.5); 731 pos.Z -= posChange.Z + 1;
732 changed = true;
803 } 733 }
804 if (Zchange > .05) 734 if (pos.X <= 0)
805 { 735 {
806 grav.Z = (float)(grav.Z * 1.25); 736 pos.X += posChange.X + 1;
737 changed = true;
807 } 738 }
808 if (Zchange > .025) 739 if (pos.Y <= 0)
809 { 740 {
810 grav.Z = (float)(grav.Z * 1.125); 741 pos.Y += posChange.Y + 1;
742 changed = true;
811 } 743 }
812 float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos); 744 if (changed)
813 float postemp = (pos.Z - terraintemp);
814 if (postemp > 2.5f)
815 { 745 {
816 grav.Z = (float)(grav.Z * 1.037125); 746 Prim.ForcePosition = pos;
747 VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
748 Prim.LocalID, m_BlockingEndPoint, posChange, pos);
817 } 749 }
818 DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
819 //End Experimental Values
820 } 750 }
821 if ((m_flags & (VehicleFlag.NO_X)) != 0) 751
752 #region downForce
753 Vector3 downForce = Vector3.Zero;
754
755 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
822 { 756 {
823 m_dir.X = 0; 757 // If the vehicle is motoring into the sky, get it going back down.
758 // Is this an angular force or both linear and angular??
759 float distanceAboveGround = pos.Z - terrainHeight;
760 if (distanceAboveGround > 2f)
761 {
762 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
763 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
764 downForce = new Vector3(0, 0, -distanceAboveGround);
765 }
766 // TODO: this calculation is all wrong. From the description at
767 // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce
768 // has a decay factor. This says this force should
769 // be computed with a motor.
770 VDetailLog("{0},MoveLinear,limitMotorUp,distAbove={1},downForce={2}",
771 Prim.LocalID, distanceAboveGround, downForce);
824 } 772 }
773 #endregion // downForce
774
775 // If not changing some axis, reduce out velocity
776 if ((m_flags & (VehicleFlag.NO_X)) != 0)
777 m_newVelocity.X = 0;
825 if ((m_flags & (VehicleFlag.NO_Y)) != 0) 778 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
826 { 779 m_newVelocity.Y = 0;
827 m_dir.Y = 0;
828 }
829 if ((m_flags & (VehicleFlag.NO_Z)) != 0) 780 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
781 m_newVelocity.Z = 0;
782
783 // Clamp REALLY high or low velocities
784 if (m_newVelocity.LengthSquared() > 1e6f)
830 { 785 {
831 m_dir.Z = 0; 786 m_newVelocity /= m_newVelocity.Length();
787 m_newVelocity *= 1000f;
832 } 788 }
789 else if (m_newVelocity.LengthSquared() < 1e-6f)
790 m_newVelocity = Vector3.Zero;
833 791
834 m_lastPositionVector = m_prim.Position; 792 // Stuff new linear velocity into the vehicle
793 Prim.ForceVelocity = m_newVelocity;
794 // Prim.ApplyForceImpulse((m_newVelocity - Prim.Velocity) * m_vehicleMass, false); // DEBUG DEBUG
835 795
836 // Apply velocity 796 Vector3 totalDownForce = downForce + grav;
837 m_prim.Velocity = m_dir; 797 if (totalDownForce != Vector3.Zero)
838 // apply gravity force 798 {
839 // Why is this set here? The physics engine already does gravity. 799 Prim.AddForce(totalDownForce * m_vehicleMass, false);
840 // m_prim.AddForce(grav, false); 800 // Prim.ApplyForceImpulse(totalDownForce * m_vehicleMass, false);
841 // m_prim.Force = grav; 801 }
842
843 // Apply friction
844 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
845 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
846 802
847 DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", 803 VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},primVel={4},totalDown={5}",
848 m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); 804 Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, Prim.Velocity, totalDownForce);
849 805
850 } // end MoveLinear() 806 } // end MoveLinear()
851 807
808 // =======================================================================
809 // Apply the effect of the angular motor.
852 private void MoveAngular(float pTimestep) 810 private void MoveAngular(float pTimestep)
853 { 811 {
854 // m_angularMotorDirection // angular velocity requested by LSL motor 812 // m_angularMotorDirection // angular velocity requested by LSL motor
@@ -859,160 +817,263 @@ namespace OpenSim.Region.Physics.BulletSPlugin
859 // m_angularFrictionTimescale // body angular velocity decay rate 817 // m_angularFrictionTimescale // body angular velocity decay rate
860 // m_lastAngularVelocity // what was last applied to body 818 // m_lastAngularVelocity // what was last applied to body
861 819
862 // Get what the body is doing, this includes 'external' influences 820 if (m_angularMotorDirection.LengthSquared() > 0.0001)
863 Vector3 angularVelocity = m_prim.RotationalVelocity;
864
865 if (m_angularMotorApply > 0)
866 { 821 {
867 // Rather than snapping the angular motor velocity from the old value to 822 Vector3 origVel = m_angularMotorVelocity;
868 // a newly set velocity, this routine steps the value from the previous 823 Vector3 origDir = m_angularMotorDirection;
869 // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection). 824
870 // There are m_angularMotorApply steps. 825 // new velocity += error / ( time to get there / step interval)
871 Vector3 origAngularVelocity = m_angularMotorVelocity; 826 // requested direction - current vehicle direction
872 // ramp up to new value 827 m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep);
873 // current velocity += error / (time to get there / step interval) 828 // decay requested direction
874 // requested speed - last motor speed 829 m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale));
875 m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); 830
876 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); 831 VDetailLog("{0},MoveAngular,angularMotorApply,angTScale={1},timeStep={2},origvel={3},origDir={4},vel={5}",
877 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); 832 Prim.LocalID, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity);
878
879 DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}",
880 m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
881
882 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected
883 // velocity may still be acheived.
884 } 833 }
885 else 834 else
886 { 835 {
887 // No motor recently applied, keep the body velocity 836 m_angularMotorVelocity = Vector3.Zero;
888 // and decay the velocity 837 }
889 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); 838
890 } // end motor section 839 #region Vertical attactor
891 840
892 // Vertical attractor section
893 Vector3 vertattr = Vector3.Zero; 841 Vector3 vertattr = Vector3.Zero;
894 if (m_verticalAttractionTimescale < 300) 842 Vector3 deflection = Vector3.Zero;
843 Vector3 banking = Vector3.Zero;
844
845 // If vertical attaction timescale is reasonable and we applied an angular force last time...
846 if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero)
895 { 847 {
896 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); 848 float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale;
897 // get present body rotation 849 if (Prim.IsColliding)
898 Quaternion rotq = m_prim.Orientation; 850 VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale);
899 // make a vector pointing up 851
900 Vector3 verterr = Vector3.Zero; 852 VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
901 verterr.Z = 1.0f; 853
902 // rotate it to Body Angle 854 // Create a vector of the vehicle "up" in world coordinates
903 verterr = verterr * rotq; 855 Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation;
904 // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. 856 // verticalError.X and .Y are the World error amounts. They are 0 when there is no
905 // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go 857 // error (Vehicle Body is 'vertical'), and .Z will be 1. As the body leans to its
906 // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. 858 // side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall
907 if (verterr.Z < 0.0f) 859 // and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be
860 // modulated to prevent a stable inverted body.
861
862 // Error is 0 (no error) to +/- 2 (max error)
863 if (verticalError.Z < 0.0f)
908 { 864 {
909 verterr.X = 2.0f - verterr.X; 865 verticalError.X = 2.0f - verticalError.X;
910 verterr.Y = 2.0f - verterr.Y; 866 verticalError.Y = 2.0f - verticalError.Y;
911 } 867 }
912 // Error is 0 (no error) to +/- 2 (max error) 868 // scale it by VAservo (timestep and timescale)
913 // scale it by VAservo 869 verticalError = verticalError * VAservo;
914 verterr = verterr * VAservo; 870
915 871 // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y
916 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so 872 // then .X increases, so change Body angular velocity X based on Y, and Y based on X.
917 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. 873 // Z is not changed.
918 vertattr.X = verterr.Y; 874 vertattr.X = verticalError.Y;
919 vertattr.Y = - verterr.X; 875 vertattr.Y = - verticalError.X;
920 vertattr.Z = 0f; 876 vertattr.Z = 0f;
921 877
922 // scaling appears better usingsquare-law 878 // scaling appears better usingsquare-law
879 Vector3 angularVelocity = Prim.ForceRotationalVelocity;
923 float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); 880 float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
924 vertattr.X += bounce * angularVelocity.X; 881 vertattr.X += bounce * angularVelocity.X;
925 vertattr.Y += bounce * angularVelocity.Y; 882 vertattr.Y += bounce * angularVelocity.Y;
926 883
927 DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", 884 VDetailLog("{0},MoveAngular,verticalAttraction,VAservo={1},effic={2},verticalError={3},bounce={4},vertattr={5}",
928 m_prim.LocalID, verterr, bounce, vertattr); 885 Prim.LocalID, VAservo, m_verticalAttractionEfficiency, verticalError, bounce, vertattr);
929 886
930 } // else vertical attractor is off 887 }
888 #endregion // Vertical attactor
889
890 #region Deflection
891
892 if (m_angularDeflectionEfficiency != 0)
893 {
894 // Compute a scaled vector that points in the preferred axis (X direction)
895 Vector3 scaledDefaultDirection =
896 new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0);
897 // Adding the current vehicle orientation and reference frame displaces the orientation to the frame.
898 // Rotate the scaled default axix relative to the actual vehicle direction giving where it should point.
899 Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame);
900
901 // Scale by efficiency and timescale
902 deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep;
903
904 VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}",
905 Prim.LocalID, preferredAxisOfMotion, deflection);
906 // This deflection computation is not correct.
907 deflection = Vector3.Zero;
908 }
909
910 #endregion
911
912 #region Banking
913
914 if (m_bankingEfficiency != 0)
915 {
916 Vector3 dir = Vector3.One * Prim.ForceOrientation;
917 float mult = (m_bankingMix*m_bankingMix)*-1*(m_bankingMix < 0 ? -1 : 1);
918 //Changes which way it banks in and out of turns
931 919
932 // m_lastVertAttractor = vertattr; 920 //Use the square of the efficiency, as it looks much more how SL banking works
921 float effSquared = (m_bankingEfficiency*m_bankingEfficiency);
922 if (m_bankingEfficiency < 0)
923 effSquared *= -1; //Keep the negative!
933 924
934 // Bank section tba 925 float mix = Math.Abs(m_bankingMix);
926 if (m_angularMotorVelocity.X == 0)
927 {
928 /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f))
929 {
930 Vector3 axisAngle;
931 float angle;
932 parent.Orientation.GetAxisAngle(out axisAngle, out angle);
933 Vector3 rotatedVel = parent.Velocity * parent.Orientation;
934 if ((rotatedVel.X < 0 && axisAngle.Y > 0) || (rotatedVel.X > 0 && axisAngle.Y < 0))
935 m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (1f) * 10;
936 else
937 m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (-1f) * 10;
938 }*/
939 }
940 else
941 banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4;
942 if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix)
943 //If they are colliding, we probably shouldn't shove the prim around... probably
944 {
945 float angVelZ = m_angularMotorVelocity.X*-1;
946 /*if(angVelZ > mix)
947 angVelZ = mix;
948 else if(angVelZ < -mix)
949 angVelZ = -mix;*/
950 //This controls how fast and how far the banking occurs
951 Vector3 bankingRot = new Vector3(angVelZ*(effSquared*mult), 0, 0);
952 if (bankingRot.X > 3)
953 bankingRot.X = 3;
954 else if (bankingRot.X < -3)
955 bankingRot.X = -3;
956 bankingRot *= Prim.ForceOrientation;
957 banking += bankingRot;
958 }
959 m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency;
960 VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},banking={3}",
961 Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, banking);
962 }
935 963
936 // Deflection section tba 964 #endregion
965
966 m_lastVertAttractor = vertattr;
937 967
938 // Sum velocities 968 // Sum velocities
939 m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection 969 m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection;
940 970
971 #region Linear Motor Offset
972
973 //Offset section
974 if (m_linearMotorOffset != Vector3.Zero)
975 {
976 //Offset of linear velocity doesn't change the linear velocity,
977 // but causes a torque to be applied, for example...
978 //
979 // IIIII >>> IIIII
980 // IIIII >>> IIIII
981 // IIIII >>> IIIII
982 // ^
983 // | Applying a force at the arrow will cause the object to move forward, but also rotate
984 //
985 //
986 // The torque created is the linear velocity crossed with the offset
987
988 // NOTE: this computation does should be in the linear section
989 // because there we know the impulse being applied.
990 Vector3 torqueFromOffset = Vector3.Zero;
991 // torqueFromOffset = Vector3.Cross(m_linearMotorOffset, appliedImpulse);
992 if (float.IsNaN(torqueFromOffset.X))
993 torqueFromOffset.X = 0;
994 if (float.IsNaN(torqueFromOffset.Y))
995 torqueFromOffset.Y = 0;
996 if (float.IsNaN(torqueFromOffset.Z))
997 torqueFromOffset.Z = 0;
998 torqueFromOffset *= m_vehicleMass;
999 Prim.ApplyTorqueImpulse(torqueFromOffset, true);
1000 VDetailLog("{0},BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
1001 }
1002
1003 #endregion
1004
941 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) 1005 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
942 { 1006 {
943 m_lastAngularVelocity.X = 0; 1007 m_lastAngularVelocity.X = 0;
944 m_lastAngularVelocity.Y = 0; 1008 m_lastAngularVelocity.Y = 0;
945 DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); 1009 VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
946 } 1010 }
947 1011
948 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) 1012 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
949 { 1013 {
950 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. 1014 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
951 DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); 1015 Prim.ZeroAngularMotion(true);
1016 VDetailLog("{0},MoveAngular,zeroAngularMotion,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
1017 }
1018 else
1019 {
1020 // Apply to the body.
1021 // The above calculates the absolute angular velocity needed. Angular velocity is massless.
1022 // Since we are stuffing the angular velocity directly into the object, the computed
1023 // velocity needs to be scaled by the timestep.
1024 Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep) - Prim.ForceRotationalVelocity);
1025 Prim.ForceRotationalVelocity = applyAngularForce;
1026
1027 // Decay the angular movement for next time
1028 Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep;
1029 m_lastAngularVelocity *= Vector3.One - decayamount;
1030
1031 VDetailLog("{0},MoveAngular,done,newRotVel={1},decay={2},lastAngular={3}",
1032 Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity);
952 } 1033 }
953
954 // apply friction
955 Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep);
956 m_lastAngularVelocity -= m_lastAngularVelocity * decayamount;
957
958 // Apply to the body
959 m_prim.RotationalVelocity = m_lastAngularVelocity;
960
961 DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity);
962 } //end MoveAngular 1034 } //end MoveAngular
963 1035
964 internal void LimitRotation(float timestep) 1036 internal void LimitRotation(float timestep)
965 { 1037 {
966 Quaternion rotq = m_prim.Orientation; 1038 Quaternion rotq = Prim.ForceOrientation;
967 Quaternion m_rot = rotq; 1039 Quaternion m_rot = rotq;
968 bool changed = false;
969 if (m_RollreferenceFrame != Quaternion.Identity) 1040 if (m_RollreferenceFrame != Quaternion.Identity)
970 { 1041 {
971 if (rotq.X >= m_RollreferenceFrame.X) 1042 if (rotq.X >= m_RollreferenceFrame.X)
972 { 1043 {
973 m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); 1044 m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2);
974 changed = true;
975 } 1045 }
976 if (rotq.Y >= m_RollreferenceFrame.Y) 1046 if (rotq.Y >= m_RollreferenceFrame.Y)
977 { 1047 {
978 m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); 1048 m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2);
979 changed = true;
980 } 1049 }
981 if (rotq.X <= -m_RollreferenceFrame.X) 1050 if (rotq.X <= -m_RollreferenceFrame.X)
982 { 1051 {
983 m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); 1052 m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2);
984 changed = true;
985 } 1053 }
986 if (rotq.Y <= -m_RollreferenceFrame.Y) 1054 if (rotq.Y <= -m_RollreferenceFrame.Y)
987 { 1055 {
988 m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); 1056 m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2);
989 changed = true;
990 } 1057 }
991 changed = true;
992 } 1058 }
993 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) 1059 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0)
994 { 1060 {
995 m_rot.X = 0; 1061 m_rot.X = 0;
996 m_rot.Y = 0; 1062 m_rot.Y = 0;
997 changed = true;
998 } 1063 }
999 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) 1064 if (rotq != m_rot)
1000 { 1065 {
1001 m_rot.X = 0; 1066 Prim.ForceOrientation = m_rot;
1002 m_rot.Y = 0; 1067 VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot);
1003 changed = true;
1004 } 1068 }
1005 if (changed)
1006 m_prim.Orientation = m_rot;
1007 1069
1008 DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
1009 } 1070 }
1010 1071
1011 // Invoke the detailed logger and output something if it's enabled. 1072 // Invoke the detailed logger and output something if it's enabled.
1012 private void DetailLog(string msg, params Object[] args) 1073 private void VDetailLog(string msg, params Object[] args)
1013 { 1074 {
1014 if (m_prim.Scene.VehicleLoggingEnabled) 1075 if (Prim.PhysicsScene.VehicleLoggingEnabled)
1015 m_prim.Scene.PhysicsLogging.Write(msg, args); 1076 Prim.PhysicsScene.DetailLog(msg, args);
1016 } 1077 }
1017 } 1078 }
1018} 1079}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 087b9bb..0df4310 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -32,35 +32,80 @@ using OMV = OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35public class BSLinkset 35public abstract class BSLinkset
36{ 36{
37 private static string LogHeader = "[BULLETSIM LINKSET]"; 37 // private static string LogHeader = "[BULLETSIM LINKSET]";
38 38
39 private BSPrim m_linksetRoot; 39 public enum LinksetImplementation
40 public BSPrim LinksetRoot { get { return m_linksetRoot; } } 40 {
41 Constraint = 0, // linkset tied together with constraints
42 Compound = 1, // linkset tied together as a compound object
43 Manual = 2 // linkset tied together manually (code moves all the pieces)
44 }
45 // Create the correct type of linkset for this child
46 public static BSLinkset Factory(BSScene physScene, BSPhysObject parent)
47 {
48 BSLinkset ret = null;
49
50 switch ((int)physScene.Params.linksetImplementation)
51 {
52 case (int)LinksetImplementation.Constraint:
53 ret = new BSLinksetConstraints(physScene, parent);
54 break;
55 case (int)LinksetImplementation.Compound:
56 ret = new BSLinksetCompound(physScene, parent);
57 break;
58 case (int)LinksetImplementation.Manual:
59 // ret = new BSLinksetManual(physScene, parent);
60 break;
61 default:
62 ret = new BSLinksetCompound(physScene, parent);
63 break;
64 }
65 return ret;
66 }
67
68 public BSPhysObject LinksetRoot { get; protected set; }
41 69
42 private BSScene m_physicsScene; 70 public BSScene PhysicsScene { get; private set; }
43 public BSScene PhysicsScene { get { return m_physicsScene; } }
44 71
45 // The children under the root in this linkset 72 static int m_nextLinksetID = 1;
46 private List<BSPrim> m_children; 73 public int LinksetID { get; private set; }
74
75 // The children under the root in this linkset.
76 protected HashSet<BSPhysObject> m_children;
47 77
48 // We lock the diddling of linkset classes to prevent any badness. 78 // We lock the diddling of linkset classes to prevent any badness.
49 // This locks the modification of the instances of this class. Changes 79 // This locks the modification of the instances of this class. Changes
50 // to the physical representation is done via the tainting mechenism. 80 // to the physical representation is done via the tainting mechenism.
51 private object m_linksetActivityLock = new Object(); 81 protected object m_linksetActivityLock = new Object();
82
83 // Some linksets have a preferred physical shape.
84 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
85 public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
86 {
87 return BSPhysicsShapeType.SHAPE_UNKNOWN;
88 }
52 89
90 // Linksets move around the children so the linkset might need to compute the child position
91 public virtual OMV.Vector3 Position(BSPhysObject member)
92 { return member.RawPosition; }
93 public virtual OMV.Quaternion Orientation(BSPhysObject member)
94 { return member.RawOrientation; }
95 // TODO: does this need to be done for Velocity and RotationalVelocityy?
96
53 // We keep the prim's mass in the linkset structure since it could be dependent on other prims 97 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
54 private float m_mass; 98 protected float m_mass;
55 public float LinksetMass 99 public float LinksetMass
56 { 100 {
57 get 101 get
58 { 102 {
59 m_mass = ComputeLinksetMass();
60 return m_mass; 103 return m_mass;
61 } 104 }
62 } 105 }
63 106
107 public virtual bool LinksetIsColliding { get { return false; } }
108
64 public OMV.Vector3 CenterOfMass 109 public OMV.Vector3 CenterOfMass
65 { 110 {
66 get { return ComputeLinksetCenterOfMass(); } 111 get { return ComputeLinksetCenterOfMass(); }
@@ -71,23 +116,31 @@ public class BSLinkset
71 get { return ComputeLinksetGeometricCenter(); } 116 get { return ComputeLinksetGeometricCenter(); }
72 } 117 }
73 118
74 public BSLinkset(BSScene scene, BSPrim parent) 119 protected void Initialize(BSScene scene, BSPhysObject parent)
75 { 120 {
76 // A simple linkset of one (no children) 121 // A simple linkset of one (no children)
77 m_physicsScene = scene; 122 LinksetID = m_nextLinksetID++;
78 m_linksetRoot = parent; 123 // We create LOTS of linksets.
79 m_children = new List<BSPrim>(); 124 if (m_nextLinksetID <= 0)
80 m_mass = parent.MassRaw; 125 m_nextLinksetID = 1;
126 PhysicsScene = scene;
127 LinksetRoot = parent;
128 m_children = new HashSet<BSPhysObject>();
129 m_mass = parent.RawMass;
81 } 130 }
82 131
83 // Link to a linkset where the child knows the parent. 132 // Link to a linkset where the child knows the parent.
84 // Parent changing should not happen so do some sanity checking. 133 // Parent changing should not happen so do some sanity checking.
85 // We return the parent's linkset so the child can track its membership. 134 // We return the parent's linkset so the child can track its membership.
86 public BSLinkset AddMeToLinkset(BSPrim child) 135 // Called at runtime.
136 public BSLinkset AddMeToLinkset(BSPhysObject child)
87 { 137 {
88 lock (m_linksetActivityLock) 138 lock (m_linksetActivityLock)
89 { 139 {
90 AddChildToLinkset(child); 140 // Don't add the root to its own linkset
141 if (!IsRoot(child))
142 AddChildToLinkset(child);
143 m_mass = ComputeLinksetMass();
91 } 144 }
92 return this; 145 return this;
93 } 146 }
@@ -95,36 +148,28 @@ public class BSLinkset
95 // Remove a child from a linkset. 148 // Remove a child from a linkset.
96 // Returns a new linkset for the child which is a linkset of one (just the 149 // Returns a new linkset for the child which is a linkset of one (just the
97 // orphened child). 150 // orphened child).
98 public BSLinkset RemoveMeFromLinkset(BSPrim child) 151 // Called at runtime.
152 public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
99 { 153 {
100 lock (m_linksetActivityLock) 154 lock (m_linksetActivityLock)
101 { 155 {
102 if (IsRoot(child)) 156 if (IsRoot(child))
103 { 157 {
104 // if root of linkset, take the linkset apart 158 // Cannot remove the root from a linkset.
105 while (m_children.Count > 0) 159 return this;
106 {
107 // Note that we don't do a foreach because the remove routine
108 // takes it out of the list.
109 RemoveChildFromOtherLinkset(m_children[0]);
110 }
111 m_children.Clear(); // just to make sure
112 }
113 else
114 {
115 // Just removing a child from an existing linkset
116 RemoveChildFromLinkset(child);
117 } 160 }
161 RemoveChildFromLinkset(child);
162 m_mass = ComputeLinksetMass();
118 } 163 }
119 164
120 // The child is down to a linkset of just itself 165 // The child is down to a linkset of just itself
121 return new BSLinkset(PhysicsScene, child); 166 return BSLinkset.Factory(PhysicsScene, child);
122 } 167 }
123 168
124 // Return 'true' if the passed object is the root object of this linkset 169 // Return 'true' if the passed object is the root object of this linkset
125 public bool IsRoot(BSPrim requestor) 170 public bool IsRoot(BSPhysObject requestor)
126 { 171 {
127 return (requestor.LocalID == m_linksetRoot.LocalID); 172 return (requestor.LocalID == LinksetRoot.LocalID);
128 } 173 }
129 174
130 public int NumberOfChildren { get { return m_children.Count; } } 175 public int NumberOfChildren { get { return m_children.Count; } }
@@ -133,12 +178,14 @@ public class BSLinkset
133 public bool HasAnyChildren { get { return (m_children.Count > 0); } } 178 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
134 179
135 // Return 'true' if this child is in this linkset 180 // Return 'true' if this child is in this linkset
136 public bool HasChild(BSPrim child) 181 public bool HasChild(BSPhysObject child)
137 { 182 {
138 bool ret = false; 183 bool ret = false;
139 lock (m_linksetActivityLock) 184 lock (m_linksetActivityLock)
140 { 185 {
141 foreach (BSPrim bp in m_children) 186 ret = m_children.Contains(child);
187 /* Safer version but the above should work
188 foreach (BSPhysObject bp in m_children)
142 { 189 {
143 if (child.LocalID == bp.LocalID) 190 if (child.LocalID == bp.LocalID)
144 { 191 {
@@ -146,274 +193,132 @@ public class BSLinkset
146 break; 193 break;
147 } 194 }
148 } 195 }
196 */
149 } 197 }
150 return ret; 198 return ret;
151 } 199 }
152 200
153 private float ComputeLinksetMass() 201 // Perform an action on each member of the linkset including root prim.
154 { 202 // Depends on the action on whether this should be done at taint time.
155 float mass = m_linksetRoot.MassRaw; 203 public delegate bool ForEachMemberAction(BSPhysObject obj);
156 foreach (BSPrim bp in m_children) 204 public virtual bool ForEachMember(ForEachMemberAction action)
157 {
158 mass += bp.MassRaw;
159 }
160 return mass;
161 }
162
163 private OMV.Vector3 ComputeLinksetCenterOfMass()
164 { 205 {
165 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; 206 bool ret = false;
166 float totalMass = m_linksetRoot.MassRaw;
167
168 lock (m_linksetActivityLock) 207 lock (m_linksetActivityLock)
169 { 208 {
170 foreach (BSPrim bp in m_children) 209 action(LinksetRoot);
210 foreach (BSPhysObject po in m_children)
171 { 211 {
172 com += bp.Position * bp.MassRaw; 212 if (action(po))
173 totalMass += bp.MassRaw; 213 break;
174 } 214 }
175 if (totalMass != 0f)
176 com /= totalMass;
177 } 215 }
178 216 return ret;
179 return com;
180 } 217 }
181 218
182 private OMV.Vector3 ComputeLinksetGeometricCenter() 219 // I am the root of a linkset and a new child is being added
183 { 220 // Called while LinkActivity is locked.
184 OMV.Vector3 com = m_linksetRoot.Position; 221 protected abstract void AddChildToLinkset(BSPhysObject child);
185
186 lock (m_linksetActivityLock)
187 {
188 foreach (BSPrim bp in m_children)
189 {
190 com += bp.Position * bp.MassRaw;
191 }
192 com /= (m_children.Count + 1);
193 }
194 222
195 return com; 223 // I am the root of a linkset and one of my children is being removed.
196 } 224 // Safe to call even if the child is not really in my linkset.
225 protected abstract void RemoveChildFromLinkset(BSPhysObject child);
197 226
198 // When physical properties are changed the linkset needs to recalculate 227 // When physical properties are changed the linkset needs to recalculate
199 // its internal properties. 228 // its internal properties.
200 public void Refresh(BSPrim requestor) 229 // May be called at runtime or taint-time.
201 { 230 public abstract void Refresh(BSPhysObject requestor);
202 // If there are no children, there aren't any constraints to recompute 231
203 if (!HasAnyChildren) 232 // The object is going dynamic (physical). Do any setup necessary
204 return; 233 // for a dynamic linkset.
205 234 // Only the state of the passed object can be modified. The rest of the linkset
206 // Only the root does the recomputation 235 // has not yet been fully constructed.
207 if (IsRoot(requestor)) 236 // Return 'true' if any properties updated on the passed object.
208 { 237 // Called at taint-time!
209 PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() 238 public abstract bool MakeDynamic(BSPhysObject child);
210 { 239
211 RecomputeLinksetConstraintVariables(); 240 // The object is going static (non-physical). Do any setup necessary
212 }); 241 // for a static linkset.
213 } 242 // Return 'true' if any properties updated on the passed object.
214 } 243 // Called at taint-time!
215 244 public abstract bool MakeStatic(BSPhysObject child);
216 // Call each of the constraints that make up this linkset and recompute the 245
217 // various transforms and variables. Used when objects are added or removed 246 // Called when a parameter update comes from the physics engine for any object
218 // from a linkset to make sure the constraints know about the new mass and 247 // of the linkset is received.
219 // geometry. 248 // Called at taint-time!!
220 // Must only be called at taint time!! 249 public abstract void UpdateProperties(BSPhysObject physObject);
221 private bool RecomputeLinksetConstraintVariables() 250
251 // Routine used when rebuilding the body of the root of the linkset
252 // Destroy all the constraints have have been made to root.
253 // This is called when the root body is changing.
254 // Returns 'true' of something was actually removed and would need restoring
255 // Called at taint-time!!
256 public abstract bool RemoveBodyDependencies(BSPrim child);
257
258 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
259 // this routine will restore the removed constraints.
260 // Called at taint-time!!
261 public abstract void RestoreBodyDependencies(BSPrim child);
262
263 // ================================================================
264 protected virtual float ComputeLinksetMass()
222 { 265 {
223 float linksetMass = LinksetMass; 266 float mass = LinksetRoot.RawMass;
224 lock (m_linksetActivityLock) 267 if (HasAnyChildren)
225 { 268 {
226 foreach (BSPrim child in m_children) 269 lock (m_linksetActivityLock)
227 { 270 {
228 BSConstraint constrain; 271 foreach (BSPhysObject bp in m_children)
229 if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain))
230 {
231 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
232 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
233 constrain.RecomputeConstraintVariables(linksetMass);
234 }
235 else
236 { 272 {
237 // Non-fatal error that can happen when children are being added to the linkset but 273 mass += bp.RawMass;
238 // their constraints have not been created yet.
239 // Caused by the fact that m_children is built at run time but building constraints
240 // happens at taint time.
241 // m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}",
242 // m_linksetRoot.Body.ID, child.Body.ID);
243 } 274 }
244 } 275 }
245 } 276 }
246 return false; 277 return mass;
247 } 278 }
248 279
249 // I am the root of a linkset and a new child is being added 280 protected virtual OMV.Vector3 ComputeLinksetCenterOfMass()
250 // Called while LinkActivity is locked.
251 private void AddChildToLinkset(BSPrim child)
252 { 281 {
253 if (!HasChild(child)) 282 OMV.Vector3 com;
283 lock (m_linksetActivityLock)
254 { 284 {
255 m_children.Add(child); 285 com = LinksetRoot.Position * LinksetRoot.RawMass;
286 float totalMass = LinksetRoot.RawMass;
256 287
257 BSPrim rootx = LinksetRoot; // capture the root as of now 288 foreach (BSPhysObject bp in m_children)
258 BSPrim childx = child;
259 m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
260 { 289 {
261 // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); 290 com += bp.Position * bp.RawMass;
262 // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); 291 totalMass += bp.RawMass;
263 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child 292 }
264 }); 293 if (totalMass != 0f)
294 com /= totalMass;
265 } 295 }
266 return;
267 }
268 296
269 // Forcefully removing a child from a linkset. 297 return com;
270 // This is not being called by the child so we have to make sure the child doesn't think
271 // it's still connected to the linkset.
272 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
273 // has to be updated also (like pointer to prim's parent).
274 private void RemoveChildFromOtherLinkset(BSPrim pchild)
275 {
276 pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
277 RemoveChildFromLinkset(pchild);
278 } 298 }
279 299
280 // I am the root of a linkset and one of my children is being removed. 300 protected virtual OMV.Vector3 ComputeLinksetGeometricCenter()
281 // Safe to call even if the child is not really in my linkset.
282 private void RemoveChildFromLinkset(BSPrim child)
283 { 301 {
284 if (m_children.Remove(child)) 302 OMV.Vector3 com;
303 lock (m_linksetActivityLock)
285 { 304 {
286 BSPrim rootx = LinksetRoot; // capture the root as of now 305 com = LinksetRoot.Position;
287 BSPrim childx = child;
288 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
289 {
290 // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
291 // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
292
293 PhysicallyUnlinkAChildFromRoot(rootx, childx);
294 });
295 306
296 RecomputeLinksetConstraintVariables(); 307 foreach (BSPhysObject bp in m_children)
297 } 308 {
298 else 309 com += bp.Position * bp.RawMass;
299 { 310 }
300 // This will happen if we remove the root of the linkset first. Non-fatal occurance. 311 com /= (m_children.Count + 1);
301 // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
302 } 312 }
303 return;
304 }
305
306 // Create a constraint between me (root of linkset) and the passed prim (the child).
307 // Called at taint time!
308 private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim)
309 {
310 // Zero motion for children so they don't interpolate
311 childPrim.ZeroMotion();
312
313 // Relative position normalized to the root prim
314 // Essentually a vector pointing from center of rootPrim to center of childPrim
315 OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
316
317 // real world coordinate of midpoint between the two objects
318 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
319
320 // create a constraint that allows no freedom of movement between the two objects
321 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
322 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
323 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}",
324 rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint);
325 BS6DofConstraint constrain = new BS6DofConstraint(
326 m_physicsScene.World, rootPrim.Body, childPrim.Body,
327 midPoint,
328 true,
329 true
330 );
331 /* NOTE: attempt to build constraint with full frame computation, etc.
332 * Using the midpoint is easier since it lets the Bullet code use the transforms
333 * of the objects.
334 * Code left here as an example.
335 // ==================================================================================
336 // relative position normalized to the root prim
337 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
338 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
339
340 // relative rotation of the child to the parent
341 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
342 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
343
344 // create a constraint that allows no freedom of movement between the two objects
345 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
346 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
347 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
348 BS6DofConstraint constrain = new BS6DofConstraint(
349 PhysicsScene.World, rootPrim.Body, childPrim.Body,
350 OMV.Vector3.Zero,
351 OMV.Quaternion.Inverse(rootPrim.Orientation),
352 OMV.Vector3.Zero,
353 OMV.Quaternion.Inverse(childPrim.Orientation),
354 // A point half way between the parent and child
355 // childRelativePosition/2,
356 // childRelativeRotation,
357 // childRelativePosition/2,
358 // inverseChildRelativeRotation,
359 true,
360 true
361 );
362 // ==================================================================================
363 */
364
365 m_physicsScene.Constraints.AddConstraint(constrain);
366
367 // zero linear and angular limits makes the objects unable to move in relation to each other
368 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
369 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
370
371 // tweek the constraint to increase stability
372 constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset));
373 constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor),
374 PhysicsScene.Params.linkConstraintTransMotorMaxVel,
375 PhysicsScene.Params.linkConstraintTransMotorMaxForce);
376 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
377
378 RecomputeLinksetConstraintVariables();
379 }
380 313
381 // Remove linkage between myself and a particular child 314 return com;
382 // Called at taint time!
383 private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim)
384 {
385 // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
386 // LogHeader, rootPrim.LocalID, childPrim.LocalID);
387 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
388
389 // Find the constraint for this link and get rid of it from the overall collection and from my list
390 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body);
391
392 // Make the child refresh its location
393 BulletSimAPI.PushUpdate2(childPrim.Body.Ptr);
394 }
395
396 // Remove linkage between myself and any possible children I might have
397 // Called at taint time!
398 private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim)
399 {
400 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
401 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
402
403 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body);
404 }
405
406 // Invoke the detailed logger and output something if it's enabled.
407 private void DebugLog(string msg, params Object[] args)
408 {
409 if (m_physicsScene.ShouldDebugLog)
410 m_physicsScene.Logger.DebugFormat(msg, args);
411 } 315 }
412 316
413 // Invoke the detailed logger and output something if it's enabled. 317 // Invoke the detailed logger and output something if it's enabled.
414 private void DetailLog(string msg, params Object[] args) 318 protected void DetailLog(string msg, params Object[] args)
415 { 319 {
416 m_physicsScene.PhysicsLogging.Write(msg, args); 320 if (PhysicsScene.PhysicsLogging.Enabled)
321 PhysicsScene.DetailLog(msg, args);
417 } 322 }
418 323
419} 324}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
new file mode 100755
index 0000000..b9c2cf9
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -0,0 +1,275 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OMV = OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35public sealed class BSLinksetCompound : BSLinkset
36{
37 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
38
39 public BSLinksetCompound(BSScene scene, BSPhysObject parent)
40 {
41 base.Initialize(scene, parent);
42 }
43
44 // For compound implimented linksets, if there are children, use compound shape for the root.
45 public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
46 {
47 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
48 if (IsRoot(requestor) && HasAnyChildren)
49 {
50 ret = BSPhysicsShapeType.SHAPE_COMPOUND;
51 }
52 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
53 return ret;
54 }
55
56 // When physical properties are changed the linkset needs to recalculate
57 // its internal properties.
58 // This is queued in the 'post taint' queue so the
59 // refresh will happen once after all the other taints are applied.
60 public override void Refresh(BSPhysObject requestor)
61 {
62 // External request for Refresh (from BSPrim) is not necessary
63 // InternalRefresh(requestor);
64 }
65
66 private void InternalRefresh(BSPhysObject requestor)
67 {
68 DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID);
69 // Queue to happen after all the other taint processing
70 PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate()
71 {
72 if (IsRoot(requestor) && HasAnyChildren)
73 RecomputeLinksetCompound();
74 });
75 }
76
77 // The object is going dynamic (physical). Do any setup necessary
78 // for a dynamic linkset.
79 // Only the state of the passed object can be modified. The rest of the linkset
80 // has not yet been fully constructed.
81 // Return 'true' if any properties updated on the passed object.
82 // Called at taint-time!
83 public override bool MakeDynamic(BSPhysObject child)
84 {
85 bool ret = false;
86 DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child));
87 if (!IsRoot(child))
88 {
89 // Physical children are removed from the world as the shape ofthe root compound
90 // shape takes over.
91 BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
92 BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
93 ret = true;
94 }
95 return ret;
96 }
97
98 // The object is going static (non-physical). Do any setup necessary for a static linkset.
99 // Return 'true' if any properties updated on the passed object.
100 // This doesn't normally happen -- OpenSim removes the objects from the physical
101 // world if it is a static linkset.
102 // Called at taint-time!
103 public override bool MakeStatic(BSPhysObject child)
104 {
105 bool ret = false;
106 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
107 if (!IsRoot(child))
108 {
109 // The non-physical children can come back to life.
110 BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
111 // Don't force activation so setting of DISABLE_SIMULATION can stay.
112 BulletSimAPI.Activate2(child.PhysBody.ptr, false);
113 ret = true;
114 }
115 return ret;
116 }
117
118 // Called at taint-time!!
119 public override void UpdateProperties(BSPhysObject updated)
120 {
121 // Nothing to do for constraints on property updates
122 }
123
124 // The children move around in relationship to the root.
125 // Just grab the current values of wherever it is right now.
126 public override OMV.Vector3 Position(BSPhysObject member)
127 {
128 return BulletSimAPI.GetPosition2(member.PhysBody.ptr);
129 }
130
131 public override OMV.Quaternion Orientation(BSPhysObject member)
132 {
133 return BulletSimAPI.GetOrientation2(member.PhysBody.ptr);
134 }
135
136 // Routine called when rebuilding the body of some member of the linkset.
137 // Since we don't keep in world relationships, do nothing unless it's a child changing.
138 // Returns 'true' of something was actually removed and would need restoring
139 // Called at taint-time!!
140 public override bool RemoveBodyDependencies(BSPrim child)
141 {
142 bool ret = false;
143
144 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
145 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child));
146
147 if (!IsRoot(child))
148 {
149 // Cause the current shape to be freed and the new one to be built.
150 InternalRefresh(LinksetRoot);
151 ret = true;
152 }
153
154 return ret;
155 }
156
157 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
158 // this routine will restore the removed constraints.
159 // Called at taint-time!!
160 public override void RestoreBodyDependencies(BSPrim child)
161 {
162 // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints.
163 }
164
165 // ================================================================
166
167 // Add a new child to the linkset.
168 // Called while LinkActivity is locked.
169 protected override void AddChildToLinkset(BSPhysObject child)
170 {
171 if (!HasChild(child))
172 {
173 m_children.Add(child);
174
175 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
176
177 // Cause constraints and assorted properties to be recomputed before the next simulation step.
178 InternalRefresh(LinksetRoot);
179 }
180 return;
181 }
182
183 // Remove the specified child from the linkset.
184 // Safe to call even if the child is not really in my linkset.
185 protected override void RemoveChildFromLinkset(BSPhysObject child)
186 {
187 if (m_children.Remove(child))
188 {
189 DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
190 child.LocalID,
191 LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"),
192 child.LocalID, child.PhysBody.ptr.ToString("X"));
193
194 // Cause the child's body to be rebuilt and thus restored to normal operation
195 child.ForceBodyShapeRebuild(false);
196
197 if (!HasAnyChildren)
198 {
199 // The linkset is now empty. The root needs rebuilding.
200 LinksetRoot.ForceBodyShapeRebuild(false);
201 }
202 else
203 {
204 // Schedule a rebuild of the linkset before the next simulation tick.
205 InternalRefresh(LinksetRoot);
206 }
207 }
208 return;
209 }
210
211 // Called before the simulation step to make sure the compound based linkset
212 // is all initialized.
213 // Constraint linksets are rebuilt every time.
214 // Note that this works for rebuilding just the root after a linkset is taken apart.
215 // Called at taint time!!
216 private void RecomputeLinksetCompound()
217 {
218 // Cause the root shape to be rebuilt as a compound object with just the root in it
219 LinksetRoot.ForceBodyShapeRebuild(true);
220
221 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
222 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
223
224 // Add a shape for each of the other children in the linkset
225 ForEachMember(delegate(BSPhysObject cPrim)
226 {
227 if (!IsRoot(cPrim))
228 {
229 // Each child position and rotation is given relative to the root.
230 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
231 OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
232 OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
233
234 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}",
235 LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot);
236
237 if (cPrim.PhysShape.isNativeShape)
238 {
239 // Native shapes are not shared so we need to create a new one.
240 // A mesh or hull is created because scale is not available on a native shape.
241 // (TODO: Bullet does have a btScaledCollisionShape. Can that be used?)
242 BulletShape saveShape = cPrim.PhysShape;
243 cPrim.PhysShape.ptr = IntPtr.Zero; // Don't let the create free the child's shape
244 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
245 BulletShape newShape = cPrim.PhysShape;
246 cPrim.PhysShape = saveShape;
247 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot);
248 }
249 else
250 {
251 // For the shared shapes (meshes and hulls), just use the shape in the child.
252 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
253 {
254 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
255 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
256 }
257 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot);
258 }
259 }
260 return false; // 'false' says to move onto the next child in the list
261 });
262
263 // With all of the linkset packed into the root prim, it has the mass of everyone.
264 float linksetMass = LinksetMass;
265 LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
266
267 BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr);
268
269 // DEBUG: see of inter-linkset collisions are causing problems for constraint linksets.
270 // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr,
271 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
272
273 }
274}
275} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
new file mode 100755
index 0000000..c855fda
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -0,0 +1,327 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OMV = OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35public sealed class BSLinksetConstraints : BSLinkset
36{
37 // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
38
39 public BSLinksetConstraints(BSScene scene, BSPhysObject parent)
40 {
41 base.Initialize(scene, parent);
42 }
43
44 // When physical properties are changed the linkset needs to recalculate
45 // its internal properties.
46 // This is queued in the 'post taint' queue so the
47 // refresh will happen once after all the other taints are applied.
48 public override void Refresh(BSPhysObject requestor)
49 {
50 // Queue to happen after all the other taint processing
51 PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
52 {
53 if (HasAnyChildren && IsRoot(requestor))
54 RecomputeLinksetConstraints();
55 });
56 }
57
58 // The object is going dynamic (physical). Do any setup necessary
59 // for a dynamic linkset.
60 // Only the state of the passed object can be modified. The rest of the linkset
61 // has not yet been fully constructed.
62 // Return 'true' if any properties updated on the passed object.
63 // Called at taint-time!
64 public override bool MakeDynamic(BSPhysObject child)
65 {
66 // What is done for each object in BSPrim is what we want.
67 return false;
68 }
69
70 // The object is going static (non-physical). Do any setup necessary for a static linkset.
71 // Return 'true' if any properties updated on the passed object.
72 // This doesn't normally happen -- OpenSim removes the objects from the physical
73 // world if it is a static linkset.
74 // Called at taint-time!
75 public override bool MakeStatic(BSPhysObject child)
76 {
77 // What is done for each object in BSPrim is what we want.
78 return false;
79 }
80
81 // Called at taint-time!!
82 public override void UpdateProperties(BSPhysObject updated)
83 {
84 // Nothing to do for constraints on property updates
85 }
86
87 // The children of the linkset are moved around by the constraints.
88 // Just grab the current values of wherever it is right now.
89 public override OMV.Vector3 Position(BSPhysObject member)
90 {
91 return BulletSimAPI.GetPosition2(member.PhysBody.ptr);
92 }
93
94 public override OMV.Quaternion Orientation(BSPhysObject member)
95 {
96 return BulletSimAPI.GetOrientation2(member.PhysBody.ptr);
97 }
98
99 // Routine called when rebuilding the body of some member of the linkset.
100 // Destroy all the constraints have have been made to root and set
101 // up to rebuild the constraints before the next simulation step.
102 // Returns 'true' of something was actually removed and would need restoring
103 // Called at taint-time!!
104 public override bool RemoveBodyDependencies(BSPrim child)
105 {
106 bool ret = false;
107
108 DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}",
109 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"));
110
111 lock (m_linksetActivityLock)
112 {
113 // Just undo all the constraints for this linkset. Rebuild at the end of the step.
114 ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
115 // Cause the constraints, et al to be rebuilt before the next simulation step.
116 Refresh(LinksetRoot);
117 }
118 return ret;
119 }
120
121 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
122 // this routine will restore the removed constraints.
123 // Called at taint-time!!
124 public override void RestoreBodyDependencies(BSPrim child)
125 {
126 // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints.
127 }
128
129 // ================================================================
130
131 // Add a new child to the linkset.
132 // Called while LinkActivity is locked.
133 protected override void AddChildToLinkset(BSPhysObject child)
134 {
135 if (!HasChild(child))
136 {
137 m_children.Add(child);
138
139 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
140
141 // Cause constraints and assorted properties to be recomputed before the next simulation step.
142 Refresh(LinksetRoot);
143 }
144 return;
145 }
146
147 // Remove the specified child from the linkset.
148 // Safe to call even if the child is not really in my linkset.
149 protected override void RemoveChildFromLinkset(BSPhysObject child)
150 {
151 if (m_children.Remove(child))
152 {
153 BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
154 BSPhysObject childx = child;
155
156 DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
157 childx.LocalID,
158 rootx.LocalID, rootx.PhysBody.ptr.ToString("X"),
159 childx.LocalID, childx.PhysBody.ptr.ToString("X"));
160
161 PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate()
162 {
163 PhysicallyUnlinkAChildFromRoot(rootx, childx);
164 });
165 // See that the linkset parameters are recomputed at the end of the taint time.
166 Refresh(LinksetRoot);
167 }
168 else
169 {
170 // Non-fatal occurance.
171 // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
172 }
173 return;
174 }
175
176 // Create a constraint between me (root of linkset) and the passed prim (the child).
177 // Called at taint time!
178 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
179 {
180 // Don't build the constraint when asked. Put it off until just before the simulation step.
181 Refresh(rootPrim);
182 }
183
184 private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim)
185 {
186 // Zero motion for children so they don't interpolate
187 childPrim.ZeroMotion(true);
188
189 // Relative position normalized to the root prim
190 // Essentually a vector pointing from center of rootPrim to center of childPrim
191 OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
192
193 // real world coordinate of midpoint between the two objects
194 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
195
196 DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
197 rootPrim.LocalID,
198 rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"),
199 childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X"),
200 rootPrim.Position, childPrim.Position, midPoint);
201
202 // create a constraint that allows no freedom of movement between the two objects
203 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
204
205 BSConstraint6Dof constrain = new BSConstraint6Dof(
206 PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true );
207 // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true );
208
209 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
210 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
211 * of the objects.
212 * Code left for future programmers.
213 // ==================================================================================
214 // relative position normalized to the root prim
215 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
216 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
217
218 // relative rotation of the child to the parent
219 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
220 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
221
222 DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
223 BS6DofConstraint constrain = new BS6DofConstraint(
224 PhysicsScene.World, rootPrim.Body, childPrim.Body,
225 OMV.Vector3.Zero,
226 OMV.Quaternion.Inverse(rootPrim.Orientation),
227 OMV.Vector3.Zero,
228 OMV.Quaternion.Inverse(childPrim.Orientation),
229 true,
230 true
231 );
232 // ==================================================================================
233 */
234
235 PhysicsScene.Constraints.AddConstraint(constrain);
236
237 // zero linear and angular limits makes the objects unable to move in relation to each other
238 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
239 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
240
241 // tweek the constraint to increase stability
242 constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset));
243 constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor),
244 PhysicsScene.Params.linkConstraintTransMotorMaxVel,
245 PhysicsScene.Params.linkConstraintTransMotorMaxForce);
246 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
247 if (PhysicsScene.Params.linkConstraintSolverIterations != 0f)
248 {
249 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
250 }
251 return constrain;
252 }
253
254 // Remove linkage between the linkset root and a particular child
255 // The root and child bodies are passed in because we need to remove the constraint between
256 // the bodies that were present at unlink time.
257 // Called at taint time!
258 private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
259 {
260 bool ret = false;
261 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
262 rootPrim.LocalID,
263 rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"),
264 childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X"));
265
266 // Find the constraint for this link and get rid of it from the overall collection and from my list
267 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody))
268 {
269 // Make the child refresh its location
270 BulletSimAPI.PushUpdate2(childPrim.PhysBody.ptr);
271 ret = true;
272 }
273
274 return ret;
275 }
276
277 // Remove linkage between myself and any possible children I might have.
278 // Returns 'true' of any constraints were destroyed.
279 // Called at taint time!
280 private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
281 {
282 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
283
284 return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody);
285 }
286
287 // Call each of the constraints that make up this linkset and recompute the
288 // various transforms and variables. Create constraints of not created yet.
289 // Called before the simulation step to make sure the constraint based linkset
290 // is all initialized.
291 // Called at taint time!!
292 private void RecomputeLinksetConstraints()
293 {
294 float linksetMass = LinksetMass;
295 LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
296
297 // DEBUG: see of inter-linkset collisions are causing problems
298 // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr,
299 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
300 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}",
301 LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass);
302
303 foreach (BSPhysObject child in m_children)
304 {
305 // A child in the linkset physically shows the mass of the whole linkset.
306 // This allows Bullet to apply enough force on the child to move the whole linkset.
307 // (Also do the mass stuff before recomputing the constraint so mass is not zero.)
308 child.UpdatePhysicalMassProperties(linksetMass);
309
310 BSConstraint constrain;
311 if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain))
312 {
313 // If constraint doesn't exist yet, create it.
314 constrain = BuildConstraint(LinksetRoot, child);
315 }
316 constrain.RecomputeConstraintVariables(linksetMass);
317
318 // DEBUG: see of inter-linkset collisions are causing problems
319 // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr,
320 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
321
322 // BulletSimAPI.DumpConstraint2(PhysicsScene.World.ptr, constrain.Constraint.ptr); // DEBUG DEBUG
323 }
324
325 }
326}
327}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
new file mode 100755
index 0000000..bc6e4c4
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
@@ -0,0 +1,104 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4using OpenMetaverse;
5
6namespace OpenSim.Region.Physics.BulletSPlugin
7{
8public abstract class BSMotor
9{
10 public virtual void Reset() { }
11 public virtual void Zero() { }
12}
13// Can all the incremental stepping be replaced with motor classes?
14public class BSVMotor : BSMotor
15{
16 public Vector3 FrameOfReference { get; set; }
17 public Vector3 Offset { get; set; }
18
19 public float TimeScale { get; set; }
20 public float TargetValueDecayTimeScale { get; set; }
21 public Vector3 CurrentValueReductionTimescale { get; set; }
22 public float Efficiency { get; set; }
23
24 public Vector3 TargetValue { get; private set; }
25 public Vector3 CurrentValue { get; private set; }
26
27
28
29 BSVMotor(float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency)
30 {
31 TimeScale = timeScale;
32 TargetValueDecayTimeScale = decayTimeScale;
33 CurrentValueReductionTimescale = frictionTimeScale;
34 Efficiency = efficiency;
35 }
36 public void SetCurrent(Vector3 current)
37 {
38 CurrentValue = current;
39 }
40 public void SetTarget(Vector3 target)
41 {
42 TargetValue = target;
43 }
44 public Vector3 Step(float timeStep)
45 {
46 if (CurrentValue.LengthSquared() > 0.001f)
47 {
48 // Vector3 origDir = Target; // DEBUG
49 // Vector3 origVel = CurrentValue; // DEBUG
50
51 // Add (desiredVelocity - currentAppliedVelocity) / howLongItShouldTakeToComplete
52 Vector3 addAmount = (TargetValue - CurrentValue)/(TargetValue) * timeStep;
53 CurrentValue += addAmount;
54
55 float decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep;
56 TargetValue *= (1f - decayFactor);
57
58 Vector3 frictionFactor = (Vector3.One / CurrentValueReductionTimescale) * timeStep;
59 CurrentValue *= (Vector3.One - frictionFactor);
60 }
61 else
62 {
63 // if what remains of direction is very small, zero it.
64 TargetValue = Vector3.Zero;
65 CurrentValue = Vector3.Zero;
66
67 // VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID);
68 }
69 return CurrentValue;
70 }
71}
72
73public class BSFMotor : BSMotor
74{
75 public float TimeScale { get; set; }
76 public float DecayTimeScale { get; set; }
77 public float Friction { get; set; }
78 public float Efficiency { get; set; }
79
80 public float Target { get; private set; }
81 public float CurrentValue { get; private set; }
82
83 BSFMotor(float timeScale, float decayTimescale, float friction, float efficiency)
84 {
85 }
86 public void SetCurrent(float target)
87 {
88 }
89 public void SetTarget(float target)
90 {
91 }
92 public float Step(float timeStep)
93 {
94 return 0f;
95 }
96}
97public class BSPIDMotor : BSMotor
98{
99 // TODO: write and use this one
100 BSPIDMotor()
101 {
102 }
103}
104}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
new file mode 100755
index 0000000..f6a890e
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -0,0 +1,263 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OMV = OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34
35namespace OpenSim.Region.Physics.BulletSPlugin
36{
37/*
38 * Class to wrap all objects.
39 * The rest of BulletSim doesn't need to keep checking for avatars or prims
40 * unless the difference is significant.
41 *
42 * Variables in the physicsl objects are in three forms:
43 * VariableName: used by the simulator and performs taint operations, etc
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.
46 * The last two (and certainly the last one) should be referenced only in taint-time.
47 */
48public abstract class BSPhysObject : PhysicsActor
49{
50 protected BSPhysObject()
51 {
52 }
53 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName)
54 {
55 PhysicsScene = parentScene;
56 LocalID = localID;
57 PhysObjectName = name;
58 TypeName = typeName;
59
60 Linkset = BSLinkset.Factory(PhysicsScene, this);
61 LastAssetBuildFailed = false;
62
63 CollisionCollection = new CollisionEventUpdate();
64 SubscribedEventsMs = 0;
65 CollidingStep = 0;
66 CollidingGroundStep = 0;
67 }
68
69 public BSScene PhysicsScene { get; protected set; }
70 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
71 public string PhysObjectName { get; protected set; }
72 public string TypeName { get; protected set; }
73
74 public BSLinkset Linkset { get; set; }
75
76 // Return the object mass without calculating it or having side effects
77 public abstract float RawMass { get; }
78 // Set the raw mass but also update physical mass properties (inertia, ...)
79 public abstract void UpdatePhysicalMassProperties(float mass);
80
81 // The last value calculated for the prim's inertia
82 public OMV.Vector3 Inertia { get; set; }
83
84 // Reference to the physical body (btCollisionObject) of this object
85 public BulletBody PhysBody;
86 // Reference to the physical shape (btCollisionShape) of this object
87 public BulletShape PhysShape;
88
89 // 'true' if the mesh's underlying asset failed to build.
90 // This will keep us from looping after the first time the build failed.
91 public bool LastAssetBuildFailed { get; set; }
92
93 // The objects base shape information. Null if not a prim type shape.
94 public PrimitiveBaseShape BaseShape { get; protected set; }
95 // Some types of objects have preferred physical representations.
96 // Returns SHAPE_UNKNOWN if there is no preference.
97 public virtual BSPhysicsShapeType PreferredPhysicalShape
98 {
99 get { return BSPhysicsShapeType.SHAPE_UNKNOWN; }
100 }
101
102 // When the physical properties are updated, an EntityProperty holds the update values.
103 // Keep the current and last EntityProperties to enable computation of differences
104 // between the current update and the previous values.
105 public EntityProperties CurrentEntityProperties { get; set; }
106 public EntityProperties LastEntityProperties { get; set; }
107
108 public abstract OMV.Vector3 Scale { get; set; }
109 public abstract bool IsSolid { get; }
110 public abstract bool IsStatic { get; }
111
112 // Stop all physical motion.
113 public abstract void ZeroMotion(bool inTaintTime);
114 public abstract void ZeroAngularMotion(bool inTaintTime);
115
116 // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured.
117 public virtual void StepVehicle(float timeStep) { }
118
119 // Update the physical location and motion of the object. Called with data from Bullet.
120 public abstract void UpdateProperties(EntityProperties entprop);
121
122 // Tell the object to clean up.
123 public abstract void Destroy();
124
125 public abstract OMV.Vector3 RawPosition { get; set; }
126 public abstract OMV.Vector3 ForcePosition { get; set; }
127
128 public abstract OMV.Quaternion RawOrientation { get; set; }
129 public abstract OMV.Quaternion ForceOrientation { get; set; }
130
131 public abstract OMV.Vector3 ForceVelocity { get; set; }
132
133 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
134
135 public abstract float ForceBuoyancy { get; set; }
136
137 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
138
139 #region Collisions
140
141 // Requested number of milliseconds between collision events. Zero means disabled.
142 protected int SubscribedEventsMs { get; set; }
143 // Given subscription, the time that a collision may be passed up
144 protected int NextCollisionOkTime { get; set; }
145 // The simulation step that last had a collision
146 protected long CollidingStep { get; set; }
147 // The simulation step that last had a collision with the ground
148 protected long CollidingGroundStep { get; set; }
149 // The collision flags we think are set in Bullet
150 protected CollisionFlags CurrentCollisionFlags { get; set; }
151
152 // The collisions that have been collected this tick
153 protected CollisionEventUpdate CollisionCollection;
154
155 // The simulation step is telling this object about a collision.
156 // Return 'true' if a collision was processed and should be sent up.
157 // Called at taint time from within the Step() function
158 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
159 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
160 {
161 bool ret = false;
162
163 // The following lines make IsColliding() and IsCollidingGround() work
164 CollidingStep = PhysicsScene.SimulationStep;
165 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID)
166 {
167 CollidingGroundStep = PhysicsScene.SimulationStep;
168 }
169
170 // prims in the same linkset cannot collide with each other
171 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
172 {
173 return ret;
174 }
175
176 // if someone has subscribed for collision events....
177 if (SubscribedEvents()) {
178 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
179 DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}",
180 LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth);
181
182 ret = true;
183 }
184 return ret;
185 }
186
187 // Send the collected collisions into the simulator.
188 // Called at taint time from within the Step() function thus no locking problems
189 // with CollisionCollection and ObjectsWithNoMoreCollisions.
190 // Return 'true' if there were some actual collisions passed up
191 public virtual bool SendCollisions()
192 {
193 bool ret = true;
194 // If the 'no collision' call, force it to happen right now so quick collision_end
195 bool force = CollisionCollection.Count == 0;
196
197 // throttle the collisions to the number of milliseconds specified in the subscription
198 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime))
199 {
200 NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs;
201
202 // We are called if we previously had collisions. If there are no collisions
203 // this time, send up one last empty event so OpenSim can sense collision end.
204 if (CollisionCollection.Count == 0)
205 {
206 // If I have no collisions this time, remove me from the list of objects with collisions.
207 ret = false;
208 }
209
210 // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
211 base.SendCollisionUpdate(CollisionCollection);
212
213 // The collisionCollection structure is passed around in the simulator.
214 // Make sure we don't have a handle to that one and that a new one is used for next time.
215 CollisionCollection = new CollisionEventUpdate();
216 }
217 return ret;
218 }
219
220 // Subscribe for collision events.
221 // Parameter is the millisecond rate the caller wishes collision events to occur.
222 public override void SubscribeEvents(int ms) {
223 // DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms);
224 SubscribedEventsMs = ms;
225 if (ms > 0)
226 {
227 // make sure first collision happens
228 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
229
230 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
231 {
232 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
233 });
234 }
235 else
236 {
237 // Subscribing for zero or less is the same as unsubscribing
238 UnSubscribeEvents();
239 }
240 }
241 public override void UnSubscribeEvents() {
242 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
243 SubscribedEventsMs = 0;
244 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
245 {
246 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
247 });
248 }
249 // Return 'true' if the simulator wants collision events
250 public override bool SubscribedEvents() {
251 return (SubscribedEventsMs > 0);
252 }
253
254 #endregion // Collisions
255
256 // High performance detailed logging routine used by the physical objects.
257 protected void DetailLog(string msg, params Object[] args)
258 {
259 if (PhysicsScene.PhysicsLogging.Enabled)
260 PhysicsScene.DetailLog(msg, args);
261 }
262}
263}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
index 0f027b8..20f5180 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
@@ -33,7 +33,7 @@ using OpenMetaverse;
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35 /// <summary> 35 /// <summary>
36 /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. 36 /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim.
37 /// This module interfaces to an unmanaged C++ library which makes the 37 /// This module interfaces to an unmanaged C++ library which makes the
38 /// actual calls into the Bullet physics engine. 38 /// actual calls into the Bullet physics engine.
39 /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/. 39 /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/.
@@ -62,7 +62,7 @@ public class BSPlugin : IPhysicsPlugin
62 if (Util.IsWindows()) 62 if (Util.IsWindows())
63 Util.LoadArchSpecificWindowsDll("BulletSim.dll"); 63 Util.LoadArchSpecificWindowsDll("BulletSim.dll");
64 // If not Windows, loading is performed by the 64 // If not Windows, loading is performed by the
65 // Mono loader as specified in 65 // Mono loader as specified in
66 // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config". 66 // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config".
67 67
68 _mScene = new BSScene(sceneIdentifier); 68 _mScene = new BSScene(sceneIdentifier);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 9c20004..2b3fa25 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -24,6 +24,7 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27
27using System; 28using System;
28using System.Reflection; 29using System.Reflection;
29using System.Collections.Generic; 30using System.Collections.Generic;
@@ -36,32 +37,17 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet;
36 37
37namespace OpenSim.Region.Physics.BulletSPlugin 38namespace OpenSim.Region.Physics.BulletSPlugin
38{ 39{
40
39 [Serializable] 41 [Serializable]
40public sealed class BSPrim : PhysicsActor 42public sealed class BSPrim : BSPhysObject
41{ 43{
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 private static readonly string LogHeader = "[BULLETS PRIM]"; 45 private static readonly string LogHeader = "[BULLETS PRIM]";
44 46
45 private void DebugLog(string mm, params Object[] xx) { if (_scene.ShouldDebugLog) m_log.DebugFormat(mm, xx); } 47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
46 48 // Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
47 private IMesh _mesh;
48 private PrimitiveBaseShape _pbs;
49 private ShapeData.PhysicsShapeType _shapeType;
50 private ulong _meshKey;
51 private ulong _hullKey;
52 private List<ConvexResult> _hulls;
53
54 private BSScene _scene;
55 public BSScene Scene { get { return _scene; } }
56 private String _avName;
57 private uint _localID = 0;
58
59 // _size is what the user passed. _scale is what we pass to the physics engine with the mesh.
60 // Often _scale is unity because the meshmerizer will apply _size when creating the mesh.
61 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user 49 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
62 private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer
63 50
64 private bool _stopped;
65 private bool _grabbed; 51 private bool _grabbed;
66 private bool _isSelected; 52 private bool _isSelected;
67 private bool _isVolumeDetect; 53 private bool _isVolumeDetect;
@@ -89,25 +75,6 @@ public sealed class BSPrim : PhysicsActor
89 private bool _kinematic; 75 private bool _kinematic;
90 private float _buoyancy; 76 private float _buoyancy;
91 77
92 // Membership in a linkset is controlled by this class.
93 private BSLinkset _linkset;
94 public BSLinkset Linkset
95 {
96 get { return _linkset; }
97 set { _linkset = value; }
98 }
99
100 private int _subscribedEventsMs = 0;
101 private int _nextCollisionOkTime = 0;
102 long _collidingStep;
103 long _collidingGroundStep;
104
105 private BulletBody m_body;
106 public BulletBody Body {
107 get { return m_body; }
108 set { m_body = value; }
109 }
110
111 private BSDynamics _vehicle; 78 private BSDynamics _vehicle;
112 79
113 private OMV.Vector3 _PIDTarget; 80 private OMV.Vector3 _PIDTarget;
@@ -120,110 +87,116 @@ public sealed class BSPrim : PhysicsActor
120 87
121 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, 88 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
122 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 89 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
90 : base(parent_scene, localID, primName, "BSPrim")
123 { 91 {
124 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 92 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
125 _localID = localID; 93 _physicsActorType = (int)ActorTypes.Prim;
126 _avName = primName;
127 _scene = parent_scene;
128 _position = pos; 94 _position = pos;
129 _size = size; 95 _size = size;
130 _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type 96 Scale = size; // the scale will be set by CreateGeom depending on object type
131 _orientation = rotation; 97 _orientation = rotation;
132 _buoyancy = 1f; 98 _buoyancy = 1f;
133 _velocity = OMV.Vector3.Zero; 99 _velocity = OMV.Vector3.Zero;
134 _rotationalVelocity = OMV.Vector3.Zero; 100 _rotationalVelocity = OMV.Vector3.Zero;
135 _hullKey = 0; 101 BaseShape = pbs;
136 _meshKey = 0;
137 _pbs = pbs;
138 _isPhysical = pisPhysical; 102 _isPhysical = pisPhysical;
139 _isVolumeDetect = false; 103 _isVolumeDetect = false;
140 _subscribedEventsMs = 0; 104 _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material
141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 105 _density = PhysicsScene.Params.defaultDensity; // TODO: compute based on object material
142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 106 _restitution = PhysicsScene.Params.defaultRestitution;
143 _restitution = _scene.Params.defaultRestitution; 107 _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness
144 _linkset = new BSLinkset(_scene, this); // a linkset of one
145 _vehicle = new BSDynamics(this); // add vehicleness
146 _mass = CalculateMass(); 108 _mass = CalculateMass();
147 // do the actual object creation at taint time 109
110 // No body or shape yet
111 PhysBody = new BulletBody(LocalID, IntPtr.Zero);
112 PhysShape = new BulletShape(IntPtr.Zero);
113
148 DetailLog("{0},BSPrim.constructor,call", LocalID); 114 DetailLog("{0},BSPrim.constructor,call", LocalID);
149 _scene.TaintedObject("BSPrim.create", delegate() 115 // do the actual object creation at taint time
116 PhysicsScene.TaintedObject("BSPrim.create", delegate()
150 { 117 {
151 RecreateGeomAndObject(); 118 CreateGeomAndObject(true);
152 119
153 // Get the pointer to the physical body for this object. 120 CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(PhysBody.ptr);
154 // At the moment, we're still letting BulletSim manage the creation and destruction
155 // of the object. Someday we'll move that into the C# code.
156 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
157 }); 121 });
158 } 122 }
159 123
160 // called when this prim is being destroyed and we should free all the resources 124 // called when this prim is being destroyed and we should free all the resources
161 public void Destroy() 125 public override void Destroy()
162 { 126 {
163 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 127 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
164 128
165 // Undo any links between me and any other object 129 // Undo any links between me and any other object
166 BSPrim parentBefore = _linkset.LinksetRoot; 130 BSPhysObject parentBefore = Linkset.LinksetRoot;
167 int childrenBefore = _linkset.NumberOfChildren; 131 int childrenBefore = Linkset.NumberOfChildren;
168 132
169 _linkset = _linkset.RemoveMeFromLinkset(this); 133 Linkset = Linkset.RemoveMeFromLinkset(this);
170 134
171 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", 135 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
172 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 136 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
173 137
174 // Undo any vehicle properties 138 // Undo any vehicle properties
175 this.VehicleType = (int)Vehicle.TYPE_NONE; 139 this.VehicleType = (int)Vehicle.TYPE_NONE;
176 140
177 _scene.TaintedObject("BSPrim.destroy", delegate() 141 PhysicsScene.TaintedObject("BSPrim.destroy", delegate()
178 { 142 {
179 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 143 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
180 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 144 // If there are physical body and shape, release my use of same.
181 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); 145 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
146 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
182 }); 147 });
183 } 148 }
184 149
185 public override bool Stopped { 150 // No one uses this property.
186 get { return _stopped; } 151 public override bool Stopped {
152 get { return false; }
187 } 153 }
188 public override OMV.Vector3 Size { 154 public override OMV.Vector3 Size {
189 get { return _size; } 155 get { return _size; }
190 set { 156 set {
157 // We presume the scale and size are the same. If scale must be changed for
158 // the physical shape, that is done when the geometry is built.
191 _size = value; 159 _size = value;
192 _scene.TaintedObject("BSPrim.setSize", delegate() 160 ForceBodyShapeRebuild(false);
193 { 161 }
194 _mass = CalculateMass(); // changing size changes the mass
195 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
196 // DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical);
197 RecreateGeomAndObject();
198 });
199 }
200 } 162 }
201 public override PrimitiveBaseShape Shape { 163 // Scale is what we set in the physics engine. It is different than 'size' in that
164 // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>.
165 public override OMV.Vector3 Scale { get; set; }
166
167 public override PrimitiveBaseShape Shape {
202 set { 168 set {
203 _pbs = value; 169 BaseShape = value;
204 _scene.TaintedObject("BSPrim.setShape", delegate() 170 ForceBodyShapeRebuild(false);
205 { 171 }
206 _mass = CalculateMass(); // changing the shape changes the mass
207 RecreateGeomAndObject();
208 });
209 }
210 } 172 }
211 public override uint LocalID { 173 // Whatever the linkset wants is what I want.
212 set { _localID = value; } 174 public override BSPhysicsShapeType PreferredPhysicalShape
213 get { return _localID; } 175 { get { return Linkset.PreferredPhysicalShape(this); } }
176
177 public override bool ForceBodyShapeRebuild(bool inTaintTime)
178 {
179 LastAssetBuildFailed = false;
180 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
181 {
182 _mass = CalculateMass(); // changing the shape changes the mass
183 CreateGeomAndObject(true);
184 });
185 return true;
214 } 186 }
215 public override bool Grabbed { 187 public override bool Grabbed {
216 set { _grabbed = value; 188 set { _grabbed = value;
217 } 189 }
218 } 190 }
219 public override bool Selected { 191 public override bool Selected {
220 set { 192 set {
221 _isSelected = value; 193 _isSelected = value;
222 _scene.TaintedObject("BSPrim.setSelected", delegate() 194 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate()
223 { 195 {
224 SetObjectDynamic(); 196 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
197 SetObjectDynamic(false);
225 }); 198 });
226 } 199 }
227 } 200 }
228 public override void CrossingFailure() { return; } 201 public override void CrossingFailure() { return; }
229 202
@@ -232,158 +205,260 @@ public sealed class BSPrim : PhysicsActor
232 BSPrim parent = obj as BSPrim; 205 BSPrim parent = obj as BSPrim;
233 if (parent != null) 206 if (parent != null)
234 { 207 {
235 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); 208 BSPhysObject parentBefore = Linkset.LinksetRoot;
236 BSPrim parentBefore = _linkset.LinksetRoot; 209 int childrenBefore = Linkset.NumberOfChildren;
237 int childrenBefore = _linkset.NumberOfChildren;
238 210
239 _linkset = parent.Linkset.AddMeToLinkset(this); 211 Linkset = parent.Linkset.AddMeToLinkset(this);
240 212
241 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", 213 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
242 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 214 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
243 } 215 }
244 return; 216 return;
245 } 217 }
246 218
247 // delink me from my linkset 219 // delink me from my linkset
248 public override void delink() { 220 public override void delink() {
249 // TODO: decide if this parent checking needs to happen at taint time 221 // TODO: decide if this parent checking needs to happen at taint time
250 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 222 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
251 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
252 _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString());
253 223
254 BSPrim parentBefore = _linkset.LinksetRoot; 224 BSPhysObject parentBefore = Linkset.LinksetRoot;
255 int childrenBefore = _linkset.NumberOfChildren; 225 int childrenBefore = Linkset.NumberOfChildren;
256 226
257 _linkset = _linkset.RemoveMeFromLinkset(this); 227 Linkset = Linkset.RemoveMeFromLinkset(this);
258 228
259 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", 229 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
260 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 230 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
261 return; 231 return;
262 } 232 }
263 233
264 // Set motion values to zero. 234 // Set motion values to zero.
265 // Do it to the properties so the values get set in the physics engine. 235 // Do it to the properties so the values get set in the physics engine.
266 // Push the setting of the values to the viewer. 236 // Push the setting of the values to the viewer.
267 // Called at taint time! 237 // Called at taint time!
268 public void ZeroMotion() 238 public override void ZeroMotion(bool inTaintTime)
269 { 239 {
270 _velocity = OMV.Vector3.Zero; 240 _velocity = OMV.Vector3.Zero;
271 _acceleration = OMV.Vector3.Zero; 241 _acceleration = OMV.Vector3.Zero;
272 _rotationalVelocity = OMV.Vector3.Zero; 242 _rotationalVelocity = OMV.Vector3.Zero;
273 243
274 // Zero some other properties directly into the physics engine 244 // Zero some other properties in the physics engine
275 BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero); 245 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
276 BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero); 246 {
277 BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); 247 BulletSimAPI.ClearAllForces2(PhysBody.ptr);
278 BulletSimAPI.ClearForces2(Body.Ptr); 248 });
249 }
250 public override void ZeroAngularMotion(bool inTaintTime)
251 {
252 _rotationalVelocity = OMV.Vector3.Zero;
253 // Zero some other properties in the physics engine
254 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
255 {
256 BulletSimAPI.SetInterpolationAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
257 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
258 });
279 } 259 }
280 260
281 public override void LockAngularMotion(OMV.Vector3 axis) 261 public override void LockAngularMotion(OMV.Vector3 axis)
282 { 262 {
283 // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); 263 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
284 return; 264 return;
285 } 265 }
286 266
287 public override OMV.Vector3 Position { 267 public override OMV.Vector3 RawPosition
288 get { 268 {
289 if (!_linkset.IsRoot(this)) 269 get { return _position; }
290 // child prims move around based on their parent. Need to get the latest location 270 set { _position = value; }
291 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 271 }
272 public override OMV.Vector3 Position {
273 get {
274 // child prims move around based on their parent. Need to get the latest location
275 if (!Linkset.IsRoot(this))
276 _position = Linkset.Position(this);
292 277
293 // don't do the GetObjectPosition for root elements because this function is called a zillion times 278 // don't do the GetObjectPosition for root elements because this function is called a zillion times.
294 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 279 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
295 return _position; 280 return _position;
296 } 281 }
297 set { 282 set {
283 // If the position must be forced into the physics engine, use ForcePosition.
284 if (_position == value)
285 {
286 return;
287 }
298 _position = value; 288 _position = value;
299 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 289 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
300 _scene.TaintedObject("BSPrim.setPosition", delegate() 290 PositionSanityCheck(false);
291 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
301 { 292 {
302 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 293 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
303 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 294 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
295 ActivateIfPhysical(false);
304 }); 296 });
305 } 297 }
298 }
299 public override OMV.Vector3 ForcePosition {
300 get {
301 _position = BulletSimAPI.GetPosition2(PhysBody.ptr);
302 return _position;
303 }
304 set {
305 _position = value;
306 // PositionSanityCheck(); // Don't do this! Causes a loop and caller should know better.
307 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
308 ActivateIfPhysical(false);
309 }
310 }
311
312 // Check that the current position is sane and, if not, modify the position to make it so.
313 // Check for being below terrain and being out of bounds.
314 // Returns 'true' of the position was made sane by some action.
315 private bool PositionSanityCheck(bool inTaintTime)
316 {
317 bool ret = false;
318
319 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
320 OMV.Vector3 upForce = OMV.Vector3.Zero;
321 if (Position.Z < terrainHeight)
322 {
323 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
324 float targetHeight = terrainHeight + (Size.Z / 2f);
325 // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec.
326 upForce.Z = (terrainHeight - Position.Z) * 1f;
327 ret = true;
328 }
329
330 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
331 {
332 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
333 // TODO: a floating motor so object will bob in the water
334 if (Math.Abs(Position.Z - waterHeight) > 0.1f)
335 {
336 // Upforce proportional to the distance away from the water. Correct the error in 1 sec.
337 upForce.Z = (waterHeight - Position.Z) * 1f;
338 ret = true;
339 }
340 }
341
342 // TODO: check for out of bounds
343
344 // The above code computes a force to apply to correct any out-of-bounds problems. Apply same.
345 if (ret)
346 {
347 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck:belowTerrain", delegate()
348 {
349 // Apply upforce and overcome gravity.
350 ForceVelocity = ForceVelocity + upForce - PhysicsScene.DefaultGravity;
351 });
352 }
353 return ret;
306 } 354 }
307 355
308 // Return the effective mass of the object. 356 // Return the effective mass of the object.
309 // If there are multiple items in the linkset, add them together for the root 357 // If there are multiple items in the linkset, add them together for the root
310 public override float Mass 358 public override float Mass
311 { 359 {
312 get 360 get
313 { 361 {
314 return _linkset.LinksetMass; 362 return Linkset.LinksetMass;
363 // return _mass;
315 } 364 }
316 } 365 }
317 366
318 // used when we only want this prim's mass and not the linkset thing 367 // used when we only want this prim's mass and not the linkset thing
319 public float MassRaw { get { return _mass; } } 368 public override float RawMass {
369 get { return _mass; }
370 }
371 // Set the physical mass to the passed mass.
372 // Note that this does not change _mass!
373 public override void UpdatePhysicalMassProperties(float physMass)
374 {
375 if (IsStatic)
376 {
377 Inertia = OMV.Vector3.Zero;
378 BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, Inertia);
379 BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
380 }
381 else
382 {
383 Inertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
384 BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, Inertia);
385 BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
386 // center of mass is at the zero of the object
387 // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation);
388 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, Inertia);
389 }
390 }
320 391
321 // Is this used? 392 // Is this used?
322 public override OMV.Vector3 CenterOfMass 393 public override OMV.Vector3 CenterOfMass
323 { 394 {
324 get { return _linkset.CenterOfMass; } 395 get { return Linkset.CenterOfMass; }
325 } 396 }
326 397
327 // Is this used? 398 // Is this used?
328 public override OMV.Vector3 GeometricCenter 399 public override OMV.Vector3 GeometricCenter
329 { 400 {
330 get { return _linkset.GeometricCenter; } 401 get { return Linkset.GeometricCenter; }
331 } 402 }
332 403
333 public override OMV.Vector3 Force { 404 public override OMV.Vector3 Force {
334 get { return _force; } 405 get { return _force; }
335 set { 406 set {
336 _force = value; 407 _force = value;
337 _scene.TaintedObject("BSPrim.setForce", delegate() 408 PhysicsScene.TaintedObject("BSPrim.setForce", delegate()
338 { 409 {
339 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 410 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
340 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 411 BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force);
341 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
342 }); 412 });
343 } 413 }
344 } 414 }
345 415
346 public override int VehicleType { 416 public override int VehicleType {
347 get { 417 get {
348 return (int)_vehicle.Type; // if we are a vehicle, return that type 418 return (int)_vehicle.Type; // if we are a vehicle, return that type
349 } 419 }
350 set { 420 set {
351 Vehicle type = (Vehicle)value; 421 Vehicle type = (Vehicle)value;
352 BSPrim vehiclePrim = this; 422
353 _scene.TaintedObject("setVehicleType", delegate() 423 // Tell the scene about the vehicle so it will get processing each frame.
424 PhysicsScene.VehicleInSceneTypeChanged(this, type);
425
426 PhysicsScene.TaintedObject("setVehicleType", delegate()
354 { 427 {
355 // Done at taint time so we're sure the physics engine is not using the variables 428 // Done at taint time so we're sure the physics engine is not using the variables
356 // Vehicle code changes the parameters for this vehicle type. 429 // Vehicle code changes the parameters for this vehicle type.
357 _vehicle.ProcessTypeChange(type); 430 _vehicle.ProcessTypeChange(type);
358 // Tell the scene about the vehicle so it will get processing each frame. 431 ActivateIfPhysical(false);
359 _scene.VehicleInSceneTypeChanged(this, type);
360 }); 432 });
361 } 433 }
362 } 434 }
363 public override void VehicleFloatParam(int param, float value) 435 public override void VehicleFloatParam(int param, float value)
364 { 436 {
365 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 437 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
366 { 438 {
367 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 439 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
440 ActivateIfPhysical(false);
368 }); 441 });
369 } 442 }
370 public override void VehicleVectorParam(int param, OMV.Vector3 value) 443 public override void VehicleVectorParam(int param, OMV.Vector3 value)
371 { 444 {
372 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 445 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
373 { 446 {
374 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 447 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
448 ActivateIfPhysical(false);
375 }); 449 });
376 } 450 }
377 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 451 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
378 { 452 {
379 _scene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 453 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
380 { 454 {
381 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 455 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
456 ActivateIfPhysical(false);
382 }); 457 });
383 } 458 }
384 public override void VehicleFlags(int param, bool remove) 459 public override void VehicleFlags(int param, bool remove)
385 { 460 {
386 _scene.TaintedObject("BSPrim.VehicleFlags", delegate() 461 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate()
387 { 462 {
388 _vehicle.ProcessVehicleFlags(param, remove); 463 _vehicle.ProcessVehicleFlags(param, remove);
389 }); 464 });
@@ -391,143 +466,356 @@ public sealed class BSPrim : PhysicsActor
391 466
392 // Called each simulation step to advance vehicle characteristics. 467 // Called each simulation step to advance vehicle characteristics.
393 // Called from Scene when doing simulation step so we're in taint processing time. 468 // Called from Scene when doing simulation step so we're in taint processing time.
394 public void StepVehicle(float timeStep) 469 public override void StepVehicle(float timeStep)
395 { 470 {
396 if (IsPhysical) 471 if (IsPhysical && _vehicle.IsActive)
472 {
397 _vehicle.Step(timeStep); 473 _vehicle.Step(timeStep);
474 /* // TEST TEST DEBUG DEBUG -- trying to reduce the extra action of Bullet simulation step
475 PhysicsScene.PostTaintObject("BSPrim.StepVehicles", LocalID, delegate()
476 {
477 // This resets the interpolation values and recomputes the tensor variables
478 BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation);
479 });
480 */
481 }
398 } 482 }
399 483
400 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 484 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
401 public override void SetVolumeDetect(int param) { 485 public override void SetVolumeDetect(int param) {
402 bool newValue = (param != 0); 486 bool newValue = (param != 0);
403 _isVolumeDetect = newValue; 487 if (_isVolumeDetect != newValue)
404 _scene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
405 { 488 {
406 SetObjectDynamic(); 489 _isVolumeDetect = newValue;
407 }); 490 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
408 return; 491 {
492 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
493 SetObjectDynamic(true);
494 });
495 }
496 return;
409 } 497 }
410 498 public override OMV.Vector3 Velocity {
411 public override OMV.Vector3 Velocity { 499 get { return _velocity; }
412 get { return _velocity; }
413 set { 500 set {
414 _velocity = value; 501 _velocity = value;
415 _scene.TaintedObject("BSPrim.setVelocity", delegate() 502 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
416 { 503 {
417 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 504 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
418 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 505 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
419 }); 506 });
420 } 507 }
508 }
509 public override OMV.Vector3 ForceVelocity {
510 get { return _velocity; }
511 set {
512 _velocity = value;
513 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
514 }
421 } 515 }
422 public override OMV.Vector3 Torque { 516 public override OMV.Vector3 Torque {
423 get { return _torque; } 517 get { return _torque; }
424 set { _torque = value; 518 set {
519 _torque = value;
520 AddAngularForce(_torque, false, false);
425 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 521 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
426 } 522 }
427 } 523 }
428 public override float CollisionScore { 524 public override float CollisionScore {
429 get { return _collisionScore; } 525 get { return _collisionScore; }
430 set { _collisionScore = value; 526 set { _collisionScore = value;
431 } 527 }
432 } 528 }
433 public override OMV.Vector3 Acceleration { 529 public override OMV.Vector3 Acceleration {
434 get { return _acceleration; } 530 get { return _acceleration; }
435 set { _acceleration = value; } 531 set { _acceleration = value; }
436 } 532 }
437 public override OMV.Quaternion Orientation { 533 public override OMV.Quaternion RawOrientation
534 {
535 get { return _orientation; }
536 set { _orientation = value; }
537 }
538 public override OMV.Quaternion Orientation {
438 get { 539 get {
439 if (!_linkset.IsRoot(this)) 540 // Children move around because tied to parent. Get a fresh value.
541 if (!Linkset.IsRoot(this))
440 { 542 {
441 // Children move around because tied to parent. Get a fresh value. 543 _orientation = Linkset.Orientation(this);
442 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
443 } 544 }
444 return _orientation; 545 return _orientation;
445 } 546 }
446 set { 547 set {
548 if (_orientation == value)
549 return;
447 _orientation = value; 550 _orientation = value;
448 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? 551 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
449 _scene.TaintedObject("BSPrim.setOrientation", delegate() 552 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
450 { 553 {
451 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 554 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
452 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 555 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
453 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 556 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
454 }); 557 });
455 } 558 }
559 }
560 // Go directly to Bullet to get/set the value.
561 public override OMV.Quaternion ForceOrientation
562 {
563 get
564 {
565 _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr);
566 return _orientation;
567 }
568 set
569 {
570 _orientation = value;
571 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
572 }
456 } 573 }
457 public override int PhysicsActorType { 574 public override int PhysicsActorType {
458 get { return _physicsActorType; } 575 get { return _physicsActorType; }
459 set { _physicsActorType = value; 576 set { _physicsActorType = value; }
460 }
461 } 577 }
462 public override bool IsPhysical { 578 public override bool IsPhysical {
463 get { return _isPhysical; } 579 get { return _isPhysical; }
464 set { 580 set {
465 _isPhysical = value; 581 if (_isPhysical != value)
466 _scene.TaintedObject("BSPrim.setIsPhysical", delegate()
467 { 582 {
468 SetObjectDynamic(); 583 _isPhysical = value;
469 }); 584 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate()
470 } 585 {
586 // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
587 SetObjectDynamic(true);
588 // whether phys-to-static or static-to-phys, the object is not moving.
589 ZeroMotion(true);
590 });
591 }
592 }
471 } 593 }
472 594
473 // An object is static (does not move) if selected or not physical 595 // An object is static (does not move) if selected or not physical
474 private bool IsStatic 596 public override bool IsStatic
475 { 597 {
476 get { return _isSelected || !IsPhysical; } 598 get { return _isSelected || !IsPhysical; }
477 } 599 }
478 600
479 // An object is solid if it's not phantom and if it's not doing VolumeDetect 601 // An object is solid if it's not phantom and if it's not doing VolumeDetect
480 private bool IsSolid 602 public override bool IsSolid
481 { 603 {
482 get { return !IsPhantom && !_isVolumeDetect; } 604 get { return !IsPhantom && !_isVolumeDetect; }
483 } 605 }
484 606
485 // Make gravity work if the object is physical and not selected 607 // Make gravity work if the object is physical and not selected
486 // No locking here because only called when it is safe 608 // Called at taint-time!!
487 private void SetObjectDynamic() 609 private void SetObjectDynamic(bool forceRebuild)
610 {
611 // Recreate the physical object if necessary
612 CreateGeomAndObject(forceRebuild);
613 }
614
615 // Convert the simulator's physical properties into settings on BulletSim objects.
616 // There are four flags we're interested in:
617 // IsStatic: Object does not move, otherwise the object has mass and moves
618 // isSolid: other objects bounce off of this object
619 // isVolumeDetect: other objects pass through but can generate collisions
620 // collisionEvents: whether this object returns collision events
621 private void UpdatePhysicalParameters()
488 { 622 {
489 // RA: remove this for the moment. 623 // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape);
490 // The problem is that dynamic objects are hulls so if we are becoming physical 624
491 // the shape has to be checked and possibly built. 625 // Mangling all the physical properties requires the object not be in the physical world.
492 // Maybe a VerifyCorrectPhysicalShape() routine? 626 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
493 // RecreateGeomAndObject(); 627 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
628
629 // Set up the object physicalness (does gravity and collisions move this object)
630 MakeDynamic(IsStatic);
631
632 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
633 _vehicle.Refresh();
494 634
495 // Bullet wants static objects to have a mass of zero 635 // Arrange for collision events if the simulator wants them
496 float mass = IsStatic ? 0f : _mass; 636 EnableCollisions(SubscribedEvents());
497 637
498 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); 638 // Make solid or not (do things bounce off or pass through this object).
639 MakeSolid(IsSolid);
499 640
500 // recompute any linkset parameters 641 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
501 _linkset.Refresh(this);
502 642
503 CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); 643 // Rebuild its shape
504 // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); 644 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
645
646 // Collision filter can be set only when the object is in the world
647 if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0)
648 {
649 BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask);
650 }
651
652 // Recompute any linkset parameters.
653 // When going from non-physical to physical, this re-enables the constraints that
654 // had been automatically disabled when the mass was set to zero.
655 // For compound based linksets, this enables and disables interactions of the children.
656 Linkset.Refresh(this);
657
658 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
659 LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape);
660 }
661
662 // "Making dynamic" means changing to and from static.
663 // When static, gravity does not effect the object and it is fixed in space.
664 // When dynamic, the object can fall and be pushed by others.
665 // This is independent of its 'solidness' which controls what passes through
666 // this object and what interacts with it.
667 private void MakeDynamic(bool makeStatic)
668 {
669 if (makeStatic)
670 {
671 // Become a Bullet 'static' object type
672 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
673 // Stop all movement
674 ZeroMotion(true);
675 // Center of mass is at the center of the object
676 // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
677 // Mass is zero which disables a bunch of physics stuff in Bullet
678 UpdatePhysicalMassProperties(0f);
679 // Set collision detection parameters
680 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
681 {
682 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
683 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
684 }
685 // There can be special things needed for implementing linksets
686 Linkset.MakeStatic(this);
687 // The activation state is 'disabled' so Bullet will not try to act on it.
688 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
689 // Start it out sleeping and physical actions could wake it up.
690 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
691
692 PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
693 PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
694 }
695 else
696 {
697 // Not a Bullet static object
698 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
699
700 // Set various physical properties so internal dynamic properties will get computed correctly as they are set
701 BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction);
702 BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution);
703
704 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
705 // Since this can be called multiple times, only zero forces when becoming physical
706 // BulletSimAPI.ClearAllForces2(BSBody.ptr);
707
708 // For good measure, make sure the transform is set through to the motion state
709 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
710
711 // Center of mass is at the center of the object
712 // DEBUG DEBUG BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
713
714 // A dynamic object has mass
715 UpdatePhysicalMassProperties(RawMass);
716
717 // Set collision detection parameters
718 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
719 {
720 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
721 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
722 }
723
724 // Various values for simulation limits
725 BulletSimAPI.SetDamping2(PhysBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping);
726 BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, PhysicsScene.Params.deactivationTime);
727 BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
728 BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
729
730 // There might be special things needed for implementing linksets.
731 Linkset.MakeDynamic(this);
732
733 // Force activation of the object so Bullet will act on it.
734 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
735 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG);
736 // BulletSimAPI.Activate2(BSBody.ptr, true);
737
738 PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
739 PhysBody.collisionMask = CollisionFilterGroups.ObjectMask;
740 }
741 }
742
743 // "Making solid" means that other object will not pass through this object.
744 // To make transparent, we create a Bullet ghost object.
745 // Note: This expects to be called from the UpdatePhysicalParameters() routine as
746 // the functions after this one set up the state of a possibly newly created collision body.
747 private void MakeSolid(bool makeSolid)
748 {
749 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(PhysBody.ptr);
750 if (makeSolid)
751 {
752 // Verify the previous code created the correct shape for this type of thing.
753 if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0)
754 {
755 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
756 }
757 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
758 }
759 else
760 {
761 if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0)
762 {
763 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
764 }
765 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
766 PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter;
767 PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
768 }
769 }
770
771 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
772 // they need waking up when parameters are changed.
773 // Called in taint-time!!
774 private void ActivateIfPhysical(bool forceIt)
775 {
776 if (IsPhysical)
777 BulletSimAPI.Activate2(PhysBody.ptr, forceIt);
778 }
779
780 // Turn on or off the flag controlling whether collision events are returned to the simulator.
781 private void EnableCollisions(bool wantsCollisionEvents)
782 {
783 if (wantsCollisionEvents)
784 {
785 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
786 }
787 else
788 {
789 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
790 }
505 } 791 }
506 792
507 // prims don't fly 793 // prims don't fly
508 public override bool Flying { 794 public override bool Flying {
509 get { return _flying; } 795 get { return _flying; }
510 set { _flying = value; } 796 set {
797 _flying = value;
798 }
511 } 799 }
512 public override bool SetAlwaysRun { 800 public override bool SetAlwaysRun {
513 get { return _setAlwaysRun; } 801 get { return _setAlwaysRun; }
514 set { _setAlwaysRun = value; } 802 set { _setAlwaysRun = value; }
515 } 803 }
516 public override bool ThrottleUpdates { 804 public override bool ThrottleUpdates {
517 get { return _throttleUpdates; } 805 get { return _throttleUpdates; }
518 set { _throttleUpdates = value; } 806 set { _throttleUpdates = value; }
519 } 807 }
520 public override bool IsColliding { 808 public override bool IsColliding {
521 get { return (_collidingStep == _scene.SimulationStep); } 809 get { return (CollidingStep == PhysicsScene.SimulationStep); }
522 set { _isColliding = value; } 810 set { _isColliding = value; }
523 } 811 }
524 public override bool CollidingGround { 812 public override bool CollidingGround {
525 get { return (_collidingGroundStep == _scene.SimulationStep); } 813 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
526 set { _collidingGround = value; } 814 set { _collidingGround = value; }
527 } 815 }
528 public override bool CollidingObj { 816 public override bool CollidingObj {
529 get { return _collidingObj; } 817 get { return _collidingObj; }
530 set { _collidingObj = value; } 818 set { _collidingObj = value; }
531 } 819 }
532 public bool IsPhantom { 820 public bool IsPhantom {
533 get { 821 get {
@@ -537,10 +825,19 @@ public sealed class BSPrim : PhysicsActor
537 return false; 825 return false;
538 } 826 }
539 } 827 }
540 public override bool FloatOnWater { 828 public override bool FloatOnWater {
541 set { _floatOnWater = value; } 829 set {
830 _floatOnWater = value;
831 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
832 {
833 if (_floatOnWater)
834 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
835 else
836 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
837 });
838 }
542 } 839 }
543 public override OMV.Vector3 RotationalVelocity { 840 public override OMV.Vector3 RotationalVelocity {
544 get { 841 get {
545 /* 842 /*
546 OMV.Vector3 pv = OMV.Vector3.Zero; 843 OMV.Vector3 pv = OMV.Vector3.Zero;
@@ -552,58 +849,76 @@ public sealed class BSPrim : PhysicsActor
552 */ 849 */
553 850
554 return _rotationalVelocity; 851 return _rotationalVelocity;
555 } 852 }
556 set { 853 set {
557 _rotationalVelocity = value; 854 _rotationalVelocity = value;
558 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 855 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
559 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 856 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
560 { 857 {
561 // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 858 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
562 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 859 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
563 }); 860 });
564 } 861 }
565 } 862 }
566 public override bool Kinematic { 863 public override OMV.Vector3 ForceRotationalVelocity {
567 get { return _kinematic; } 864 get {
568 set { _kinematic = value; 865 return _rotationalVelocity;
866 }
867 set {
868 _rotationalVelocity = value;
869 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
870 }
871 }
872 public override bool Kinematic {
873 get { return _kinematic; }
874 set { _kinematic = value;
569 // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic); 875 // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic);
570 } 876 }
571 } 877 }
572 public override float Buoyancy { 878 public override float Buoyancy {
573 get { return _buoyancy; } 879 get { return _buoyancy; }
574 set { 880 set {
575 _buoyancy = value; 881 _buoyancy = value;
576 _scene.TaintedObject("BSPrim.setBuoyancy", delegate() 882 PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate()
577 { 883 {
578 // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 884 ForceBuoyancy = _buoyancy;
579 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
580 }); 885 });
581 } 886 }
887 }
888 public override float ForceBuoyancy {
889 get { return _buoyancy; }
890 set {
891 _buoyancy = value;
892 // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
893 // Buoyancy is faked by changing the gravity applied to the object
894 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
895 BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
896 }
582 } 897 }
583 898
584 // Used for MoveTo 899 // Used for MoveTo
585 public override OMV.Vector3 PIDTarget { 900 public override OMV.Vector3 PIDTarget {
586 set { _PIDTarget = value; } 901 set { _PIDTarget = value; }
587 } 902 }
588 public override bool PIDActive { 903 public override bool PIDActive {
589 set { _usePID = value; } 904 set { _usePID = value; }
590 } 905 }
591 public override float PIDTau { 906 public override float PIDTau {
592 set { _PIDTau = value; } 907 set { _PIDTau = value; }
593 } 908 }
594 909
595 // Used for llSetHoverHeight and maybe vehicle height 910 // Used for llSetHoverHeight and maybe vehicle height
596 // Hover Height will override MoveTo target's Z 911 // Hover Height will override MoveTo target's Z
597 public override bool PIDHoverActive { 912 public override bool PIDHoverActive {
598 set { _useHoverPID = value; } 913 set { _useHoverPID = value; }
599 } 914 }
600 public override float PIDHoverHeight { 915 public override float PIDHoverHeight {
601 set { _PIDHoverHeight = value; } 916 set { _PIDHoverHeight = value; }
602 } 917 }
603 public override PIDHoverType PIDHoverType { 918 public override PIDHoverType PIDHoverType {
604 set { _PIDHoverType = value; } 919 set { _PIDHoverType = value; }
605 } 920 }
606 public override float PIDHoverTau { 921 public override float PIDHoverTau {
607 set { _PIDHoverTao = value; } 922 set { _PIDHoverTao = value; }
608 } 923 }
609 924
@@ -615,6 +930,10 @@ public sealed class BSPrim : PhysicsActor
615 930
616 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); 931 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
617 public override void AddForce(OMV.Vector3 force, bool pushforce) { 932 public override void AddForce(OMV.Vector3 force, bool pushforce) {
933 AddForce(force, pushforce, false);
934 }
935 // Applying a force just adds this to the total force on the object.
936 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
618 // for an object, doesn't matter if force is a pushforce or not 937 // for an object, doesn't matter if force is a pushforce or not
619 if (force.IsFinite()) 938 if (force.IsFinite())
620 { 939 {
@@ -624,56 +943,88 @@ public sealed class BSPrim : PhysicsActor
624 } 943 }
625 else 944 else
626 { 945 {
627 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 946 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
628 return; 947 return;
629 } 948 }
630 _scene.TaintedObject("BSPrim.AddForce", delegate() 949 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
631 { 950 {
632 OMV.Vector3 fSum = OMV.Vector3.Zero; 951 OMV.Vector3 fSum = OMV.Vector3.Zero;
633 lock (m_accumulatedForces) 952 lock (m_accumulatedForces)
634 { 953 {
954 // Sum the accumulated additional forces for one big force to apply once.
635 foreach (OMV.Vector3 v in m_accumulatedForces) 955 foreach (OMV.Vector3 v in m_accumulatedForces)
636 { 956 {
637 fSum += v; 957 fSum += v;
638 } 958 }
639 m_accumulatedForces.Clear(); 959 m_accumulatedForces.Clear();
640 } 960 }
641 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); 961 DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum);
642 BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); 962 if (fSum != OMV.Vector3.Zero)
963 BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum);
643 }); 964 });
644 } 965 }
645 966
646 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 967 // An impulse force is scaled by the mass of the object.
647 // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); 968 public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime)
648 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 969 {
970 OMV.Vector3 applyImpulse = impulse;
971 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyForceImpulse", delegate()
972 {
973 DetailLog("{0},BSPrim.ApplyForceImpulse,taint,tImpulse={1}", LocalID, applyImpulse);
974 BulletSimAPI.ApplyCentralImpulse2(PhysBody.ptr, applyImpulse);
975 });
649 } 976 }
650 public override void SetMomentum(OMV.Vector3 momentum) { 977
651 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); 978 private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>();
979 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
980 AddAngularForce(force, pushforce, false);
652 } 981 }
653 public override void SubscribeEvents(int ms) { 982 public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
654 _subscribedEventsMs = ms; 983 {
655 if (ms > 0) 984 if (force.IsFinite())
656 { 985 {
657 // make sure first collision happens 986 // _force += force;
658 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; 987 lock (m_accumulatedAngularForces)
659 988 m_accumulatedAngularForces.Add(new OMV.Vector3(force));
660 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
661 {
662 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
663 });
664 } 989 }
665 } 990 else
666 public override void UnSubscribeEvents() { 991 {
667 _subscribedEventsMs = 0; 992 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
668 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate() 993 return;
994 }
995 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
669 { 996 {
670 BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 997 OMV.Vector3 fSum = OMV.Vector3.Zero;
998 lock (m_accumulatedAngularForces)
999 {
1000 // Sum the accumulated additional forces for one big force to apply once.
1001 foreach (OMV.Vector3 v in m_accumulatedAngularForces)
1002 {
1003 fSum += v;
1004 }
1005 m_accumulatedAngularForces.Clear();
1006 }
1007 DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum);
1008 if (fSum != OMV.Vector3.Zero)
1009 {
1010 BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum);
1011 _torque = fSum;
1012 }
671 }); 1013 });
672 } 1014 }
673 public override bool SubscribedEvents() { 1015 // A torque impulse.
674 return (_subscribedEventsMs > 0); 1016 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1017 {
1018 OMV.Vector3 applyImpulse = impulse;
1019 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
1020 {
1021 BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse);
1022 });
675 } 1023 }
676 1024
1025 public override void SetMomentum(OMV.Vector3 momentum) {
1026 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
1027 }
677 #region Mass Calculation 1028 #region Mass Calculation
678 1029
679 private float CalculateMass() 1030 private float CalculateMass()
@@ -682,19 +1033,19 @@ public sealed class BSPrim : PhysicsActor
682 float tmp; 1033 float tmp;
683 1034
684 float returnMass = 0; 1035 float returnMass = 0;
685 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; 1036 float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f;
686 float hollowVolume = hollowAmount * hollowAmount; 1037 float hollowVolume = hollowAmount * hollowAmount;
687 1038
688 switch (_pbs.ProfileShape) 1039 switch (BaseShape.ProfileShape)
689 { 1040 {
690 case ProfileShape.Square: 1041 case ProfileShape.Square:
691 // default box 1042 // default box
692 1043
693 if (_pbs.PathCurve == (byte)Extrusion.Straight) 1044 if (BaseShape.PathCurve == (byte)Extrusion.Straight)
694 { 1045 {
695 if (hollowAmount > 0.0) 1046 if (hollowAmount > 0.0)
696 { 1047 {
697 switch (_pbs.HollowShape) 1048 switch (BaseShape.HollowShape)
698 { 1049 {
699 case HollowShape.Square: 1050 case HollowShape.Square:
700 case HollowShape.Same: 1051 case HollowShape.Same:
@@ -718,19 +1069,19 @@ public sealed class BSPrim : PhysicsActor
718 } 1069 }
719 } 1070 }
720 1071
721 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1072 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
722 { 1073 {
723 //a tube 1074 //a tube
724 1075
725 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); 1076 volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX);
726 tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); 1077 tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY);
727 volume -= volume*tmp*tmp; 1078 volume -= volume*tmp*tmp;
728 1079
729 if (hollowAmount > 0.0) 1080 if (hollowAmount > 0.0)
730 { 1081 {
731 hollowVolume *= hollowAmount; 1082 hollowVolume *= hollowAmount;
732 1083
733 switch (_pbs.HollowShape) 1084 switch (BaseShape.HollowShape)
734 { 1085 {
735 case HollowShape.Square: 1086 case HollowShape.Square:
736 case HollowShape.Same: 1087 case HollowShape.Same:
@@ -755,13 +1106,13 @@ public sealed class BSPrim : PhysicsActor
755 1106
756 case ProfileShape.Circle: 1107 case ProfileShape.Circle:
757 1108
758 if (_pbs.PathCurve == (byte)Extrusion.Straight) 1109 if (BaseShape.PathCurve == (byte)Extrusion.Straight)
759 { 1110 {
760 volume *= 0.78539816339f; // elipse base 1111 volume *= 0.78539816339f; // elipse base
761 1112
762 if (hollowAmount > 0.0) 1113 if (hollowAmount > 0.0)
763 { 1114 {
764 switch (_pbs.HollowShape) 1115 switch (BaseShape.HollowShape)
765 { 1116 {
766 case HollowShape.Same: 1117 case HollowShape.Same:
767 case HollowShape.Circle: 1118 case HollowShape.Circle:
@@ -783,19 +1134,19 @@ public sealed class BSPrim : PhysicsActor
783 } 1134 }
784 } 1135 }
785 1136
786 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1137 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
787 { 1138 {
788 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); 1139 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX);
789 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); 1140 tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY);
790 volume *= (1.0f - tmp * tmp); 1141 volume *= (1.0f - tmp * tmp);
791 1142
792 if (hollowAmount > 0.0) 1143 if (hollowAmount > 0.0)
793 { 1144 {
794 1145
795 // calculate the hollow volume by it's shape compared to the prim shape 1146 // calculate the hollow volume by it's shape compared to the prim shape
796 hollowVolume *= hollowAmount; 1147 hollowVolume *= hollowAmount;
797 1148
798 switch (_pbs.HollowShape) 1149 switch (BaseShape.HollowShape)
799 { 1150 {
800 case HollowShape.Same: 1151 case HollowShape.Same:
801 case HollowShape.Circle: 1152 case HollowShape.Circle:
@@ -819,7 +1170,7 @@ public sealed class BSPrim : PhysicsActor
819 break; 1170 break;
820 1171
821 case ProfileShape.HalfCircle: 1172 case ProfileShape.HalfCircle:
822 if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1173 if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
823 { 1174 {
824 volume *= 0.52359877559829887307710723054658f; 1175 volume *= 0.52359877559829887307710723054658f;
825 } 1176 }
@@ -827,7 +1178,7 @@ public sealed class BSPrim : PhysicsActor
827 1178
828 case ProfileShape.EquilateralTriangle: 1179 case ProfileShape.EquilateralTriangle:
829 1180
830 if (_pbs.PathCurve == (byte)Extrusion.Straight) 1181 if (BaseShape.PathCurve == (byte)Extrusion.Straight)
831 { 1182 {
832 volume *= 0.32475953f; 1183 volume *= 0.32475953f;
833 1184
@@ -835,7 +1186,7 @@ public sealed class BSPrim : PhysicsActor
835 { 1186 {
836 1187
837 // calculate the hollow volume by it's shape compared to the prim shape 1188 // calculate the hollow volume by it's shape compared to the prim shape
838 switch (_pbs.HollowShape) 1189 switch (BaseShape.HollowShape)
839 { 1190 {
840 case HollowShape.Same: 1191 case HollowShape.Same:
841 case HollowShape.Triangle: 1192 case HollowShape.Triangle:
@@ -860,11 +1211,11 @@ public sealed class BSPrim : PhysicsActor
860 volume *= (1.0f - hollowVolume); 1211 volume *= (1.0f - hollowVolume);
861 } 1212 }
862 } 1213 }
863 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1214 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
864 { 1215 {
865 volume *= 0.32475953f; 1216 volume *= 0.32475953f;
866 volume *= 0.01f * (float)(200 - _pbs.PathScaleX); 1217 volume *= 0.01f * (float)(200 - BaseShape.PathScaleX);
867 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); 1218 tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY);
868 volume *= (1.0f - tmp * tmp); 1219 volume *= (1.0f - tmp * tmp);
869 1220
870 if (hollowAmount > 0.0) 1221 if (hollowAmount > 0.0)
@@ -872,7 +1223,7 @@ public sealed class BSPrim : PhysicsActor
872 1223
873 hollowVolume *= hollowAmount; 1224 hollowVolume *= hollowAmount;
874 1225
875 switch (_pbs.HollowShape) 1226 switch (BaseShape.HollowShape)
876 { 1227 {
877 case HollowShape.Same: 1228 case HollowShape.Same:
878 case HollowShape.Triangle: 1229 case HollowShape.Triangle:
@@ -912,26 +1263,26 @@ public sealed class BSPrim : PhysicsActor
912 float profileBegin; 1263 float profileBegin;
913 float profileEnd; 1264 float profileEnd;
914 1265
915 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) 1266 if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible)
916 { 1267 {
917 taperX1 = _pbs.PathScaleX * 0.01f; 1268 taperX1 = BaseShape.PathScaleX * 0.01f;
918 if (taperX1 > 1.0f) 1269 if (taperX1 > 1.0f)
919 taperX1 = 2.0f - taperX1; 1270 taperX1 = 2.0f - taperX1;
920 taperX = 1.0f - taperX1; 1271 taperX = 1.0f - taperX1;
921 1272
922 taperY1 = _pbs.PathScaleY * 0.01f; 1273 taperY1 = BaseShape.PathScaleY * 0.01f;
923 if (taperY1 > 1.0f) 1274 if (taperY1 > 1.0f)
924 taperY1 = 2.0f - taperY1; 1275 taperY1 = 2.0f - taperY1;
925 taperY = 1.0f - taperY1; 1276 taperY = 1.0f - taperY1;
926 } 1277 }
927 else 1278 else
928 { 1279 {
929 taperX = _pbs.PathTaperX * 0.01f; 1280 taperX = BaseShape.PathTaperX * 0.01f;
930 if (taperX < 0.0f) 1281 if (taperX < 0.0f)
931 taperX = -taperX; 1282 taperX = -taperX;
932 taperX1 = 1.0f - taperX; 1283 taperX1 = 1.0f - taperX;
933 1284
934 taperY = _pbs.PathTaperY * 0.01f; 1285 taperY = BaseShape.PathTaperY * 0.01f;
935 if (taperY < 0.0f) 1286 if (taperY < 0.0f)
936 taperY = -taperY; 1287 taperY = -taperY;
937 taperY1 = 1.0f - taperY; 1288 taperY1 = 1.0f - taperY;
@@ -941,20 +1292,18 @@ public sealed class BSPrim : PhysicsActor
941 1292
942 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); 1293 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
943 1294
944 pathBegin = (float)_pbs.PathBegin * 2.0e-5f; 1295 pathBegin = (float)BaseShape.PathBegin * 2.0e-5f;
945 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; 1296 pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f;
946 volume *= (pathEnd - pathBegin); 1297 volume *= (pathEnd - pathBegin);
947 1298
948 // this is crude aproximation 1299 // this is crude aproximation
949 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; 1300 profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f;
950 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; 1301 profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f;
951 volume *= (profileEnd - profileBegin); 1302 volume *= (profileEnd - profileBegin);
952 1303
953 returnMass = _density * volume; 1304 returnMass = _density * volume;
954 1305
955 /* 1306 /* Comment out code that computes the mass of the linkset. That is done in the Linkset class.
956 * This change means each object keeps its own mass and the Mass property
957 * will return the sum if we're part of a linkset.
958 if (IsRootOfLinkset) 1307 if (IsRootOfLinkset)
959 { 1308 {
960 foreach (BSPrim prim in _childrenPrims) 1309 foreach (BSPrim prim in _childrenPrims)
@@ -967,296 +1316,49 @@ public sealed class BSPrim : PhysicsActor
967 if (returnMass <= 0) 1316 if (returnMass <= 0)
968 returnMass = 0.0001f; 1317 returnMass = 0.0001f;
969 1318
970 if (returnMass > _scene.MaximumObjectMass) 1319 if (returnMass > PhysicsScene.MaximumObjectMass)
971 returnMass = _scene.MaximumObjectMass; 1320 returnMass = PhysicsScene.MaximumObjectMass;
972 1321
973 return returnMass; 1322 return returnMass;
974 }// end CalculateMass 1323 }// end CalculateMass
975 #endregion Mass Calculation 1324 #endregion Mass Calculation
976 1325
977 // Create the geometry information in Bullet for later use 1326 // Rebuild the geometry and object.
978 // The objects needs a hull if it's physical otherwise a mesh is enough 1327 // This is called when the shape changes so we need to recreate the mesh/hull.
979 // No locking here because this is done when we know physics is not simulating 1328 // Called at taint-time!!!
980 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used 1329 private void CreateGeomAndObject(bool forceRebuild)
981 // Returns 'true' if the geometry was rebuilt
982 private bool CreateGeom(bool forceRebuild)
983 {
984 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
985 bool ret = false;
986 if (!_scene.NeedsMeshing(_pbs))
987 {
988 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
989 {
990 // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
991 // {
992 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
993 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
994 {
995 // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
996 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
997 // Bullet native objects are scaled by the Bullet engine so pass the size in
998 _scale = _size;
999 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
1000 ret = true;
1001 }
1002 // }
1003 }
1004 else
1005 {
1006 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
1007 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
1008 {
1009 // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
1010 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
1011 _scale = _size;
1012 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
1013 ret = true;
1014 }
1015 }
1016 }
1017 else
1018 {
1019 if (IsPhysical)
1020 {
1021 if (forceRebuild || _hullKey == 0)
1022 {
1023 // physical objects require a hull for interaction.
1024 // This will create the mesh if it doesn't already exist
1025 CreateGeomHull();
1026 ret = true;
1027 }
1028 }
1029 else
1030 {
1031 if (forceRebuild || _meshKey == 0)
1032 {
1033 // Static (non-physical) objects only need a mesh for bumping into
1034 CreateGeomMesh();
1035 ret = true;
1036 }
1037 }
1038 }
1039 return ret;
1040 }
1041
1042 // No locking here because this is done when we know physics is not simulating
1043 private void CreateGeomMesh()
1044 {
1045 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD;
1046 ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod);
1047 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey);
1048
1049 // if this new shape is the same as last time, don't recreate the mesh
1050 if (_meshKey == newMeshKey) return;
1051
1052 // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1053 // Since we're recreating new, get rid of any previously generated shape
1054 if (_meshKey != 0)
1055 {
1056 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1057 // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
1058 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1059 _mesh = null;
1060 _meshKey = 0;
1061 }
1062
1063 _meshKey = newMeshKey;
1064 // always pass false for physicalness as this creates some sort of bounding box which we don't need
1065 _mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, lod, false);
1066
1067 int[] indices = _mesh.getIndexListAsInt();
1068 List<OMV.Vector3> vertices = _mesh.getVertexList();
1069
1070 float[] verticesAsFloats = new float[vertices.Count * 3];
1071 int vi = 0;
1072 foreach (OMV.Vector3 vv in vertices)
1073 {
1074 verticesAsFloats[vi++] = vv.X;
1075 verticesAsFloats[vi++] = vv.Y;
1076 verticesAsFloats[vi++] = vv.Z;
1077 }
1078
1079 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
1080 // LogHeader, _localID, _meshKey, indices.Length, vertices.Count);
1081 BulletSimAPI.CreateMesh(_scene.WorldID, _meshKey, indices.GetLength(0), indices,
1082 vertices.Count, verticesAsFloats);
1083
1084 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1085 // meshes are already scaled by the meshmerizer
1086 _scale = new OMV.Vector3(1f, 1f, 1f);
1087 // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID);
1088 return;
1089 }
1090
1091 // No locking here because this is done when we know physics is not simulating
1092 private void CreateGeomHull()
1093 { 1330 {
1094 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; 1331 // If this prim is part of a linkset, we must remove and restore the physical
1095 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); 1332 // links if the body is rebuilt.
1096 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); 1333 bool needToRestoreLinkset = false;
1097 1334 bool needToRestoreVehicle = false;
1098 // if the hull hasn't changed, don't rebuild it 1335
1099 if (newHullKey == _hullKey) return; 1336 // Create the correct physical representation for this type of object.
1100 1337 // Updates PhysBody and PhysShape with the new information.
1101 // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); 1338 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
1102 1339 // Returns 'true' if either the body or the shape was changed.
1103 // Since we're recreating new, get rid of any previously generated shape 1340 PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody)
1104 if (_hullKey != 0)
1105 {
1106 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1107 // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey);
1108 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1109 _hullKey = 0;
1110 }
1111
1112 _hullKey = newHullKey;
1113
1114 // Make sure the underlying mesh exists and is correct
1115 CreateGeomMesh();
1116
1117 int[] indices = _mesh.getIndexListAsInt();
1118 List<OMV.Vector3> vertices = _mesh.getVertexList();
1119
1120 //format conversion from IMesh format to DecompDesc format
1121 List<int> convIndices = new List<int>();
1122 List<float3> convVertices = new List<float3>();
1123 for (int ii = 0; ii < indices.GetLength(0); ii++)
1124 {
1125 convIndices.Add(indices[ii]);
1126 }
1127 foreach (OMV.Vector3 vv in vertices)
1128 { 1341 {
1129 convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); 1342 // Called if the current prim body is about to be destroyed.
1130 } 1343 // Remove all the physical dependencies on the old body.
1344 // (Maybe someday make the changing of BSShape an event handled by BSLinkset.)
1345 needToRestoreLinkset = Linkset.RemoveBodyDependencies(this);
1346 needToRestoreVehicle = _vehicle.RemoveBodyDependencies(this);
1347 });
1131 1348
1132 // setup and do convex hull conversion 1349 if (needToRestoreLinkset)
1133 _hulls = new List<ConvexResult>();
1134 DecompDesc dcomp = new DecompDesc();
1135 dcomp.mIndices = convIndices;
1136 dcomp.mVertices = convVertices;
1137 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
1138 // create the hull into the _hulls variable
1139 convexBuilder.process(dcomp);
1140
1141 // Convert the vertices and indices for passing to unmanaged.
1142 // The hull information is passed as a large floating point array.
1143 // The format is:
1144 // convHulls[0] = number of hulls
1145 // convHulls[1] = number of vertices in first hull
1146 // convHulls[2] = hull centroid X coordinate
1147 // convHulls[3] = hull centroid Y coordinate
1148 // convHulls[4] = hull centroid Z coordinate
1149 // convHulls[5] = first hull vertex X
1150 // convHulls[6] = first hull vertex Y
1151 // convHulls[7] = first hull vertex Z
1152 // convHulls[8] = second hull vertex X
1153 // ...
1154 // convHulls[n] = number of vertices in second hull
1155 // convHulls[n+1] = second hull centroid X coordinate
1156 // ...
1157 //
1158 // TODO: is is very inefficient. Someday change the convex hull generator to return
1159 // data structures that do not need to be converted in order to pass to Bullet.
1160 // And maybe put the values directly into pinned memory rather than marshaling.
1161 int hullCount = _hulls.Count;
1162 int totalVertices = 1; // include one for the count of the hulls
1163 foreach (ConvexResult cr in _hulls)
1164 { 1350 {
1165 totalVertices += 4; // add four for the vertex count and centroid 1351 // If physical body dependencies were removed, restore them
1166 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles 1352 Linkset.RestoreBodyDependencies(this);
1167 } 1353 }
1168 float[] convHulls = new float[totalVertices]; 1354 if (needToRestoreVehicle)
1169
1170 convHulls[0] = (float)hullCount;
1171 int jj = 1;
1172 foreach (ConvexResult cr in _hulls)
1173 { 1355 {
1174 // copy vertices for index access 1356 // If physical body dependencies were removed, restore them
1175 float3[] verts = new float3[cr.HullVertices.Count]; 1357 _vehicle.RestoreBodyDependencies(this);
1176 int kk = 0;
1177 foreach (float3 ff in cr.HullVertices)
1178 {
1179 verts[kk++] = ff;
1180 }
1181
1182 // add to the array one hull's worth of data
1183 convHulls[jj++] = cr.HullIndices.Count;
1184 convHulls[jj++] = 0f; // centroid x,y,z
1185 convHulls[jj++] = 0f;
1186 convHulls[jj++] = 0f;
1187 foreach (int ind in cr.HullIndices)
1188 {
1189 convHulls[jj++] = verts[ind].x;
1190 convHulls[jj++] = verts[ind].y;
1191 convHulls[jj++] = verts[ind].z;
1192 }
1193 } 1358 }
1194 1359
1195 // create the hull definition in Bullet 1360 // Make sure the properties are set on the new object
1196 // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount); 1361 UpdatePhysicalParameters();
1197 BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls);
1198 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1199 // meshes are already scaled by the meshmerizer
1200 _scale = new OMV.Vector3(1f, 1f, 1f);
1201 // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1202 return;
1203 }
1204
1205 // Callback from convex hull creater with a newly created hull.
1206 // Just add it to the collection of hulls for this shape.
1207 private void HullReturn(ConvexResult result)
1208 {
1209 _hulls.Add(result);
1210 return;
1211 }
1212
1213 // Create an object in Bullet if it has not already been created
1214 // No locking here because this is done when the physics engine is not simulating
1215 // Returns 'true' if an object was actually created.
1216 private bool CreateObject()
1217 {
1218 // this routine is called when objects are rebuilt.
1219
1220 // the mesh or hull must have already been created in Bullet
1221 ShapeData shape;
1222 FillShapeInfo(out shape);
1223 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1224 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1225
1226 // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
1227 Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
1228
1229 return ret;
1230 }
1231
1232 // Copy prim's info into the BulletSim shape description structure
1233 public void FillShapeInfo(out ShapeData shape)
1234 {
1235 shape.ID = _localID;
1236 shape.Type = _shapeType;
1237 shape.Position = _position;
1238 shape.Rotation = _orientation;
1239 shape.Velocity = _velocity;
1240 shape.Scale = _scale;
1241 shape.Mass = _isPhysical ? _mass : 0f;
1242 shape.Buoyancy = _buoyancy;
1243 shape.HullKey = _hullKey;
1244 shape.MeshKey = _meshKey;
1245 shape.Friction = _friction;
1246 shape.Restitution = _restitution;
1247 shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
1248 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1249 }
1250
1251
1252 // Rebuild the geometry and object.
1253 // This is called when the shape changes so we need to recreate the mesh/hull.
1254 // No locking here because this is done when the physics engine is not simulating
1255 private void RecreateGeomAndObject()
1256 {
1257 // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID);
1258 if (CreateGeom(true))
1259 CreateObject();
1260 return; 1362 return;
1261 } 1363 }
1262 1364
@@ -1277,7 +1379,7 @@ public sealed class BSPrim : PhysicsActor
1277 const float ACCELERATION_TOLERANCE = 0.01f; 1379 const float ACCELERATION_TOLERANCE = 0.01f;
1278 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; 1380 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1279 1381
1280 public void UpdateProperties(EntityProperties entprop) 1382 public override void UpdateProperties(EntityProperties entprop)
1281 { 1383 {
1282 /* 1384 /*
1283 UpdatedProperties changed = 0; 1385 UpdatedProperties changed = 0;
@@ -1315,7 +1417,7 @@ public sealed class BSPrim : PhysicsActor
1315 if (changed != 0) 1417 if (changed != 0)
1316 { 1418 {
1317 // Only update the position of single objects and linkset roots 1419 // Only update the position of single objects and linkset roots
1318 if (this._parentPrim == null) 1420 if (Linkset.IsRoot(this))
1319 { 1421 {
1320 base.RequestPhysicsterseUpdate(); 1422 base.RequestPhysicsterseUpdate();
1321 } 1423 }
@@ -1325,78 +1427,46 @@ public sealed class BSPrim : PhysicsActor
1325 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. 1427 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1326 1428
1327 // Updates only for individual prims and for the root object of a linkset. 1429 // Updates only for individual prims and for the root object of a linkset.
1328 if (_linkset.IsRoot(this)) 1430 if (Linkset.IsRoot(this))
1329 { 1431 {
1330 // Assign to the local variables so the normal set action does not happen 1432 // Assign directly to the local variables so the normal set action does not happen
1331 _position = entprop.Position; 1433 _position = entprop.Position;
1332 _orientation = entprop.Rotation; 1434 _orientation = entprop.Rotation;
1333 _velocity = entprop.Velocity; 1435 _velocity = entprop.Velocity;
1334 _acceleration = entprop.Acceleration; 1436 _acceleration = entprop.Acceleration;
1335 _rotationalVelocity = entprop.RotationalVelocity; 1437 _rotationalVelocity = entprop.RotationalVelocity;
1336 1438
1337 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", 1439 // The sanity check can change the velocity and/or position.
1338 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1440 if (PositionSanityCheck(true))
1339 // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1441 {
1340 // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1442 entprop.Position = _position;
1443 entprop.Velocity = _velocity;
1444 }
1445
1446 // remember the current and last set values
1447 LastEntityProperties = CurrentEntityProperties;
1448 CurrentEntityProperties = entprop;
1449
1450 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation;
1451 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
1452 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
1453
1454 // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG
1341 1455
1342 base.RequestPhysicsterseUpdate(); 1456 base.RequestPhysicsterseUpdate();
1343 } 1457 }
1344 /* 1458 /*
1345 else 1459 else
1346 { 1460 {
1347 // For debugging, we also report the movement of children 1461 // For debugging, report the movement of children
1348 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1462 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1349 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1463 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1350 entprop.Acceleration, entprop.RotationalVelocity); 1464 entprop.Acceleration, entprop.RotationalVelocity);
1351 } 1465 }
1352 */ 1466 */
1353 }
1354
1355 // I've collided with something
1356 CollisionEventUpdate collisionCollection;
1357 public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
1358 {
1359 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
1360
1361 // The following lines make IsColliding() and IsCollidingGround() work
1362 _collidingStep = _scene.SimulationStep;
1363 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
1364 {
1365 _collidingGroundStep = _scene.SimulationStep;
1366 }
1367
1368 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
1369
1370 // if someone is subscribed to collision events....
1371 if (_subscribedEventsMs != 0) {
1372 // throttle the collisions to the number of milliseconds specified in the subscription
1373 int nowTime = _scene.SimulationNowTime;
1374 if (nowTime >= _nextCollisionOkTime) {
1375 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
1376 1467
1377 if (collisionCollection == null) 1468 // The linkset implimentation might want to know about this.
1378 collisionCollection = new CollisionEventUpdate(); 1469 Linkset.UpdateProperties(this);
1379 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
1380 }
1381 }
1382 }
1383
1384 // The scene is telling us it's time to pass our collected collisions into the simulator
1385 public void SendCollisions()
1386 {
1387 if (collisionCollection != null && collisionCollection.Count > 0)
1388 {
1389 base.SendCollisionUpdate(collisionCollection);
1390 // The collisionCollection structure is passed around in the simulator.
1391 // Make sure we don't have a handle to that one and that a new one is used next time.
1392 collisionCollection = null;
1393 }
1394 }
1395
1396 // Invoke the detailed logger and output something if it's enabled.
1397 private void DetailLog(string msg, params Object[] args)
1398 {
1399 Scene.PhysicsLogging.Write(msg, args);
1400 } 1470 }
1401} 1471}
1402} 1472}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index a31c578..27a78d1 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -39,96 +39,88 @@ using log4net;
39using OpenMetaverse; 39using OpenMetaverse;
40 40
41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
42// Debug linkset 42// Test sculpties (verified that they don't work)
43// Test with multiple regions in one simulator
44// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight)
45// Test sculpties
46// Compute physics FPS reasonably 43// Compute physics FPS reasonably
47// Based on material, set density and friction 44// Based on material, set density and friction
48// More efficient memory usage when passing hull information from BSPrim to BulletSim 45// Don't use constraints in linksets of non-physical objects. Means having to move children manually.
49// Move all logic out of the C++ code and into the C# code for easier future modifications.
50// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? 46// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
51// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) 47// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground)
52// At the moment, physical and phantom causes object to drop through the terrain 48// At the moment, physical and phantom causes object to drop through the terrain
53// Physical phantom objects and related typing (collision options ) 49// Physical phantom objects and related typing (collision options )
54// Use collision masks for collision with terrain and phantom objects
55// Check out llVolumeDetect. Must do something for that. 50// Check out llVolumeDetect. Must do something for that.
51// Use collision masks for collision with terrain and phantom objects
52// More efficient memory usage when passing hull information from BSPrim to BulletSim
56// Should prim.link() and prim.delink() membership checking happen at taint time? 53// Should prim.link() and prim.delink() membership checking happen at taint time?
57// changing the position and orientation of a linked prim must rebuild the constraint with the root. 54// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once.
58// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
59// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 55// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
60// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
61// Implement LockAngularMotion 56// Implement LockAngularMotion
62// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 57// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
63// Does NeedsMeshing() really need to exclude all the different shapes?
64// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. 58// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
65// Add PID movement operations. What does ScenePresence.MoveToTarget do? 59// Add PID movement operations. What does ScenePresence.MoveToTarget do?
66// Check terrain size. 128 or 127? 60// Check terrain size. 128 or 127?
67// Raycast 61// Raycast
68// 62//
69namespace OpenSim.Region.Physics.BulletSPlugin 63namespace OpenSim.Region.Physics.BulletSPlugin
70{ 64{
71public class BSScene : PhysicsScene, IPhysicsParameters 65public sealed class BSScene : PhysicsScene, IPhysicsParameters
72{ 66{
73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 67 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
74 private static readonly string LogHeader = "[BULLETS SCENE]"; 68 private static readonly string LogHeader = "[BULLETS SCENE]";
75 69
76 public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); } 70 // The name of the region we're working for.
71 public string RegionName { get; private set; }
77 72
78 public string BulletSimVersion = "?"; 73 public string BulletSimVersion = "?";
79 74
80 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); 75 public Dictionary<uint, BSPhysObject> PhysObjects;
81 private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>(); 76 public BSShapeCollection Shapes;
82 private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
83 private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>();
84 private List<BSPrim> m_vehicles = new List<BSPrim>();
85 private float[] m_heightMap;
86 private float m_waterLevel;
87 private uint m_worldID;
88 public uint WorldID { get { return m_worldID; } }
89 77
90 // let my minuions use my logger 78 // Keeping track of the objects with collisions so we can report begin and end of a collision
91 public ILog Logger { get { return m_log; } } 79 public HashSet<BSPhysObject> ObjectsWithCollisions = new HashSet<BSPhysObject>();
80 public HashSet<BSPhysObject> ObjectsWithNoMoreCollisions = new HashSet<BSPhysObject>();
81 // Keep track of all the avatars so we can send them a collision event
82 // every tick so OpenSim will update its animation.
83 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>();
92 84
93 private bool m_initialized = false; 85 // List of all the objects that have vehicle properties and should be called
86 // to update each physics step.
87 private List<BSPhysObject> m_vehicles = new List<BSPhysObject>();
94 88
95 private int m_detailedStatsStep = 0; 89 // let my minuions use my logger
90 public ILog Logger { get { return m_log; } }
96 91
97 public IMesher mesher; 92 public IMesher mesher;
98 private float m_meshLOD; 93 // Level of Detail values kept as float because that's what the Meshmerizer wants
99 public float MeshLOD 94 public float MeshLOD { get; private set; }
100 { 95 public float MeshMegaPrimLOD { get; private set; }
101 get { return m_meshLOD; } 96 public float MeshMegaPrimThreshold { get; private set; }
102 } 97 public float SculptLOD { get; private set; }
103 private float m_sculptLOD;
104 public float SculptLOD
105 {
106 get { return m_sculptLOD; }
107 }
108 98
109 private BulletSim m_worldSim; 99 public uint WorldID { get; private set; }
110 public BulletSim World 100 public BulletSim World { get; private set; }
111 { 101
112 get { return m_worldSim; } 102 // All the constraints that have been allocated in this instance.
113 } 103 public BSConstraintCollection Constraints { get; private set; }
114 private BSConstraintCollection m_constraintCollection;
115 public BSConstraintCollection Constraints
116 {
117 get { return m_constraintCollection; }
118 }
119 104
105 // Simulation parameters
120 private int m_maxSubSteps; 106 private int m_maxSubSteps;
121 private float m_fixedTimeStep; 107 private float m_fixedTimeStep;
122 private long m_simulationStep = 0; 108 private long m_simulationStep = 0;
123 public long SimulationStep { get { return m_simulationStep; } } 109 public long SimulationStep { get { return m_simulationStep; } }
124 110 private int m_taintsToProcessPerStep;
125 public float LastSimulatedTimestep { get; private set; }
126 111
127 // A value of the time now so all the collision and update routines do not have to get their own 112 // A value of the time now so all the collision and update routines do not have to get their own
128 // Set to 'now' just before all the prims and actors are called for collisions and updates 113 // Set to 'now' just before all the prims and actors are called for collisions and updates
129 private int m_simulationNowTime; 114 public int SimulationNowTime { get; private set; }
130 public int SimulationNowTime { get { return m_simulationNowTime; } } 115
116 // True if initialized and ready to do simulation steps
117 private bool m_initialized = false;
118
119 // Flag which is true when processing taints.
120 // Not guaranteed to be correct all the time (don't depend on this) but good for debugging.
121 public bool InTaintTime { get; private set; }
131 122
123 // Pinned memory used to pass step information between managed and unmanaged
132 private int m_maxCollisionsPerFrame; 124 private int m_maxCollisionsPerFrame;
133 private CollisionDesc[] m_collisionArray; 125 private CollisionDesc[] m_collisionArray;
134 private GCHandle m_collisionArrayPinnedHandle; 126 private GCHandle m_collisionArrayPinnedHandle;
@@ -137,14 +129,19 @@ public class BSScene : PhysicsScene, IPhysicsParameters
137 private EntityProperties[] m_updateArray; 129 private EntityProperties[] m_updateArray;
138 private GCHandle m_updateArrayPinnedHandle; 130 private GCHandle m_updateArrayPinnedHandle;
139 131
140 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed 132 public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
141 private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes 133 public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
134 public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
142 135
143 public float PID_D { get; private set; } // derivative 136 public float PID_D { get; private set; } // derivative
144 public float PID_P { get; private set; } // proportional 137 public float PID_P { get; private set; } // proportional
145 138
146 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 139 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
147 public const uint GROUNDPLANE_ID = 1; 140 public const uint GROUNDPLANE_ID = 1;
141 public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
142
143 private float m_waterLevel;
144 public BSTerrainManager TerrainManager { get; private set; }
148 145
149 public ConfigurationParameters Params 146 public ConfigurationParameters Params
150 { 147 {
@@ -154,13 +151,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
154 { 151 {
155 get { return new Vector3(0f, 0f, Params.gravity); } 152 get { return new Vector3(0f, 0f, Params.gravity); }
156 } 153 }
157 154 // Just the Z value of the gravity
158 private float m_maximumObjectMass; 155 public float DefaultGravityZ
159 public float MaximumObjectMass
160 { 156 {
161 get { return m_maximumObjectMass; } 157 get { return Params.gravity; }
162 } 158 }
163 159
160 public float MaximumObjectMass { get; private set; }
161
162 // When functions in the unmanaged code must be called, it is only
163 // done at a known time just before the simulation step. The taint
164 // system saves all these function calls and executes them in
165 // order before the simulation.
164 public delegate void TaintCallback(); 166 public delegate void TaintCallback();
165 private struct TaintCallbackEntry 167 private struct TaintCallbackEntry
166 { 168 {
@@ -172,15 +174,19 @@ public class BSScene : PhysicsScene, IPhysicsParameters
172 callback = c; 174 callback = c;
173 } 175 }
174 } 176 }
175 private List<TaintCallbackEntry> _taintedObjects; 177 private Object _taintLock = new Object(); // lock for using the next object
176 private Object _taintLock = new Object(); 178 private List<TaintCallbackEntry> _taintOperations;
179 private Dictionary<string, TaintCallbackEntry> _postTaintOperations;
180 private List<TaintCallbackEntry> _postStepOperations;
177 181
178 // A pointer to an instance if this structure is passed to the C++ code 182 // A pointer to an instance if this structure is passed to the C++ code
183 // Used to pass basic configuration values to the unmanaged code.
179 ConfigurationParameters[] m_params; 184 ConfigurationParameters[] m_params;
180 GCHandle m_paramsHandle; 185 GCHandle m_paramsHandle;
181 186
182 public bool ShouldDebugLog { get; private set; } 187 // Handle to the callback used by the unmanaged code to call into the managed code.
183 188 // Used for debug logging.
189 // Need to store the handle in a persistant variable so it won't be freed.
184 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; 190 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
185 191
186 // Sometimes you just have to log everything. 192 // Sometimes you just have to log everything.
@@ -189,17 +195,26 @@ public class BSScene : PhysicsScene, IPhysicsParameters
189 private string m_physicsLoggingDir; 195 private string m_physicsLoggingDir;
190 private string m_physicsLoggingPrefix; 196 private string m_physicsLoggingPrefix;
191 private int m_physicsLoggingFileMinutes; 197 private int m_physicsLoggingFileMinutes;
198 // 'true' of the vehicle code is to log lots of details
199 public bool VehicleLoggingEnabled { get; private set; }
192 200
193 private bool m_vehicleLoggingEnabled; 201 #region Construction and Initialization
194 public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
195
196 public BSScene(string identifier) 202 public BSScene(string identifier)
197 { 203 {
198 m_initialized = false; 204 m_initialized = false;
205 // we are passed the name of the region we're working for.
206 RegionName = identifier;
199 } 207 }
200 208
201 public override void Initialise(IMesher meshmerizer, IConfigSource config) 209 public override void Initialise(IMesher meshmerizer, IConfigSource config)
202 { 210 {
211 mesher = meshmerizer;
212 _taintOperations = new List<TaintCallbackEntry>();
213 _postTaintOperations = new Dictionary<string, TaintCallbackEntry>();
214 _postStepOperations = new List<TaintCallbackEntry>();
215 PhysObjects = new Dictionary<uint, BSPhysObject>();
216 Shapes = new BSShapeCollection(this);
217
203 // Allocate pinned memory to pass parameters. 218 // Allocate pinned memory to pass parameters.
204 m_params = new ConfigurationParameters[1]; 219 m_params = new ConfigurationParameters[1];
205 m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); 220 m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned);
@@ -215,7 +230,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
215 230
216 // Enable very detailed logging. 231 // Enable very detailed logging.
217 // By creating an empty logger when not logging, the log message invocation code 232 // By creating an empty logger when not logging, the log message invocation code
218 // can be left in and every call doesn't have to check for null. 233 // can be left in and every call doesn't have to check for null.
219 if (m_physicsLoggingEnabled) 234 if (m_physicsLoggingEnabled)
220 { 235 {
221 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); 236 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes);
@@ -225,39 +240,43 @@ public class BSScene : PhysicsScene, IPhysicsParameters
225 PhysicsLogging = new Logging.LogWriter(); 240 PhysicsLogging = new Logging.LogWriter();
226 } 241 }
227 242
228 // Get the version of the DLL 243 // If Debug logging level, enable logging from the unmanaged code
229 // TODO: this doesn't work yet. Something wrong with marshaling the returned string. 244 m_DebugLogCallbackHandle = null;
230 // BulletSimVersion = BulletSimAPI.GetVersion();
231 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
232
233 // if Debug, enable logging from the unmanaged code
234 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) 245 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
235 { 246 {
236 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); 247 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
237 if (PhysicsLogging.Enabled) 248 if (PhysicsLogging.Enabled)
249 // The handle is saved in a variable to make sure it doesn't get freed after this call
238 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); 250 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
239 else 251 else
240 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); 252 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
241 // the handle is saved in a variable to make sure it doesn't get freed after this call
242 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
243 } 253 }
244 254
245 _taintedObjects = new List<TaintCallbackEntry>(); 255 // Get the version of the DLL
256 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
257 // BulletSimVersion = BulletSimAPI.GetVersion();
258 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
246 259
247 mesher = meshmerizer; 260 // The bounding box for the simulated world. The origin is 0,0,0 unless we're
248 // The bounding box for the simulated world 261 // a child in a mega-region.
249 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); 262 // Bullet actually doesn't care about the extents of the simulated
263 // area. It tracks active objects no matter where they are.
264 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
250 265
251 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); 266 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
252 m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), 267 World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
253 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), 268 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
254 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); 269 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
270 m_DebugLogCallbackHandle));
271
272 Constraints = new BSConstraintCollection(World);
255 273
256 // Initialization to support the transition to a new API which puts most of the logic 274 TerrainManager = new BSTerrainManager(this);
257 // into the C# code so it is easier to modify and add to. 275 TerrainManager.CreateInitialGroundPlaneAndTerrain();
258 m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID));
259 m_constraintCollection = new BSConstraintCollection(World);
260 276
277 m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)Params.linksetImplementation);
278
279 InTaintTime = false;
261 m_initialized = true; 280 m_initialized = true;
262 } 281 }
263 282
@@ -281,10 +300,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
281 // Very detailed logging for physics debugging 300 // Very detailed logging for physics debugging
282 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 301 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
283 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); 302 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
284 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-"); 303 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
285 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); 304 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
286 // Very detailed logging for vehicle debugging 305 // Very detailed logging for vehicle debugging
287 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); 306 VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
307
308 // Do any replacements in the parameters
309 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
288 } 310 }
289 } 311 }
290 } 312 }
@@ -309,13 +331,51 @@ public class BSScene : PhysicsScene, IPhysicsParameters
309 { 331 {
310 m_log.Debug("[BULLETS UNMANAGED]:" + msg); 332 m_log.Debug("[BULLETS UNMANAGED]:" + msg);
311 } 333 }
312 334
313 // Called directly from unmanaged code so don't do much 335 // Called directly from unmanaged code so don't do much
314 private void BulletLoggerPhysLog(string msg) 336 private void BulletLoggerPhysLog(string msg)
315 { 337 {
316 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); 338 DetailLog("[BULLETS UNMANAGED]:" + msg);
317 } 339 }
318 340
341 public override void Dispose()
342 {
343 // m_log.DebugFormat("{0}: Dispose()", LogHeader);
344
345 // make sure no stepping happens while we're deleting stuff
346 m_initialized = false;
347
348 TerrainManager.ReleaseGroundPlaneAndTerrain();
349
350 foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
351 {
352 kvp.Value.Destroy();
353 }
354 PhysObjects.Clear();
355
356 // Now that the prims are all cleaned up, there should be no constraints left
357 if (Constraints != null)
358 {
359 Constraints.Dispose();
360 Constraints = null;
361 }
362
363 if (Shapes != null)
364 {
365 Shapes.Dispose();
366 Shapes = null;
367 }
368
369 // Anything left in the unmanaged code should be cleaned out
370 BulletSimAPI.Shutdown2(World.ptr);
371
372 // Not logging any more
373 PhysicsLogging.Close();
374 }
375 #endregion // Construction and Initialization
376
377 #region Prim and Avatar addition and removal
378
319 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) 379 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
320 { 380 {
321 m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader); 381 m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader);
@@ -329,7 +389,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
329 if (!m_initialized) return null; 389 if (!m_initialized) return null;
330 390
331 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); 391 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
332 lock (m_avatars) m_avatars.Add(localID, actor); 392 lock (PhysObjects) PhysObjects.Add(localID, actor);
393
394 // TODO: Remove kludge someday.
395 // We must generate a collision for avatars whether they collide or not.
396 // This is required by OpenSim to update avatar animations, etc.
397 lock (m_avatars) m_avatars.Add(actor);
398
333 return actor; 399 return actor;
334 } 400 }
335 401
@@ -344,7 +410,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
344 { 410 {
345 try 411 try
346 { 412 {
347 lock (m_avatars) m_avatars.Remove(actor.LocalID); 413 lock (PhysObjects) PhysObjects.Remove(actor.LocalID);
414 // Remove kludge someday
415 lock (m_avatars) m_avatars.Remove(bsactor);
348 } 416 }
349 catch (Exception e) 417 catch (Exception e)
350 { 418 {
@@ -362,11 +430,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
362 BSPrim bsprim = prim as BSPrim; 430 BSPrim bsprim = prim as BSPrim;
363 if (bsprim != null) 431 if (bsprim != null)
364 { 432 {
365 // DetailLog("{0},RemovePrim,call", bsprim.LocalID); 433 DetailLog("{0},RemovePrim,call", bsprim.LocalID);
366 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); 434 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
367 try 435 try
368 { 436 {
369 lock (m_prims) m_prims.Remove(bsprim.LocalID); 437 lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID);
370 } 438 }
371 catch (Exception e) 439 catch (Exception e)
372 { 440 {
@@ -388,18 +456,21 @@ public class BSScene : PhysicsScene, IPhysicsParameters
388 456
389 if (!m_initialized) return null; 457 if (!m_initialized) return null;
390 458
391 // DetailLog("{0},AddPrimShape,call", localID); 459 DetailLog("{0},AddPrimShape,call", localID);
392 460
393 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); 461 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
394 lock (m_prims) m_prims.Add(localID, prim); 462 lock (PhysObjects) PhysObjects.Add(localID, prim);
395 return prim; 463 return prim;
396 } 464 }
397 465
398 // This is a call from the simulator saying that some physical property has been updated. 466 // This is a call from the simulator saying that some physical property has been updated.
399 // The BulletSim driver senses the changing of relevant properties so this taint 467 // The BulletSim driver senses the changing of relevant properties so this taint
400 // information call is not needed. 468 // information call is not needed.
401 public override void AddPhysicsActorTaint(PhysicsActor prim) { } 469 public override void AddPhysicsActorTaint(PhysicsActor prim) { }
402 470
471 #endregion // Prim and Avatar addition and removal
472
473 #region Simulation
403 // Simulate one timestep 474 // Simulate one timestep
404 public override float Simulate(float timeStep) 475 public override float Simulate(float timeStep)
405 { 476 {
@@ -408,14 +479,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters
408 int collidersCount = 0; 479 int collidersCount = 0;
409 IntPtr collidersPtr; 480 IntPtr collidersPtr;
410 481
411 LastSimulatedTimestep = timeStep; 482 int beforeTime = 0;
483 int simTime = 0;
412 484
413 // prevent simulation until we've been initialized 485 // prevent simulation until we've been initialized
414 if (!m_initialized) return 10.0f; 486 if (!m_initialized) return 5.0f;
415
416 int simulateStartTime = Util.EnvironmentTickCount();
417 487
418 // update the prim states while we know the physics engine is not busy 488 // update the prim states while we know the physics engine is not busy
489 int numTaints = _taintOperations.Count;
419 ProcessTaints(); 490 ProcessTaints();
420 491
421 // Some of the prims operate with special vehicle properties 492 // Some of the prims operate with special vehicle properties
@@ -425,25 +496,34 @@ public class BSScene : PhysicsScene, IPhysicsParameters
425 // step the physical world one interval 496 // step the physical world one interval
426 m_simulationStep++; 497 m_simulationStep++;
427 int numSubSteps = 0; 498 int numSubSteps = 0;
499
428 try 500 try
429 { 501 {
430 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, 502 if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
503 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
504
505 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
431 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 506 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
432 // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); 507
508 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
509 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
510 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
511 if (VehicleLoggingEnabled) DumpVehicles(); // DEBUG
433 } 512 }
434 catch (Exception e) 513 catch (Exception e)
435 { 514 {
436 m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); 515 m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}",
437 // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); 516 LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e);
438 // updatedEntityCount = 0; 517 DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}",
518 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
519 updatedEntityCount = 0;
439 collidersCount = 0; 520 collidersCount = 0;
440 } 521 }
441 522
442
443 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in 523 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in
444 524
445 // Get a value for 'now' so all the collision and update routines don't have to get their own 525 // Get a value for 'now' so all the collision and update routines don't have to get their own
446 m_simulationNowTime = Util.EnvironmentTickCount(); 526 SimulationNowTime = Util.EnvironmentTickCount();
447 527
448 // If there were collisions, process them by sending the event to the prim. 528 // If there were collisions, process them by sending the event to the prim.
449 // Collisions must be processed before updates. 529 // Collisions must be processed before updates.
@@ -462,19 +542,32 @@ public class BSScene : PhysicsScene, IPhysicsParameters
462 542
463 // The above SendCollision's batch up the collisions on the objects. 543 // The above SendCollision's batch up the collisions on the objects.
464 // Now push the collisions into the simulator. 544 // Now push the collisions into the simulator.
465 foreach (BSPrim bsp in m_primsWithCollisions) 545 if (ObjectsWithCollisions.Count > 0)
466 bsp.SendCollisions(); 546 {
467 m_primsWithCollisions.Clear(); 547 foreach (BSPhysObject bsp in ObjectsWithCollisions)
468 548 if (!bsp.SendCollisions())
469 // This is a kludge to get avatar movement updated. 549 {
470 // Don't send collisions only if there were collisions -- send everytime. 550 // If the object is done colliding, see that it's removed from the colliding list
471 // ODE sends collisions even if there are none and this is used to update 551 ObjectsWithNoMoreCollisions.Add(bsp);
472 // avatar animations and stuff. 552 }
473 // foreach (BSCharacter bsc in m_avatarsWithCollisions) 553 }
474 // bsc.SendCollisions(); 554
475 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 555 // This is a kludge to get avatar movement updates.
476 kvp.Value.SendCollisions(); 556 // The simulator expects collisions for avatars even if there are have been no collisions.
477 m_avatarsWithCollisions.Clear(); 557 // The event updates avatar animations and stuff.
558 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
559 foreach (BSPhysObject bsp in m_avatars)
560 if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice
561 bsp.SendCollisions();
562
563 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
564 // Not done above because it is inside an iteration of ObjectWithCollisions.
565 if (ObjectsWithNoMoreCollisions.Count > 0)
566 {
567 foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
568 ObjectsWithCollisions.Remove(po);
569 ObjectsWithNoMoreCollisions.Clear();
570 }
478 571
479 // If any of the objects had updated properties, tell the object it has been changed by the physics engine 572 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
480 if (updatedEntityCount > 0) 573 if (updatedEntityCount > 0)
@@ -482,320 +575,316 @@ public class BSScene : PhysicsScene, IPhysicsParameters
482 for (int ii = 0; ii < updatedEntityCount; ii++) 575 for (int ii = 0; ii < updatedEntityCount; ii++)
483 { 576 {
484 EntityProperties entprop = m_updateArray[ii]; 577 EntityProperties entprop = m_updateArray[ii];
485 BSPrim prim; 578 BSPhysObject pobj;
486 if (m_prims.TryGetValue(entprop.ID, out prim)) 579 if (PhysObjects.TryGetValue(entprop.ID, out pobj))
487 {
488 prim.UpdateProperties(entprop);
489 continue;
490 }
491 BSCharacter actor;
492 if (m_avatars.TryGetValue(entprop.ID, out actor))
493 { 580 {
494 actor.UpdateProperties(entprop); 581 pobj.UpdateProperties(entprop);
495 continue;
496 } 582 }
497 } 583 }
498 } 584 }
499 585
500 // If enabled, call into the physics engine to dump statistics 586 ProcessPostStepTaints();
501 if (m_detailedStatsStep > 0)
502 {
503 if ((m_simulationStep % m_detailedStatsStep) == 0)
504 {
505 BulletSimAPI.DumpBulletStatistics();
506 }
507 }
508 587
509 // this is a waste since the outside routine also calcuates the physics simulation 588 // This causes the unmanaged code to output ALL the values found in ALL the objects in the world.
510 // period. TODO: There should be a way of computing physics frames from simulator computation. 589 // Only enable this in a limited test world with few objects.
511 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); 590 // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG
512 // return (timeStep * (float)simulateTotalTime); 591
513 592 // The physics engine returns the number of milliseconds it simulated this call.
514 // TODO: FIX THIS: fps calculation possibly wrong. 593 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
515 // This calculation says 1/timeStep is the ideal frame rate. Any time added to 594 // We multiply by 55 to give a recognizable running rate (55 or less).
516 // that by the physics simulation gives a slower frame rate. 595 return numSubSteps * m_fixedTimeStep * 1000 * 55;
517 long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime); 596 // return timeStep * 1000 * 55;
518 if (totalSimulationTime >= timeStep)
519 return 0;
520 return 1f / (timeStep + totalSimulationTime);
521 } 597 }
522 598
523 // Something has collided 599 // Something has collided
524 private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration) 600 private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration)
525 { 601 {
526 if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID) 602 if (localID <= TerrainManager.HighestTerrainID)
527 { 603 {
528 return; // don't send collisions to the terrain 604 return; // don't send collisions to the terrain
529 } 605 }
530 606
531 ActorTypes type = ActorTypes.Prim; 607 BSPhysObject collider;
532 if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID) 608 if (!PhysObjects.TryGetValue(localID, out collider))
533 type = ActorTypes.Ground; 609 {
534 else if (m_avatars.ContainsKey(collidingWith)) 610 // If the object that is colliding cannot be found, just ignore the collision.
535 type = ActorTypes.Agent; 611 DetailLog("{0},BSScene.SendCollision,colliderNotInObjectList,id={1},with={2}", DetailLogZero, localID, collidingWith);
536
537 BSPrim prim;
538 if (m_prims.TryGetValue(localID, out prim)) {
539 prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
540 m_primsWithCollisions.Add(prim);
541 return; 612 return;
542 } 613 }
543 BSCharacter actor; 614
544 if (m_avatars.TryGetValue(localID, out actor)) { 615 // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called.
545 actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration); 616 BSPhysObject collidee = null;
546 m_avatarsWithCollisions.Add(actor); 617 PhysObjects.TryGetValue(collidingWith, out collidee);
547 return; 618
619 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
620
621 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
622 {
623 // If a collision was posted, remember to send it to the simulator
624 ObjectsWithCollisions.Add(collider);
548 } 625 }
626
549 return; 627 return;
550 } 628 }
551 629
630 #endregion // Simulation
631
552 public override void GetResults() { } 632 public override void GetResults() { }
553 633
634 #region Terrain
635
554 public override void SetTerrain(float[] heightMap) { 636 public override void SetTerrain(float[] heightMap) {
555 m_heightMap = heightMap; 637 TerrainManager.SetTerrain(heightMap);
556 this.TaintedObject("BSScene.SetTerrain", delegate()
557 {
558 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
559 });
560 } 638 }
561 639
562 // Someday we will have complex terrain with caves and tunnels 640 public override void SetWaterLevel(float baseheight)
563 // For the moment, it's flat and convex
564 public float GetTerrainHeightAtXYZ(Vector3 loc)
565 { 641 {
566 return GetTerrainHeightAtXY(loc.X, loc.Y); 642 m_waterLevel = baseheight;
643 }
644 // Someday....
645 public float GetWaterLevelAtXYZ(Vector3 loc)
646 {
647 return m_waterLevel;
567 } 648 }
568 649
569 public float GetTerrainHeightAtXY(float tX, float tY) 650 public override void DeleteTerrain()
570 { 651 {
571 if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize) 652 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
572 return 30;
573 return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)];
574 } 653 }
575 654
576 public override void SetWaterLevel(float baseheight) 655 // Although no one seems to check this, I do support combining.
656 public override bool SupportsCombining()
577 { 657 {
578 m_waterLevel = baseheight; 658 return TerrainManager.SupportsCombining();
579 // TODO: pass to physics engine so things will float?
580 } 659 }
581 public float GetWaterLevel() 660 // This call says I am a child to region zero in a mega-region. 'pScene' is that
661 // of region zero, 'offset' is my offset from regions zero's origin, and
662 // 'extents' is the largest XY that is handled in my region.
663 public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
582 { 664 {
583 return m_waterLevel; 665 TerrainManager.Combine(pScene, offset, extents);
584 } 666 }
585 667
586 public override void DeleteTerrain() 668 // Unhook all the combining that I know about.
669 public override void UnCombine(PhysicsScene pScene)
587 { 670 {
588 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); 671 TerrainManager.UnCombine(pScene);
589 } 672 }
590 673
591 public override void Dispose() 674 #endregion // Terrain
675
676 public override Dictionary<uint, float> GetTopColliders()
592 { 677 {
593 // m_log.DebugFormat("{0}: Dispose()", LogHeader); 678 return new Dictionary<uint, float>();
679 }
594 680
595 // make sure no stepping happens while we're deleting stuff 681 public override bool IsThreaded { get { return false; } }
596 m_initialized = false;
597 682
598 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 683 #region Taints
599 {
600 kvp.Value.Destroy();
601 }
602 m_avatars.Clear();
603 684
604 foreach (KeyValuePair<uint, BSPrim> kvp in m_prims) 685 // Calls to the PhysicsActors can't directly call into the physics engine
605 { 686 // because it might be busy. We delay changes to a known time.
606 kvp.Value.Destroy(); 687 // We rely on C#'s closure to save and restore the context for the delegate.
607 } 688 public void TaintedObject(String ident, TaintCallback callback)
608 m_prims.Clear(); 689 {
690 if (!m_initialized) return;
609 691
610 // Now that the prims are all cleaned up, there should be no constraints left 692 lock (_taintLock)
611 if (m_constraintCollection != null)
612 { 693 {
613 m_constraintCollection.Dispose(); 694 _taintOperations.Add(new TaintCallbackEntry(ident, callback));
614 m_constraintCollection = null;
615 } 695 }
616 696
617 // Anything left in the unmanaged code should be cleaned out 697 return;
618 BulletSimAPI.Shutdown(WorldID);
619
620 // Not logging any more
621 PhysicsLogging.Close();
622 } 698 }
623 699
624 public override Dictionary<uint, float> GetTopColliders() 700 // Sometimes a potentially tainted operation can be used in and out of taint time.
701 // This routine executes the command immediately if in taint-time otherwise it is queued.
702 public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback)
625 { 703 {
626 return new Dictionary<uint, float>(); 704 if (inTaintTime)
705 callback();
706 else
707 TaintedObject(ident, callback);
627 } 708 }
628 709
629 public override bool IsThreaded { get { return false; } } 710 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues
630 711 // a callback into itself to do the actual property change. That callback is called
631 /// <summary> 712 // here just before the physics engine is called to step the simulation.
632 /// Routine to figure out if we need to mesh this prim with our mesher 713 public void ProcessTaints()
633 /// </summary>
634 /// <param name="pbs"></param>
635 /// <returns>true if the prim needs meshing</returns>
636 public bool NeedsMeshing(PrimitiveBaseShape pbs)
637 { 714 {
638 // most of this is redundant now as the mesher will return null if it cant mesh a prim 715 InTaintTime = true; // Only used for debugging so locking is not necessary.
639 // but we still need to check for sculptie meshing being enabled so this is the most 716 ProcessRegularTaints();
640 // convenient place to do it for now... 717 ProcessPostTaintTaints();
641 718 InTaintTime = false;
642 // int iPropertiesNotSupportedDefault = 0; 719 }
643
644 if (pbs.SculptEntry && !_meshSculptedPrim)
645 {
646 // Render sculpties as boxes
647 return false;
648 }
649 720
650 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet 721 private void ProcessRegularTaints()
651 // can use an internal representation for the prim 722 {
652 if (!_forceSimplePrimMeshing) 723 if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process
653 { 724 {
654 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) 725 /*
655 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 726 // Code to limit the number of taints processed per step. Meant to limit step time.
656 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)) 727 // Unsure if a good idea as code assumes that taints are done before the step.
728 int taintCount = m_taintsToProcessPerStep;
729 TaintCallbackEntry oneCallback = new TaintCallbackEntry();
730 while (_taintOperations.Count > 0 && taintCount-- > 0)
657 { 731 {
658 732 bool gotOne = false;
659 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 733 lock (_taintLock)
660 && pbs.ProfileHollow == 0
661 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
662 && pbs.PathBegin == 0 && pbs.PathEnd == 0
663 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
664 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
665 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
666 { 734 {
667 return false; 735 if (_taintOperations.Count > 0)
736 {
737 oneCallback = _taintOperations[0];
738 _taintOperations.RemoveAt(0);
739 gotOne = true;
740 }
741 }
742 if (gotOne)
743 {
744 try
745 {
746 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident);
747 oneCallback.callback();
748 }
749 catch (Exception e)
750 {
751 DetailLog("{0},BSScene.ProcessTaints,doTaintException,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG
752 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e);
753 }
668 } 754 }
669 } 755 }
670 } 756 if (_taintOperations.Count > 0)
671
672 /* TODO: verify that the mesher will now do all these shapes
673 if (pbs.ProfileHollow != 0)
674 iPropertiesNotSupportedDefault++;
675
676 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
677 iPropertiesNotSupportedDefault++;
678
679 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
680 iPropertiesNotSupportedDefault++;
681
682 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
683 iPropertiesNotSupportedDefault++;
684
685 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
686 iPropertiesNotSupportedDefault++;
687
688 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
689 iPropertiesNotSupportedDefault++;
690
691 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
692 iPropertiesNotSupportedDefault++;
693
694 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
695 iPropertiesNotSupportedDefault++;
696
697 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1)
698 iPropertiesNotSupportedDefault++;
699
700 // test for torus
701 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
702 {
703 if (pbs.PathCurve == (byte)Extrusion.Curve1)
704 { 757 {
705 iPropertiesNotSupportedDefault++; 758 DetailLog("{0},BSScene.ProcessTaints,leftTaintsOnList,numNotProcessed={1}", DetailLogZero, _taintOperations.Count);
706 } 759 }
707 } 760 */
708 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) 761
709 { 762 // swizzle a new list into the list location so we can process what's there
710 if (pbs.PathCurve == (byte)Extrusion.Straight) 763 List<TaintCallbackEntry> oldList;
764 lock (_taintLock)
711 { 765 {
712 iPropertiesNotSupportedDefault++; 766 oldList = _taintOperations;
767 _taintOperations = new List<TaintCallbackEntry>();
713 } 768 }
714 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits 769
715 else if (pbs.PathCurve == (byte)Extrusion.Curve1) 770 foreach (TaintCallbackEntry tcbe in oldList)
716 { 771 {
717 iPropertiesNotSupportedDefault++; 772 try
773 {
774 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG
775 tcbe.callback();
776 }
777 catch (Exception e)
778 {
779 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
780 }
718 } 781 }
782 oldList.Clear();
719 } 783 }
720 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) 784 }
785
786 // Schedule an update to happen after all the regular taints are processed.
787 // Note that new requests for the same operation ("ident") for the same object ("ID")
788 // will replace any previous operation by the same object.
789 public void PostTaintObject(String ident, uint ID, TaintCallback callback)
790 {
791 string uniqueIdent = ident + "-" + ID.ToString();
792 lock (_taintLock)
721 { 793 {
722 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2) 794 _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback);
723 {
724 iPropertiesNotSupportedDefault++;
725 }
726 } 795 }
727 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) 796
797 return;
798 }
799
800 private void ProcessPostTaintTaints()
801 {
802 if (_postTaintOperations.Count > 0)
728 { 803 {
729 if (pbs.PathCurve == (byte)Extrusion.Straight) 804 Dictionary<string, TaintCallbackEntry> oldList;
805 lock (_taintLock)
730 { 806 {
731 iPropertiesNotSupportedDefault++; 807 oldList = _postTaintOperations;
808 _postTaintOperations = new Dictionary<string, TaintCallbackEntry>();
732 } 809 }
733 else if (pbs.PathCurve == (byte)Extrusion.Curve1) 810
811 foreach (KeyValuePair<string,TaintCallbackEntry> kvp in oldList)
734 { 812 {
735 iPropertiesNotSupportedDefault++; 813 try
814 {
815 DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG
816 kvp.Value.callback();
817 }
818 catch (Exception e)
819 {
820 m_log.ErrorFormat("{0}: ProcessPostTaintTaints: {1}: Exception: {2}", LogHeader, kvp.Key, e);
821 }
736 } 822 }
823 oldList.Clear();
737 } 824 }
738 if (iPropertiesNotSupportedDefault == 0)
739 {
740 return false;
741 }
742 */
743 return true;
744 } 825 }
745 826
746 // Calls to the PhysicsActors can't directly call into the physics engine 827 public void PostStepTaintObject(String ident, TaintCallback callback)
747 // because it might be busy. We delay changes to a known time.
748 // We rely on C#'s closure to save and restore the context for the delegate.
749 public void TaintedObject(String ident, TaintCallback callback)
750 { 828 {
751 if (!m_initialized) return; 829 if (!m_initialized) return;
752 830
753 lock (_taintLock) 831 lock (_taintLock)
754 _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); 832 {
833 _postStepOperations.Add(new TaintCallbackEntry(ident, callback));
834 }
835
755 return; 836 return;
756 } 837 }
757 838
758 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues 839 private void ProcessPostStepTaints()
759 // a callback into itself to do the actual property change. That callback is called
760 // here just before the physics engine is called to step the simulation.
761 public void ProcessTaints()
762 { 840 {
763 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process 841 if (_postStepOperations.Count > 0)
764 { 842 {
765 // swizzle a new list into the list location so we can process what's there
766 List<TaintCallbackEntry> oldList; 843 List<TaintCallbackEntry> oldList;
767 lock (_taintLock) 844 lock (_taintLock)
768 { 845 {
769 oldList = _taintedObjects; 846 oldList = _postStepOperations;
770 _taintedObjects = new List<TaintCallbackEntry>(); 847 _postStepOperations = new List<TaintCallbackEntry>();
771 } 848 }
772 849
773 foreach (TaintCallbackEntry tcbe in oldList) 850 foreach (TaintCallbackEntry tcbe in oldList)
774 { 851 {
775 try 852 try
776 { 853 {
854 DetailLog("{0},BSScene.ProcessPostStepTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG
777 tcbe.callback(); 855 tcbe.callback();
778 } 856 }
779 catch (Exception e) 857 catch (Exception e)
780 { 858 {
781 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); 859 m_log.ErrorFormat("{0}: ProcessPostStepTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
782 } 860 }
783 } 861 }
784 oldList.Clear(); 862 oldList.Clear();
785 } 863 }
786 } 864 }
787 865
866 // Only used for debugging. Does not change state of anything so locking is not necessary.
867 public bool AssertInTaintTime(string whereFrom)
868 {
869 if (!InTaintTime)
870 {
871 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
872 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
873 Util.PrintCallStack(); // Prints the stack into the DEBUG log file.
874 }
875 return InTaintTime;
876 }
877
878 #endregion // Taints
879
788 #region Vehicles 880 #region Vehicles
789 881
790 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) 882 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
791 { 883 {
792 if (newType == Vehicle.TYPE_NONE) 884 RemoveVehiclePrim(vehic);
885 if (newType != Vehicle.TYPE_NONE)
793 { 886 {
794 RemoveVehiclePrim(vehic); 887 // make it so the scene will call us each tick to do vehicle things
795 }
796 else
797 {
798 // make it so the scene will call us each tick to do vehicle things
799 AddVehiclePrim(vehic); 888 AddVehiclePrim(vehic);
800 } 889 }
801 } 890 }
@@ -827,21 +916,22 @@ public class BSScene : PhysicsScene, IPhysicsParameters
827 } 916 }
828 917
829 // Some prims have extra vehicle actions 918 // Some prims have extra vehicle actions
830 // no locking because only called when physics engine is not busy 919 // Called at taint time!
831 private void ProcessVehicles(float timeStep) 920 private void ProcessVehicles(float timeStep)
832 { 921 {
833 foreach (BSPrim prim in m_vehicles) 922 foreach (BSPhysObject pobj in m_vehicles)
834 { 923 {
835 prim.StepVehicle(timeStep); 924 pobj.StepVehicle(timeStep);
836 } 925 }
837 } 926 }
838 #endregion Vehicles 927 #endregion Vehicles
839 928
840 #region Parameters 929 #region INI and command line parameter processing
841 930
842 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); 931 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
843 delegate float ParamGet(BSScene scene); 932 delegate float ParamGet(BSScene scene);
844 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); 933 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
934 delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
845 935
846 private struct ParameterDefn 936 private struct ParameterDefn
847 { 937 {
@@ -851,6 +941,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
851 public ParamUser userParam; // get the value from the configuration file 941 public ParamUser userParam; // get the value from the configuration file
852 public ParamGet getter; // return the current value stored for this parameter 942 public ParamGet getter; // return the current value stored for this parameter
853 public ParamSet setter; // set the current value for this parameter 943 public ParamSet setter; // set the current value for this parameter
944 public SetOnObject onObject; // set the value on an object in the physical domain
854 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) 945 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
855 { 946 {
856 name = n; 947 name = n;
@@ -859,6 +950,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
859 userParam = u; 950 userParam = u;
860 getter = g; 951 getter = g;
861 setter = s; 952 setter = s;
953 onObject = null;
954 }
955 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
956 {
957 name = n;
958 desc = d;
959 defaultValue = v;
960 userParam = u;
961 getter = g;
962 setter = s;
963 onObject = o;
862 } 964 }
863 } 965 }
864 966
@@ -869,7 +971,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
869 // getters and setters. 971 // getters and setters.
870 // It is easiest to find an existing definition and copy it. 972 // It is easiest to find an existing definition and copy it.
871 // Parameter values are floats. Booleans are converted to a floating value. 973 // Parameter values are floats. Booleans are converted to a floating value.
872 // 974 //
873 // A ParameterDefn() takes the following parameters: 975 // A ParameterDefn() takes the following parameters:
874 // -- the text name of the parameter. This is used for console input and ini file. 976 // -- the text name of the parameter. This is used for console input and ini file.
875 // -- a short text description of the parameter. This shows up in the console listing. 977 // -- a short text description of the parameter. This shows up in the console listing.
@@ -880,6 +982,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
880 // 982 //
881 // The single letter parameters for the delegates are: 983 // The single letter parameters for the delegates are:
882 // s = BSScene 984 // s = BSScene
985 // o = BSPhysObject
883 // p = string parameter name 986 // p = string parameter name
884 // l = localID of referenced object 987 // l = localID of referenced object
885 // v = float value 988 // v = float value
@@ -888,25 +991,40 @@ public class BSScene : PhysicsScene, IPhysicsParameters
888 { 991 {
889 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", 992 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
890 ConfigurationParameters.numericTrue, 993 ConfigurationParameters.numericTrue,
891 (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, 994 (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
892 (s) => { return s.NumericBool(s._meshSculptedPrim); }, 995 (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); },
893 (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ), 996 (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ),
894 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", 997 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
895 ConfigurationParameters.numericFalse, 998 ConfigurationParameters.numericFalse,
896 (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, 999 (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
897 (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, 1000 (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); },
898 (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), 1001 (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ),
1002 new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
1003 ConfigurationParameters.numericTrue,
1004 (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); },
1005 (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); },
1006 (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ),
899 1007
900 new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 1008 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
901 8f, 1009 8f,
902 (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); }, 1010 (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); },
903 (s) => { return (float)s.m_meshLOD; }, 1011 (s) => { return s.MeshLOD; },
904 (s,p,l,v) => { s.m_meshLOD = (int)v; } ), 1012 (s,p,l,v) => { s.MeshLOD = v; } ),
905 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", 1013 new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
1014 16f,
1015 (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
1016 (s) => { return s.MeshMegaPrimLOD; },
1017 (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ),
1018 new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
1019 10f,
1020 (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
1021 (s) => { return s.MeshMegaPrimThreshold; },
1022 (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ),
1023 new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
906 32f, 1024 32f,
907 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, 1025 (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); },
908 (s) => { return (float)s.m_sculptLOD; }, 1026 (s) => { return s.SculptLOD; },
909 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), 1027 (s,p,l,v) => { s.SculptLOD = v; } ),
910 1028
911 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", 1029 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
912 10f, 1030 10f,
@@ -928,11 +1046,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters
928 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, 1046 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
929 (s) => { return (float)s.m_maxUpdatesPerFrame; }, 1047 (s) => { return (float)s.m_maxUpdatesPerFrame; },
930 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), 1048 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
1049 new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step",
1050 500f,
1051 (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); },
1052 (s) => { return (float)s.m_taintsToProcessPerStep; },
1053 (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ),
931 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", 1054 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
932 10000.01f, 1055 10000.01f,
933 (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); }, 1056 (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
934 (s) => { return (float)s.m_maximumObjectMass; }, 1057 (s) => { return (float)s.MaximumObjectMass; },
935 (s,p,l,v) => { s.m_maximumObjectMass = v; } ), 1058 (s,p,l,v) => { s.MaximumObjectMass = v; } ),
936 1059
937 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", 1060 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
938 2200f, 1061 2200f,
@@ -969,104 +1092,128 @@ public class BSScene : PhysicsScene, IPhysicsParameters
969 -9.80665f, 1092 -9.80665f,
970 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, 1093 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); },
971 (s) => { return s.m_params[0].gravity; }, 1094 (s) => { return s.m_params[0].gravity; },
972 (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ), 1095 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); },
1096 (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ),
973 1097
974 1098
975 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", 1099 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
976 0f, 1100 0f,
977 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, 1101 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
978 (s) => { return s.m_params[0].linearDamping; }, 1102 (s) => { return s.m_params[0].linearDamping; },
979 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ), 1103 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); },
1104 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, s.m_params[0].angularDamping); } ),
980 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 1105 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
981 0f, 1106 0f,
982 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, 1107 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
983 (s) => { return s.m_params[0].angularDamping; }, 1108 (s) => { return s.m_params[0].angularDamping; },
984 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ), 1109 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); },
1110 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, s.m_params[0].linearDamping, v); } ),
985 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 1111 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
986 0.2f, 1112 0.2f,
987 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, 1113 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
988 (s) => { return s.m_params[0].deactivationTime; }, 1114 (s) => { return s.m_params[0].deactivationTime; },
989 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ), 1115 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); },
1116 (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ),
990 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 1117 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
991 0.8f, 1118 0.8f,
992 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, 1119 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
993 (s) => { return s.m_params[0].linearSleepingThreshold; }, 1120 (s) => { return s.m_params[0].linearSleepingThreshold; },
994 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), 1121 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); },
1122 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
995 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 1123 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
996 1.0f, 1124 1.0f,
997 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, 1125 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
998 (s) => { return s.m_params[0].angularSleepingThreshold; }, 1126 (s) => { return s.m_params[0].angularSleepingThreshold; },
999 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), 1127 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); },
1128 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
1000 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 1129 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
1001 0f, // set to zero to disable 1130 0f, // set to zero to disable
1002 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, 1131 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
1003 (s) => { return s.m_params[0].ccdMotionThreshold; }, 1132 (s) => { return s.m_params[0].ccdMotionThreshold; },
1004 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), 1133 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); },
1134 (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ),
1005 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 1135 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
1006 0f, 1136 0f,
1007 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, 1137 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
1008 (s) => { return s.m_params[0].ccdSweptSphereRadius; }, 1138 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
1009 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), 1139 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); },
1140 (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ),
1010 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 1141 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
1011 0.1f, 1142 0.1f,
1012 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, 1143 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
1013 (s) => { return s.m_params[0].contactProcessingThreshold; }, 1144 (s) => { return s.m_params[0].contactProcessingThreshold; },
1014 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), 1145 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); },
1015 1146 (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ),
1147
1148 new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
1149 (float)BSTerrainPhys.TerrainImplementation.Mesh,
1150 (s,cf,p,v) => { s.m_params[0].terrainImplementation = cf.GetFloat(p,v); },
1151 (s) => { return s.m_params[0].terrainImplementation; },
1152 (s,p,l,v) => { s.m_params[0].terrainImplementation = v; } ),
1016 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 1153 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
1017 0.5f, 1154 0.5f,
1018 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, 1155 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
1019 (s) => { return s.m_params[0].terrainFriction; }, 1156 (s) => { return s.m_params[0].terrainFriction; },
1020 (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ), 1157 (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ),
1021 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , 1158 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
1022 0.8f, 1159 0.8f,
1023 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, 1160 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); },
1024 (s) => { return s.m_params[0].terrainHitFraction; }, 1161 (s) => { return s.m_params[0].terrainHitFraction; },
1025 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ), 1162 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ),
1026 new ParameterDefn("TerrainRestitution", "Bouncyness" , 1163 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
1027 0f, 1164 0f,
1028 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, 1165 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
1029 (s) => { return s.m_params[0].terrainRestitution; }, 1166 (s) => { return s.m_params[0].terrainRestitution; },
1030 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), 1167 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ),
1031 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 1168 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
1032 0.5f, 1169 0.2f,
1033 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, 1170 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
1034 (s) => { return s.m_params[0].avatarFriction; }, 1171 (s) => { return s.m_params[0].avatarFriction; },
1035 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ), 1172 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
1173 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
1174 10f,
1175 (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); },
1176 (s) => { return s.m_params[0].avatarStandingFriction; },
1177 (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ),
1036 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 1178 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
1037 60f, 1179 60f,
1038 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, 1180 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
1039 (s) => { return s.m_params[0].avatarDensity; }, 1181 (s) => { return s.m_params[0].avatarDensity; },
1040 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ), 1182 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ),
1041 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", 1183 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
1042 0f, 1184 0f,
1043 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, 1185 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
1044 (s) => { return s.m_params[0].avatarRestitution; }, 1186 (s) => { return s.m_params[0].avatarRestitution; },
1045 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ), 1187 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ),
1046 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", 1188 new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
1047 0.37f, 1189 0.6f,
1048 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, 1190 (s,cf,p,v) => { s.m_params[0].avatarCapsuleWidth = cf.GetFloat(p, v); },
1049 (s) => { return s.m_params[0].avatarCapsuleRadius; }, 1191 (s) => { return s.m_params[0].avatarCapsuleWidth; },
1050 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), 1192 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleWidth, p, l, v); } ),
1193 new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
1194 0.45f,
1195 (s,cf,p,v) => { s.m_params[0].avatarCapsuleDepth = cf.GetFloat(p, v); },
1196 (s) => { return s.m_params[0].avatarCapsuleDepth; },
1197 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleDepth, p, l, v); } ),
1051 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", 1198 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
1052 1.5f, 1199 1.5f,
1053 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, 1200 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
1054 (s) => { return s.m_params[0].avatarCapsuleHeight; }, 1201 (s) => { return s.m_params[0].avatarCapsuleHeight; },
1055 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), 1202 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
1056 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 1203 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
1057 0.1f, 1204 0.1f,
1058 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, 1205 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
1059 (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, 1206 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
1060 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), 1207 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1061 1208
1062 1209
1063 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", 1210 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
1064 0f, // zero to disable 1211 0f,
1065 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, 1212 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
1066 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, 1213 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
1067 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), 1214 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1068 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", 1215 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
1069 0f, // zero to disable 1216 0f,
1070 (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, 1217 (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
1071 (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; }, 1218 (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
1072 (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ), 1219 (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
@@ -1081,12 +1228,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1081 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; }, 1228 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
1082 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ), 1229 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
1083 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", 1230 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
1084 ConfigurationParameters.numericFalse, 1231 ConfigurationParameters.numericTrue,
1085 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1232 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1086 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, 1233 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
1087 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), 1234 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
1088 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", 1235 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
1089 ConfigurationParameters.numericFalse, 1236 ConfigurationParameters.numericTrue,
1090 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1237 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1091 (s) => { return s.m_params[0].shouldSplitSimulationIslands; }, 1238 (s) => { return s.m_params[0].shouldSplitSimulationIslands; },
1092 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ), 1239 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ),
@@ -1101,6 +1248,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1101 (s) => { return s.m_params[0].numberOfSolverIterations; }, 1248 (s) => { return s.m_params[0].numberOfSolverIterations; },
1102 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), 1249 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ),
1103 1250
1251 new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
1252 (float)BSLinkset.LinksetImplementation.Compound,
1253 (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); },
1254 (s) => { return s.m_params[0].linksetImplementation; },
1255 (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ),
1104 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", 1256 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
1105 ConfigurationParameters.numericFalse, 1257 ConfigurationParameters.numericFalse,
1106 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1258 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
@@ -1121,28 +1273,27 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1121 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, 1273 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1122 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, 1274 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1123 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), 1275 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1124 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0", 1276 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
1125 0.0f, 1277 0.1f,
1126 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, 1278 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
1127 (s) => { return s.m_params[0].linkConstraintCFM; }, 1279 (s) => { return s.m_params[0].linkConstraintCFM; },
1128 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), 1280 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
1129 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", 1281 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
1130 0.2f, 1282 0.1f,
1131 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, 1283 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
1132 (s) => { return s.m_params[0].linkConstraintERP; }, 1284 (s) => { return s.m_params[0].linkConstraintERP; },
1133 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), 1285 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
1286 new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
1287 40,
1288 (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); },
1289 (s) => { return s.m_params[0].linkConstraintSolverIterations; },
1290 (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
1134 1291
1135 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", 1292 new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)",
1136 0f, 1293 0f,
1137 (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, 1294 (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); },
1138 (s) => { return (float)s.m_detailedStatsStep; }, 1295 (s) => { return (float)s.m_params[0].physicsLoggingFrames; },
1139 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), 1296 (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ),
1140 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
1141 ConfigurationParameters.numericFalse,
1142 (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
1143 (s) => { return s.NumericBool(s.ShouldDebugLog); },
1144 (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ),
1145
1146 }; 1297 };
1147 1298
1148 // Convert a boolean to our numeric true and false values 1299 // Convert a boolean to our numeric true and false values
@@ -1200,11 +1351,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1200 1351
1201 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; 1352 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
1202 1353
1354 // This creates an array in the correct format for returning the list of
1355 // parameters. This is used by the 'list' option of the 'physics' command.
1203 private void BuildParameterTable() 1356 private void BuildParameterTable()
1204 { 1357 {
1205 if (SettableParameters.Length < ParameterDefinitions.Length) 1358 if (SettableParameters.Length < ParameterDefinitions.Length)
1206 { 1359 {
1207
1208 List<PhysParameterEntry> entries = new List<PhysParameterEntry>(); 1360 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
1209 for (int ii = 0; ii < ParameterDefinitions.Length; ii++) 1361 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
1210 { 1362 {
@@ -1249,60 +1401,54 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1249 return ret; 1401 return ret;
1250 } 1402 }
1251 1403
1252 // check to see if we are updating a parameter for a particular or all of the prims
1253 protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val)
1254 {
1255 List<uint> operateOn;
1256 lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
1257 UpdateParameterSet(operateOn, ref loc, parm, localID, val);
1258 }
1259
1260 // check to see if we are updating a parameter for a particular or all of the avatars
1261 protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
1262 {
1263 List<uint> operateOn;
1264 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys);
1265 UpdateParameterSet(operateOn, ref loc, parm, localID, val);
1266 }
1267
1268 // update all the localIDs specified 1404 // update all the localIDs specified
1269 // If the local ID is APPLY_TO_NONE, just change the default value 1405 // If the local ID is APPLY_TO_NONE, just change the default value
1270 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs 1406 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
1271 // If the localID is a specific object, apply the parameter change to only that object 1407 // If the localID is a specific object, apply the parameter change to only that object
1272 protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val) 1408 private void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val)
1273 { 1409 {
1410 List<uint> objectIDs = new List<uint>();
1274 switch (localID) 1411 switch (localID)
1275 { 1412 {
1276 case PhysParameterEntry.APPLY_TO_NONE: 1413 case PhysParameterEntry.APPLY_TO_NONE:
1277 defaultLoc = val; // setting only the default value 1414 defaultLoc = val; // setting only the default value
1415 // This will cause a call into the physical world if some operation is specified (SetOnObject).
1416 objectIDs.Add(TERRAIN_ID);
1417 TaintedUpdateParameter(parm, objectIDs, val);
1278 break; 1418 break;
1279 case PhysParameterEntry.APPLY_TO_ALL: 1419 case PhysParameterEntry.APPLY_TO_ALL:
1280 defaultLoc = val; // setting ALL also sets the default value 1420 defaultLoc = val; // setting ALL also sets the default value
1281 List<uint> objectIDs = lIDs; 1421 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
1282 string xparm = parm.ToLower(); 1422 TaintedUpdateParameter(parm, objectIDs, val);
1283 float xval = val;
1284 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1285 foreach (uint lID in objectIDs)
1286 {
1287 BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval);
1288 }
1289 });
1290 break; 1423 break;
1291 default: 1424 default:
1292 // setting only one localID 1425 // setting only one localID
1293 TaintedUpdateParameter(parm, localID, val); 1426 objectIDs.Add(localID);
1427 TaintedUpdateParameter(parm, objectIDs, val);
1294 break; 1428 break;
1295 } 1429 }
1296 } 1430 }
1297 1431
1298 // schedule the actual updating of the paramter to when the phys engine is not busy 1432 // schedule the actual updating of the paramter to when the phys engine is not busy
1299 protected void TaintedUpdateParameter(string parm, uint localID, float val) 1433 private void TaintedUpdateParameter(string parm, List<uint> lIDs, float val)
1300 { 1434 {
1301 uint xlocalID = localID;
1302 string xparm = parm.ToLower();
1303 float xval = val; 1435 float xval = val;
1304 TaintedObject("BSScene.TaintedUpdateParameter", delegate() { 1436 List<uint> xlIDs = lIDs;
1305 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); 1437 string xparm = parm;
1438 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1439 ParameterDefn thisParam;
1440 if (TryGetParameter(xparm, out thisParam))
1441 {
1442 if (thisParam.onObject != null)
1443 {
1444 foreach (uint lID in xlIDs)
1445 {
1446 BSPhysObject theObject = null;
1447 PhysObjects.TryGetValue(lID, out theObject);
1448 thisParam.onObject(this, theObject, xval);
1449 }
1450 }
1451 }
1306 }); 1452 });
1307 } 1453 }
1308 1454
@@ -1326,12 +1472,24 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1326 1472
1327 #endregion Runtime settable parameters 1473 #endregion Runtime settable parameters
1328 1474
1475 // Debugging routine for dumping detailed physical information for vehicle prims
1476 private void DumpVehicles()
1477 {
1478 foreach (BSPrim prim in m_vehicles)
1479 {
1480 BulletSimAPI.DumpRigidBody2(World.ptr, prim.PhysBody.ptr);
1481 BulletSimAPI.DumpCollisionShape2(World.ptr, prim.PhysShape.ptr);
1482 }
1483 }
1484
1329 // Invoke the detailed logger and output something if it's enabled. 1485 // Invoke the detailed logger and output something if it's enabled.
1330 public void DetailLog(string msg, params Object[] args) 1486 public void DetailLog(string msg, params Object[] args)
1331 { 1487 {
1332 PhysicsLogging.Write(msg, args); 1488 PhysicsLogging.Write(msg, args);
1489 // Add the Flush() if debugging crashes. Gets all the messages written out.
1490 // PhysicsLogging.Flush();
1333 } 1491 }
1334 // used to fill in the LocalID when there isn't one 1492 // Used to fill in the LocalID when there isn't one. It's the correct number of characters.
1335 public const string DetailLogZero = "0000000000"; 1493 public const string DetailLogZero = "0000000000";
1336 1494
1337} 1495}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
new file mode 100755
index 0000000..892c34b
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -0,0 +1,1001 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OMV = OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Region.Physics.Manager;
33using OpenSim.Region.Physics.ConvexDecompositionDotNet;
34
35namespace OpenSim.Region.Physics.BulletSPlugin
36{
37public sealed class BSShapeCollection : IDisposable
38{
39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
40
41 private BSScene PhysicsScene { get; set; }
42
43 private Object m_collectionActivityLock = new Object();
44
45 // Description of a Mesh
46 private struct MeshDesc
47 {
48 public IntPtr ptr;
49 public int referenceCount;
50 public DateTime lastReferenced;
51 public UInt64 shapeKey;
52 }
53
54 // Description of a hull.
55 // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations.
56 private struct HullDesc
57 {
58 public IntPtr ptr;
59 public int referenceCount;
60 public DateTime lastReferenced;
61 public UInt64 shapeKey;
62 }
63
64 // The sharable set of meshes and hulls. Indexed by their shape hash.
65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
67
68 public BSShapeCollection(BSScene physScene)
69 {
70 PhysicsScene = physScene;
71 }
72
73 public void Dispose()
74 {
75 // TODO!!!!!!!!!
76 }
77
78 // Callbacks called just before either the body or shape is destroyed.
79 // Mostly used for changing bodies out from under Linksets.
80 // Useful for other cases where parameters need saving.
81 // Passing 'null' says no callback.
82 public delegate void ShapeDestructionCallback(BulletShape shape);
83 public delegate void BodyDestructionCallback(BulletBody body);
84
85 // Called to update/change the body and shape for an object.
86 // First checks the shape and updates that if necessary then makes
87 // sure the body is of the right type.
88 // Return 'true' if either the body or the shape changed.
89 // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before
90 // the current shape or body is destroyed. This allows the caller to remove any
91 // higher level dependencies on the shape or body. Mostly used for LinkSets to
92 // remove the physical constraints before the body is destroyed.
93 // Called at taint-time!!
94 public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim,
95 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
96 {
97 PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
98
99 bool ret = false;
100
101 // This lock could probably be pushed down lower but building shouldn't take long
102 lock (m_collectionActivityLock)
103 {
104 // Do we have the correct geometry for this type of object?
105 // Updates prim.BSShape with information/pointers to shape.
106 // Returns 'true' of BSShape is changed to a new shape.
107 bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback);
108 // If we had to select a new shape geometry for the object,
109 // rebuild the body around it.
110 // Updates prim.BSBody with information/pointers to requested body
111 // Returns 'true' if BSBody was changed.
112 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World,
113 prim.PhysShape, bodyCallback);
114 ret = newGeom || newBody;
115 }
116 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}",
117 prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape);
118
119 return ret;
120 }
121
122 // Track another user of a body.
123 // We presume the caller has allocated the body.
124 // Bodies only have one user so the body is just put into the world if not already there.
125 public void ReferenceBody(BulletBody body, bool inTaintTime)
126 {
127 lock (m_collectionActivityLock)
128 {
129 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
130 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate()
131 {
132 if (!BulletSimAPI.IsInWorld2(body.ptr))
133 {
134 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
135 DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
136 }
137 });
138 }
139 }
140
141 // Release the usage of a body.
142 // Called when releasing use of a BSBody. BSShape is handled separately.
143 public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback )
144 {
145 if (body.ptr == IntPtr.Zero)
146 return;
147
148 lock (m_collectionActivityLock)
149 {
150 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate()
151 {
152 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}",
153 body.ID, body, inTaintTime);
154 // If the caller needs to know the old body is going away, pass the event up.
155 if (bodyCallback != null) bodyCallback(body);
156
157 if (BulletSimAPI.IsInWorld2(body.ptr))
158 {
159 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
160 DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
161 }
162
163 // Zero any reference to the shape so it is not freed when the body is deleted.
164 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
165 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr);
166 });
167 }
168 }
169
170 // Track the datastructures and use count for a shape.
171 // When creating a hull, this is called first to reference the mesh
172 // and then again to reference the hull.
173 // Meshes and hulls for the same shape have the same hash key.
174 // NOTE that native shapes are not added to the mesh list or removed.
175 // Returns 'true' if this is the initial reference to the shape. Otherwise reused.
176 public bool ReferenceShape(BulletShape shape)
177 {
178 bool ret = false;
179 switch (shape.type)
180 {
181 case BSPhysicsShapeType.SHAPE_MESH:
182 MeshDesc meshDesc;
183 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
184 {
185 // There is an existing instance of this mesh.
186 meshDesc.referenceCount++;
187 DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
188 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
189 }
190 else
191 {
192 // This is a new reference to a mesh
193 meshDesc.ptr = shape.ptr;
194 meshDesc.shapeKey = shape.shapeKey;
195 // We keep a reference to the underlying IMesh data so a hull can be built
196 meshDesc.referenceCount = 1;
197 DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
198 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
199 ret = true;
200 }
201 meshDesc.lastReferenced = System.DateTime.Now;
202 Meshes[shape.shapeKey] = meshDesc;
203 break;
204 case BSPhysicsShapeType.SHAPE_HULL:
205 HullDesc hullDesc;
206 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
207 {
208 // There is an existing instance of this hull.
209 hullDesc.referenceCount++;
210 DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
211 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
212 }
213 else
214 {
215 // This is a new reference to a hull
216 hullDesc.ptr = shape.ptr;
217 hullDesc.shapeKey = shape.shapeKey;
218 hullDesc.referenceCount = 1;
219 DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
220 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
221 ret = true;
222
223 }
224 hullDesc.lastReferenced = System.DateTime.Now;
225 Hulls[shape.shapeKey] = hullDesc;
226 break;
227 case BSPhysicsShapeType.SHAPE_UNKNOWN:
228 break;
229 default:
230 // Native shapes are not tracked and they don't go into any list
231 break;
232 }
233 return ret;
234 }
235
236 // Release the usage of a shape.
237 public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
238 {
239 if (shape.ptr == IntPtr.Zero)
240 return;
241
242 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate()
243 {
244 if (shape.ptr != IntPtr.Zero)
245 {
246 if (shape.isNativeShape)
247 {
248 // Native shapes are not tracked and are released immediately
249 DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
250 BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime);
251 if (shapeCallback != null) shapeCallback(shape);
252 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
253 }
254 else
255 {
256 switch (shape.type)
257 {
258 case BSPhysicsShapeType.SHAPE_HULL:
259 DereferenceHull(shape, shapeCallback);
260 break;
261 case BSPhysicsShapeType.SHAPE_MESH:
262 DereferenceMesh(shape, shapeCallback);
263 break;
264 case BSPhysicsShapeType.SHAPE_COMPOUND:
265 DereferenceCompound(shape, shapeCallback);
266 break;
267 case BSPhysicsShapeType.SHAPE_UNKNOWN:
268 break;
269 default:
270 break;
271 }
272 }
273 }
274 });
275 }
276
277 // Count down the reference count for a mesh shape
278 // Called at taint-time.
279 private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback)
280 {
281 MeshDesc meshDesc;
282 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
283 {
284 meshDesc.referenceCount--;
285 // TODO: release the Bullet storage
286 if (shapeCallback != null) shapeCallback(shape);
287 meshDesc.lastReferenced = System.DateTime.Now;
288 Meshes[shape.shapeKey] = meshDesc;
289 DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
290 BSScene.DetailLogZero, shape, meshDesc.referenceCount);
291
292 }
293 }
294
295 // Count down the reference count for a hull shape
296 // Called at taint-time.
297 private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback)
298 {
299 HullDesc hullDesc;
300 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
301 {
302 hullDesc.referenceCount--;
303 // TODO: release the Bullet storage (aging old entries?)
304
305 // Tell upper layers that, if they have dependencies on this shape, this link is going away
306 if (shapeCallback != null) shapeCallback(shape);
307
308 hullDesc.lastReferenced = System.DateTime.Now;
309 Hulls[shape.shapeKey] = hullDesc;
310 DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
311 BSScene.DetailLogZero, shape, hullDesc.referenceCount);
312 }
313 }
314
315 // Remove a reference to a compound shape.
316 // Taking a compound shape apart is a little tricky because if you just delete the
317 // physical shape, it will free all the underlying children. We can't do that because
318 // they could be shared. So, this removes each of the children from the compound and
319 // dereferences them separately before destroying the compound collision object itself.
320 // Called at taint-time.
321 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback)
322 {
323 if (!BulletSimAPI.IsCompound2(shape.ptr))
324 {
325 // Failed the sanity check!!
326 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
327 LogHeader, shape.type, shape.ptr.ToString("X"));
328 DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
329 BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X"));
330 return;
331 }
332
333 int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr);
334 DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
335
336 for (int ii = numChildren - 1; ii >= 0; ii--)
337 {
338 IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii);
339 DereferenceAnonCollisionShape(childShape);
340 }
341 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
342 }
343
344 // Sometimes we have a pointer to a collision shape but don't know what type it is.
345 // Figure out type and call the correct dereference routine.
346 // Called at taint-time.
347 private void DereferenceAnonCollisionShape(IntPtr cShape)
348 {
349 MeshDesc meshDesc;
350 HullDesc hullDesc;
351
352 BulletShape shapeInfo = new BulletShape(cShape);
353 if (TryGetMeshByPtr(cShape, out meshDesc))
354 {
355 shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH;
356 shapeInfo.shapeKey = meshDesc.shapeKey;
357 }
358 else
359 {
360 if (TryGetHullByPtr(cShape, out hullDesc))
361 {
362 shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL;
363 shapeInfo.shapeKey = hullDesc.shapeKey;
364 }
365 else
366 {
367 if (BulletSimAPI.IsCompound2(cShape))
368 {
369 shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND;
370 }
371 else
372 {
373 if (BulletSimAPI.IsNativeShape2(cShape))
374 {
375 shapeInfo.isNativeShape = true;
376 shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
377 }
378 }
379 }
380 }
381
382 DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
383
384 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
385 {
386 DereferenceShape(shapeInfo, true, null);
387 }
388 else
389 {
390 PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}",
391 LogHeader, PhysicsScene.RegionName, cShape.ToString("X"));
392 }
393 }
394
395 // Create the geometry information in Bullet for later use.
396 // The objects needs a hull if it's physical otherwise a mesh is enough.
397 // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls,
398 // shared geometries will be used. If the parameters of the existing shape are the same
399 // as this request, the shape is not rebuilt.
400 // Info in prim.BSShape is updated to the new shape.
401 // Returns 'true' if the geometry was rebuilt.
402 // Called at taint-time!
403 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
404 {
405 bool ret = false;
406 bool haveShape = false;
407
408 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
409 {
410 // an avatar capsule is close to a native shape (it is not shared)
411 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE,
412 FixedShapeKey.KEY_CAPSULE, shapeCallback);
413 DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
414 ret = true;
415 haveShape = true;
416 }
417
418 // Compound shapes are handled special as they are rebuilt from scratch.
419 // This isn't too great a hardship since most of the child shapes will already been created.
420 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
421 {
422 ret = GetReferenceToCompoundShape(prim, shapeCallback);
423 DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
424 haveShape = true;
425 }
426
427 if (!haveShape)
428 {
429 ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback);
430 }
431
432 return ret;
433 }
434
435 // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'.
436 private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
437 {
438 bool ret = false;
439 bool haveShape = false;
440 bool nativeShapePossible = true;
441 PrimitiveBaseShape pbs = prim.BaseShape;
442
443 // If the prim attributes are simple, this could be a simple Bullet native shape
444 if (!haveShape
445 && pbs != null
446 && nativeShapePossible
447 && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim)
448 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
449 && pbs.ProfileHollow == 0
450 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
451 && pbs.PathBegin == 0 && pbs.PathEnd == 0
452 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
453 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
454 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
455 {
456 // It doesn't look like Bullet scales spheres so make sure the scales are all equal
457 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
458 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
459 {
460 haveShape = true;
461 if (forceRebuild
462 || prim.Scale != prim.Size
463 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE
464 )
465 {
466 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE,
467 FixedShapeKey.KEY_SPHERE, shapeCallback);
468 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
469 prim.LocalID, forceRebuild, prim.PhysShape);
470 }
471 }
472 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
473 {
474 haveShape = true;
475 if (forceRebuild
476 || prim.Scale != prim.Size
477 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX
478 )
479 {
480 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX,
481 FixedShapeKey.KEY_BOX, shapeCallback);
482 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
483 prim.LocalID, forceRebuild, prim.PhysShape);
484 }
485 }
486 }
487
488 // If a simple shape is not happening, create a mesh and possibly a hull.
489 if (!haveShape && pbs != null)
490 {
491 ret = CreateGeomMeshOrHull(prim, shapeCallback);
492 }
493
494 return ret;
495 }
496
497 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
498 {
499
500 bool ret = false;
501 // Note that if it's a native shape, the check for physical/non-physical is not
502 // made. Native shapes work in either case.
503 if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects)
504 {
505 // Update prim.BSShape to reference a hull of this shape.
506 ret = GetReferenceToHull(prim,shapeCallback);
507 DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
508 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
509 }
510 else
511 {
512 ret = GetReferenceToMesh(prim, shapeCallback);
513 DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
514 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
515 }
516 return ret;
517 }
518
519 // Creates a native shape and assignes it to prim.BSShape.
520 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape().
521 private bool GetReferenceToNativeShape(BSPhysObject prim,
522 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey,
523 ShapeDestructionCallback shapeCallback)
524 {
525 // release any previous shape
526 DereferenceShape(prim.PhysShape, true, shapeCallback);
527
528 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
529
530 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
531 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
532 prim.LocalID, newShape, prim.Scale);
533
534 prim.PhysShape = newShape;
535 return true;
536 }
537
538 private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType,
539 FixedShapeKey shapeKey)
540 {
541 BulletShape newShape;
542 // Need to make sure the passed shape information is for the native type.
543 ShapeData nativeShapeData = new ShapeData();
544 nativeShapeData.Type = shapeType;
545 nativeShapeData.ID = prim.LocalID;
546 nativeShapeData.Scale = prim.Scale;
547 nativeShapeData.Size = prim.Scale; // unneeded, I think.
548 nativeShapeData.MeshKey = (ulong)shapeKey;
549 nativeShapeData.HullKey = (ulong)shapeKey;
550
551 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
552 {
553 // The proper scale has been calculated in the prim.
554 newShape = new BulletShape(
555 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale)
556 , shapeType);
557 DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
558 }
559 else
560 {
561 // Native shapes are scaled in Bullet so set the scaling to the size
562 prim.Scale = prim.Size;
563 nativeShapeData.Scale = prim.Scale;
564 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType);
565 }
566 if (newShape.ptr == IntPtr.Zero)
567 {
568 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
569 LogHeader, prim.LocalID, shapeType);
570 }
571 newShape.shapeKey = (System.UInt64)shapeKey;
572 newShape.isNativeShape = true;
573
574 return newShape;
575 }
576
577 // Builds a mesh shape in the physical world and updates prim.BSShape.
578 // Dereferences previous shape in BSShape and adds a reference for this new shape.
579 // Returns 'true' of a mesh was actually built. Otherwise .
580 // Called at taint-time!
581 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
582 {
583 BulletShape newShape = new BulletShape(IntPtr.Zero);
584
585 float lod;
586 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
587
588 // if this new shape is the same as last time, don't recreate the mesh
589 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
590 return false;
591
592 DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}",
593 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
594
595 // Since we're recreating new, get rid of the reference to the previous shape
596 DereferenceShape(prim.PhysShape, true, shapeCallback);
597
598 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod);
599 // Take evasive action if the mesh was not constructed.
600 newShape = VerifyMeshCreated(newShape, prim);
601
602 ReferenceShape(newShape);
603
604 // meshes are already scaled by the meshmerizer
605 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
606 prim.PhysShape = newShape;
607
608 return true; // 'true' means a new shape has been added to this prim
609 }
610
611 private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
612 {
613 IMesh meshData = null;
614 IntPtr meshPtr = IntPtr.Zero;
615 MeshDesc meshDesc;
616 if (Meshes.TryGetValue(newMeshKey, out meshDesc))
617 {
618 // If the mesh has already been built just use it.
619 meshPtr = meshDesc.ptr;
620 }
621 else
622 {
623 // Pass false for physicalness as this creates some sort of bounding box which we don't need
624 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
625
626 if (meshData != null)
627 {
628 int[] indices = meshData.getIndexListAsInt();
629 List<OMV.Vector3> vertices = meshData.getVertexList();
630
631 float[] verticesAsFloats = new float[vertices.Count * 3];
632 int vi = 0;
633 foreach (OMV.Vector3 vv in vertices)
634 {
635 verticesAsFloats[vi++] = vv.X;
636 verticesAsFloats[vi++] = vv.Y;
637 verticesAsFloats[vi++] = vv.Z;
638 }
639
640 // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
641 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
642
643 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
644 indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
645 }
646 }
647 BulletShape newShape = new BulletShape(meshPtr, BSPhysicsShapeType.SHAPE_MESH);
648 newShape.shapeKey = newMeshKey;
649
650 return newShape;
651 }
652
653 // See that hull shape exists in the physical world and update prim.BSShape.
654 // We could be creating the hull because scale changed or whatever.
655 private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
656 {
657 BulletShape newShape;
658
659 float lod;
660 System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
661
662 // if the hull hasn't changed, don't rebuild it
663 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
664 return false;
665
666 DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
667 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
668
669 // Remove usage of the previous shape.
670 DereferenceShape(prim.PhysShape, true, shapeCallback);
671
672 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
673 newShape = VerifyMeshCreated(newShape, prim);
674
675 ReferenceShape(newShape);
676
677 // hulls are already scaled by the meshmerizer
678 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
679 prim.PhysShape = newShape;
680 return true; // 'true' means a new shape has been added to this prim
681 }
682
683 List<ConvexResult> m_hulls;
684 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
685 {
686
687 IntPtr hullPtr = IntPtr.Zero;
688 HullDesc hullDesc;
689 if (Hulls.TryGetValue(newHullKey, out hullDesc))
690 {
691 // If the hull shape already is created, just use it.
692 hullPtr = hullDesc.ptr;
693 }
694 else
695 {
696 // Build a new hull in the physical world
697 // Pass false for physicalness as this creates some sort of bounding box which we don't need
698 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
699 if (meshData != null)
700 {
701
702 int[] indices = meshData.getIndexListAsInt();
703 List<OMV.Vector3> vertices = meshData.getVertexList();
704
705 //format conversion from IMesh format to DecompDesc format
706 List<int> convIndices = new List<int>();
707 List<float3> convVertices = new List<float3>();
708 for (int ii = 0; ii < indices.GetLength(0); ii++)
709 {
710 convIndices.Add(indices[ii]);
711 }
712 foreach (OMV.Vector3 vv in vertices)
713 {
714 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
715 }
716
717 // setup and do convex hull conversion
718 m_hulls = new List<ConvexResult>();
719 DecompDesc dcomp = new DecompDesc();
720 dcomp.mIndices = convIndices;
721 dcomp.mVertices = convVertices;
722 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
723 // create the hull into the _hulls variable
724 convexBuilder.process(dcomp);
725
726 // Convert the vertices and indices for passing to unmanaged.
727 // The hull information is passed as a large floating point array.
728 // The format is:
729 // convHulls[0] = number of hulls
730 // convHulls[1] = number of vertices in first hull
731 // convHulls[2] = hull centroid X coordinate
732 // convHulls[3] = hull centroid Y coordinate
733 // convHulls[4] = hull centroid Z coordinate
734 // convHulls[5] = first hull vertex X
735 // convHulls[6] = first hull vertex Y
736 // convHulls[7] = first hull vertex Z
737 // convHulls[8] = second hull vertex X
738 // ...
739 // convHulls[n] = number of vertices in second hull
740 // convHulls[n+1] = second hull centroid X coordinate
741 // ...
742 //
743 // TODO: is is very inefficient. Someday change the convex hull generator to return
744 // data structures that do not need to be converted in order to pass to Bullet.
745 // And maybe put the values directly into pinned memory rather than marshaling.
746 int hullCount = m_hulls.Count;
747 int totalVertices = 1; // include one for the count of the hulls
748 foreach (ConvexResult cr in m_hulls)
749 {
750 totalVertices += 4; // add four for the vertex count and centroid
751 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
752 }
753 float[] convHulls = new float[totalVertices];
754
755 convHulls[0] = (float)hullCount;
756 int jj = 1;
757 foreach (ConvexResult cr in m_hulls)
758 {
759 // copy vertices for index access
760 float3[] verts = new float3[cr.HullVertices.Count];
761 int kk = 0;
762 foreach (float3 ff in cr.HullVertices)
763 {
764 verts[kk++] = ff;
765 }
766
767 // add to the array one hull's worth of data
768 convHulls[jj++] = cr.HullIndices.Count;
769 convHulls[jj++] = 0f; // centroid x,y,z
770 convHulls[jj++] = 0f;
771 convHulls[jj++] = 0f;
772 foreach (int ind in cr.HullIndices)
773 {
774 convHulls[jj++] = verts[ind].x;
775 convHulls[jj++] = verts[ind].y;
776 convHulls[jj++] = verts[ind].z;
777 }
778 }
779 // create the hull data structure in Bullet
780 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls);
781 }
782 }
783
784 BulletShape newShape = new BulletShape(hullPtr, BSPhysicsShapeType.SHAPE_HULL);
785 newShape.shapeKey = newHullKey;
786
787 return newShape; // 'true' means a new shape has been added to this prim
788 }
789
790 // Callback from convex hull creater with a newly created hull.
791 // Just add it to our collection of hulls for this shape.
792 private void HullReturn(ConvexResult result)
793 {
794 m_hulls.Add(result);
795 return;
796 }
797
798 // Compound shapes are always built from scratch.
799 // This shouldn't be to bad since most of the parts will be meshes that had been built previously.
800 private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
801 {
802 // Remove reference to the old shape
803 // Don't need to do this as the shape is freed when the new root shape is created below.
804 // DereferenceShape(prim.PhysShape, true, shapeCallback);
805
806 BulletShape cShape = new BulletShape(
807 BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), BSPhysicsShapeType.SHAPE_COMPOUND);
808
809 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
810 CreateGeomMeshOrHull(prim, shapeCallback);
811 BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity);
812 DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
813 prim.LocalID, cShape, prim.PhysShape);
814
815 prim.PhysShape = cShape;
816
817 return true;
818 }
819
820 // Create a hash of all the shape parameters to be used as a key
821 // for this particular shape.
822 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
823 {
824 // level of detail based on size and type of the object
825 float lod = PhysicsScene.MeshLOD;
826 if (pbs.SculptEntry)
827 lod = PhysicsScene.SculptLOD;
828
829 // Mega prims usually get more detail because one can interact with shape approximations at this size.
830 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
831 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
832 lod = PhysicsScene.MeshMegaPrimLOD;
833
834 retLod = lod;
835 return pbs.GetMeshKey(size, lod);
836 }
837 // For those who don't want the LOD
838 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
839 {
840 float lod;
841 return ComputeShapeKey(size, pbs, out lod);
842 }
843
844 // The creation of a mesh or hull can fail if an underlying asset is not available.
845 // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
846 // and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
847 // The first case causes the asset to be fetched. The second case requires
848 // us to not loop forever.
849 // Called after creating a physical mesh or hull. If the physical shape was created,
850 // just return.
851 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
852 {
853 // If the shape was successfully created, nothing more to do
854 if (newShape.ptr != IntPtr.Zero)
855 return newShape;
856
857 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
858 if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero)
859 {
860 prim.LastAssetBuildFailed = true;
861 BSPhysObject xprim = prim;
862 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}",
863 LogHeader, prim.LocalID, prim.LastAssetBuildFailed);
864 Util.FireAndForget(delegate
865 {
866 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
867 if (assetProvider != null)
868 {
869 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
870 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
871 {
872 if (!yprim.BaseShape.SculptEntry)
873 return;
874 if (yprim.BaseShape.SculptTexture.ToString() != asset.ID)
875 return;
876
877 yprim.BaseShape.SculptData = asset.Data;
878 // This will cause the prim to see that the filler shape is not the right
879 // one and try again to build the object.
880 // No race condition with the normal shape setting since the rebuild is at taint time.
881 yprim.ForceBodyShapeRebuild(false);
882
883 });
884 }
885 });
886 }
887 else
888 {
889 if (prim.LastAssetBuildFailed)
890 {
891 PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}",
892 LogHeader, prim.LocalID, prim.BaseShape.SculptTexture);
893 }
894 }
895
896 // While we figure out the real problem, stick a simple native shape on the object.
897 BulletShape fillinShape =
898 BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
899
900 return fillinShape;
901 }
902
903 // Create a body object in Bullet.
904 // Updates prim.BSBody with the information about the new body if one is created.
905 // Returns 'true' if an object was actually created.
906 // Called at taint-time.
907 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape,
908 BodyDestructionCallback bodyCallback)
909 {
910 bool ret = false;
911
912 // the mesh, hull or native shape must have already been created in Bullet
913 bool mustRebuild = (prim.PhysBody.ptr == IntPtr.Zero);
914
915 // If there is an existing body, verify it's of an acceptable type.
916 // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
917 if (!mustRebuild)
918 {
919 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.PhysBody.ptr);
920 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY
921 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT)
922 {
923 // If the collisionObject is not the correct type for solidness, rebuild what's there
924 mustRebuild = true;
925 }
926 }
927
928 if (mustRebuild || forceRebuild)
929 {
930 // Free any old body
931 DereferenceBody(prim.PhysBody, true, bodyCallback);
932
933 BulletBody aBody;
934 IntPtr bodyPtr = IntPtr.Zero;
935 if (prim.IsSolid)
936 {
937 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
938 prim.LocalID, prim.RawPosition, prim.RawOrientation);
939 DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
940 }
941 else
942 {
943 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
944 prim.LocalID, prim.RawPosition, prim.RawOrientation);
945 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
946 }
947 aBody = new BulletBody(prim.LocalID, bodyPtr);
948
949 ReferenceBody(aBody, true);
950
951 prim.PhysBody = aBody;
952
953 ret = true;
954 }
955
956 return ret;
957 }
958
959 private bool TryGetMeshByPtr(IntPtr addr, out MeshDesc outDesc)
960 {
961 bool ret = false;
962 MeshDesc foundDesc = new MeshDesc();
963 foreach (MeshDesc md in Meshes.Values)
964 {
965 if (md.ptr == addr)
966 {
967 foundDesc = md;
968 ret = true;
969 break;
970 }
971
972 }
973 outDesc = foundDesc;
974 return ret;
975 }
976
977 private bool TryGetHullByPtr(IntPtr addr, out HullDesc outDesc)
978 {
979 bool ret = false;
980 HullDesc foundDesc = new HullDesc();
981 foreach (HullDesc hd in Hulls.Values)
982 {
983 if (hd.ptr == addr)
984 {
985 foundDesc = hd;
986 ret = true;
987 break;
988 }
989
990 }
991 outDesc = foundDesc;
992 return ret;
993 }
994
995 private void DetailLog(string msg, params Object[] args)
996 {
997 if (PhysicsScene.PhysicsLogging.Enabled)
998 PhysicsScene.DetailLog(msg, args);
999 }
1000}
1001}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
new file mode 100755
index 0000000..96cd55e
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -0,0 +1,208 @@
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
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35public abstract class BSShape
36{
37 public IntPtr ptr { get; set; }
38 public BSPhysicsShapeType type { get; set; }
39 public System.UInt64 key { get; set; }
40 public int referenceCount { get; set; }
41 public DateTime lastReferenced { get; set; }
42
43 public BSShape()
44 {
45 ptr = IntPtr.Zero;
46 type = BSPhysicsShapeType.SHAPE_UNKNOWN;
47 key = 0;
48 referenceCount = 0;
49 lastReferenced = DateTime.Now;
50 }
51
52 // Get a reference to a physical shape. Create if it doesn't exist
53 public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
54 {
55 BSShape ret = null;
56
57 if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
58 {
59 // an avatar capsule is close to a native shape (it is not shared)
60 ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE,
61 FixedShapeKey.KEY_CAPSULE);
62 physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret);
63 }
64
65 // Compound shapes are handled special as they are rebuilt from scratch.
66 // This isn't too great a hardship since most of the child shapes will already been created.
67 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
68 {
69 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
70 ret = BSShapeCompound.GetReference(prim);
71 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
72 }
73
74 if (ret == null)
75 ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim);
76
77 return ret;
78 }
79 public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
80 {
81 return null;
82 }
83 public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
84 {
85 return null;
86 }
87
88 // Release the use of a physical shape.
89 public abstract void Dereference(BSScene physicsScene);
90
91 // All shapes have a static call to get a reference to the physical shape
92 // protected abstract static BSShape GetReference();
93
94 public override string ToString()
95 {
96 StringBuilder buff = new StringBuilder();
97 buff.Append("<p=");
98 buff.Append(ptr.ToString("X"));
99 buff.Append(",s=");
100 buff.Append(type.ToString());
101 buff.Append(",k=");
102 buff.Append(key.ToString("X"));
103 buff.Append(",c=");
104 buff.Append(referenceCount.ToString());
105 buff.Append(">");
106 return buff.ToString();
107 }
108}
109
110public class BSShapeNull : BSShape
111{
112 public BSShapeNull() : base()
113 {
114 }
115 public static BSShape GetReference() { return new BSShapeNull(); }
116 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ }
117}
118
119public class BSShapeNative : BSShape
120{
121 private static string LogHeader = "[BULLETSIM SHAPE NATIVE]";
122 public BSShapeNative() : base()
123 {
124 }
125 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
126 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
127 {
128 // Native shapes are not shared and are always built anew.
129 return new BSShapeNative(physicsScene, prim, shapeType, shapeKey);
130 }
131
132 private BSShapeNative(BSScene physicsScene, BSPhysObject prim,
133 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
134 {
135 ShapeData nativeShapeData = new ShapeData();
136 nativeShapeData.Type = shapeType;
137 nativeShapeData.ID = prim.LocalID;
138 nativeShapeData.Scale = prim.Scale;
139 nativeShapeData.Size = prim.Scale;
140 nativeShapeData.MeshKey = (ulong)shapeKey;
141 nativeShapeData.HullKey = (ulong)shapeKey;
142
143
144 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
145 {
146 ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale);
147 physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
148 }
149 else
150 {
151 ptr = BulletSimAPI.BuildNativeShape2(physicsScene.World.ptr, nativeShapeData);
152 }
153 if (ptr == IntPtr.Zero)
154 {
155 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
156 LogHeader, prim.LocalID, shapeType);
157 }
158 type = shapeType;
159 key = (UInt64)shapeKey;
160 }
161 // Make this reference to the physical shape go away since native shapes are not shared.
162 public override void Dereference(BSScene physicsScene)
163 {
164 // Native shapes are not tracked and are released immediately
165 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
166 BulletSimAPI.DeleteCollisionShape2(physicsScene.World.ptr, ptr);
167 ptr = IntPtr.Zero;
168 // Garbage collection will free up this instance.
169 }
170}
171
172public class BSShapeMesh : BSShape
173{
174 private static string LogHeader = "[BULLETSIM SHAPE MESH]";
175 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>();
176
177 public BSShapeMesh() : base()
178 {
179 }
180 public static BSShape GetReference() { return new BSShapeNull(); }
181 public override void Dereference(BSScene physicsScene) { }
182}
183
184public class BSShapeHull : BSShape
185{
186 private static string LogHeader = "[BULLETSIM SHAPE HULL]";
187 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
188
189 public BSShapeHull() : base()
190 {
191 }
192 public static BSShape GetReference() { return new BSShapeNull(); }
193 public override void Dereference(BSScene physicsScene) { }
194}
195
196public class BSShapeCompound : BSShape
197{
198 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
199 public BSShapeCompound() : base()
200 {
201 }
202 public static BSShape GetReference(BSPhysObject prim)
203 {
204 return new BSShapeNull();
205 }
206 public override void Dereference(BSScene physicsScene) { }
207}
208}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
new file mode 100755
index 0000000..3ca756c
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
@@ -0,0 +1,170 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework;
33using OpenSim.Region.CoreModules;
34using OpenSim.Region.Physics.Manager;
35
36using Nini.Config;
37using log4net;
38
39using OpenMetaverse;
40
41namespace OpenSim.Region.Physics.BulletSPlugin
42{
43public sealed class BSTerrainHeightmap : BSTerrainPhys
44{
45 static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]";
46
47 BulletHeightMapInfo m_mapInfo = null;
48
49 // Constructor to build a default, flat heightmap terrain.
50 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
51 : base(physicsScene, regionBase, id)
52 {
53 Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE);
54 Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION);
55 int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
56 float[] initialMap = new float[totalHeights];
57 for (int ii = 0; ii < totalHeights; ii++)
58 {
59 initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION;
60 }
61 m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero);
62 m_mapInfo.minCoords = minTerrainCoords;
63 m_mapInfo.maxCoords = maxTerrainCoords;
64 m_mapInfo.terrainRegionBase = TerrainBase;
65 // Don't have to free any previous since we just got here.
66 BuildHeightmapTerrain();
67 }
68
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).
71 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
72 Vector3 minCoords, Vector3 maxCoords)
73 : base(physicsScene, regionBase, id)
74 {
75 m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero);
76 m_mapInfo.minCoords = minCoords;
77 m_mapInfo.maxCoords = maxCoords;
78 m_mapInfo.minZ = minCoords.Z;
79 m_mapInfo.maxZ = maxCoords.Z;
80 m_mapInfo.terrainRegionBase = TerrainBase;
81
82 // Don't have to free any previous since we just got here.
83 BuildHeightmapTerrain();
84 }
85
86 public override void Dispose()
87 {
88 ReleaseHeightMapTerrain();
89 }
90
91 // Using the information in m_mapInfo, create the physical representation of the heightmap.
92 private void BuildHeightmapTerrain()
93 {
94 m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID,
95 m_mapInfo.minCoords, m_mapInfo.maxCoords,
96 m_mapInfo.heightMap, BSTerrainManager.TERRAIN_COLLISION_MARGIN);
97
98 // Create the terrain shape from the mapInfo
99 m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr),
100 BSPhysicsShapeType.SHAPE_TERRAIN);
101
102 // The terrain object initial position is at the center of the object
103 Vector3 centerPos;
104 centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f);
105 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f);
106 centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f);
107
108 m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID,
109 BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr,
110 m_mapInfo.ID, centerPos, Quaternion.Identity));
111
112 // Set current terrain attributes
113 BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction);
114 BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction);
115 BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution);
116 BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
117
118 // Return the new terrain to the world of physical objects
119 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
120
121 // redo its bounding box now that it is in the world
122 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
123
124 BulletSimAPI.SetCollisionFilterMask2(m_mapInfo.terrainBody.ptr,
125 (uint)CollisionFilterGroups.TerrainFilter,
126 (uint)CollisionFilterGroups.TerrainMask);
127
128 // Make it so the terrain will not move or be considered for movement.
129 BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
130
131 return;
132 }
133
134 // If there is information in m_mapInfo pointing to physical structures, release same.
135 private void ReleaseHeightMapTerrain()
136 {
137 if (m_mapInfo != null)
138 {
139 if (m_mapInfo.terrainBody.ptr != IntPtr.Zero)
140 {
141 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
142 // Frees both the body and the shape.
143 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
144 BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr);
145 }
146 }
147 m_mapInfo = null;
148 }
149
150 // The passed position is relative to the base of the region.
151 public override float GetHeightAtXYZ(Vector3 pos)
152 {
153 float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
154
155 int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X;
156 try
157 {
158 ret = m_mapInfo.heightMap[mapIndex];
159 }
160 catch
161 {
162 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
163 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
164 LogHeader, m_mapInfo.terrainRegionBase, pos);
165 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
166 }
167 return ret;
168 }
169}
170}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
new file mode 100755
index 0000000..23fcfd3
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -0,0 +1,419 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework;
33using OpenSim.Region.CoreModules;
34using OpenSim.Region.Physics.Manager;
35
36using Nini.Config;
37using log4net;
38
39using OpenMetaverse;
40
41namespace OpenSim.Region.Physics.BulletSPlugin
42{
43
44// The physical implementation of the terrain is wrapped in this class.
45public abstract class BSTerrainPhys : IDisposable
46{
47 public enum TerrainImplementation
48 {
49 Heightmap = 0,
50 Mesh = 1
51 }
52
53 public BSScene PhysicsScene { get; private set; }
54 // Base of the region in world coordinates. Coordinates inside the region are relative to this.
55 public Vector3 TerrainBase { get; private set; }
56 public uint ID { get; private set; }
57
58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id)
59 {
60 PhysicsScene = physicsScene;
61 TerrainBase = regionBase;
62 ID = id;
63 }
64 public abstract void Dispose();
65 public abstract float GetHeightAtXYZ(Vector3 pos);
66}
67
68// ==========================================================================================
69public sealed class BSTerrainManager
70{
71 static string LogHeader = "[BULLETSIM TERRAIN MANAGER]";
72
73 // These height values are fractional so the odd values will be
74 // noticable when debugging.
75 public const float HEIGHT_INITIALIZATION = 24.987f;
76 public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f;
77 public const float HEIGHT_GETHEIGHT_RET = 24.765f;
78
79 // If the min and max height are equal, we reduce the min by this
80 // amount to make sure that a bounding box is built for the terrain.
81 public const float HEIGHT_EQUAL_FUDGE = 0.2f;
82
83 public const float TERRAIN_COLLISION_MARGIN = 0.0f;
84
85 // Until the whole simulator is changed to pass us the region size, we rely on constants.
86 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
87
88 // The scene that I am part of
89 private BSScene PhysicsScene { get; set; }
90
91 // The ground plane created to keep thing from falling to infinity.
92 private BulletBody m_groundPlane;
93
94 // If doing mega-regions, if we're region zero we will be managing multiple
95 // region terrains since region zero does the physics for the whole mega-region.
96 private Dictionary<Vector3, BSTerrainPhys> m_terrains;
97
98 // Flags used to know when to recalculate the height.
99 private bool m_terrainModified = false;
100
101 // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount.
102 // This is incremented before assigning to new region so it is the last ID allocated.
103 private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1;
104 public uint HighestTerrainID { get {return m_terrainCount; } }
105
106 // If doing mega-regions, this holds our offset from region zero of
107 // the mega-regions. "parentScene" points to the PhysicsScene of region zero.
108 private Vector3 m_worldOffset;
109 // If the parent region (region 0), this is the extent of the combined regions
110 // relative to the origin of region zero
111 private Vector3 m_worldMax;
112 private PhysicsScene MegaRegionParentPhysicsScene { get; set; }
113
114 public BSTerrainManager(BSScene physicsScene)
115 {
116 PhysicsScene = physicsScene;
117 m_terrains = new Dictionary<Vector3,BSTerrainPhys>();
118
119 // Assume one region of default size
120 m_worldOffset = Vector3.Zero;
121 m_worldMax = new Vector3(DefaultRegionSize);
122 MegaRegionParentPhysicsScene = null;
123 }
124
125 // Create the initial instance of terrain and the underlying ground plane.
126 // This is called from the initialization routine so we presume it is
127 // safe to call Bullet in real time. We hope no one is moving prims around yet.
128 public void CreateInitialGroundPlaneAndTerrain()
129 {
130 // The ground plane is here to catch things that are trying to drop to negative infinity
131 BulletShape groundPlaneShape = new BulletShape(
132 BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN),
133 BSPhysicsShapeType.SHAPE_GROUNDPLANE);
134 m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
135 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID,
136 Vector3.Zero, Quaternion.Identity));
137 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr);
138 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr);
139 // Ground plane does not move
140 BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
141 // Everything collides with the ground plane.
142 BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr,
143 (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask);
144
145 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
146 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
147 m_terrains.Add(Vector3.Zero, initialTerrain);
148 }
149
150 // Release all the terrain structures we might have allocated
151 public void ReleaseGroundPlaneAndTerrain()
152 {
153 if (m_groundPlane.ptr != IntPtr.Zero)
154 {
155 if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr))
156 {
157 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr);
158 }
159 m_groundPlane.ptr = IntPtr.Zero;
160 }
161
162 ReleaseTerrain();
163 }
164
165 // Release all the terrain we have allocated
166 public void ReleaseTerrain()
167 {
168 foreach (KeyValuePair<Vector3, BSTerrainPhys> kvp in m_terrains)
169 {
170 kvp.Value.Dispose();
171 }
172 m_terrains.Clear();
173 }
174
175 // The simulator wants to set a new heightmap for the terrain.
176 public void SetTerrain(float[] heightMap) {
177 float[] localHeightMap = heightMap;
178 PhysicsScene.TaintedObject("TerrainManager.SetTerrain", delegate()
179 {
180 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null)
181 {
182 // If a child of a mega-region, we shouldn't have any terrain allocated for us
183 ReleaseGroundPlaneAndTerrain();
184 // If doing the mega-prim stuff and we are the child of the zero region,
185 // the terrain is added to our parent
186 if (MegaRegionParentPhysicsScene is BSScene)
187 {
188 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
189 BSScene.DetailLogZero, m_worldOffset, m_worldMax);
190 ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain(
191 BSScene.CHILDTERRAIN_ID, localHeightMap,
192 m_worldOffset, m_worldOffset + DefaultRegionSize, true);
193 }
194 }
195 else
196 {
197 // If not doing the mega-prim thing, just change the terrain
198 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
199
200 UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap,
201 m_worldOffset, m_worldOffset + DefaultRegionSize, true);
202 }
203 });
204 }
205
206 // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain
207 // based on the passed information. The 'id' should be either the terrain id or
208 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
209 // The latter feature is for creating child terrains for mega-regions.
210 // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new
211 // terrain shape is created and added to the body.
212 // This call is most often used to update the heightMap and parameters of the terrain.
213 // (The above does suggest that some simplification/refactoring is in order.)
214 private void UpdateTerrain(uint id, float[] heightMap,
215 Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
216 {
217 DetailLog("{0},BSTerrainManager.UpdateTerrain,call,minC={1},maxC={2},inTaintTime={3}",
218 BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime);
219
220 // Find high and low points of passed heightmap.
221 // The min and max passed in is usually the area objects can be in (maximum
222 // object height, for instance). The terrain wants the bounding box for the
223 // terrain so we replace passed min and max Z with the actual terrain min/max Z.
224 float minZ = float.MaxValue;
225 float maxZ = float.MinValue;
226 foreach (float height in heightMap)
227 {
228 if (height < minZ) minZ = height;
229 if (height > maxZ) maxZ = height;
230 }
231 if (minZ == maxZ)
232 {
233 // If min and max are the same, reduce min a little bit so a good bounding box is created.
234 minZ -= BSTerrainManager.HEIGHT_EQUAL_FUDGE;
235 }
236 minCoords.Z = minZ;
237 maxCoords.Z = maxZ;
238
239 Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f);
240
241 BSTerrainPhys terrainPhys;
242 if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys))
243 {
244 // There is already a terrain in this spot. Free the old and build the new.
245 DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}",
246 BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords);
247
248 PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateTerrain:UpdateExisting", delegate()
249 {
250 // Remove old terrain from the collection
251 m_terrains.Remove(terrainRegionBase);
252 // Release any physical memory it may be using.
253 terrainPhys.Dispose();
254
255 if (MegaRegionParentPhysicsScene == null)
256 {
257 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
258 m_terrains.Add(terrainRegionBase, newTerrainPhys);
259
260 m_terrainModified = true;
261 }
262 else
263 {
264 // It's possible that Combine() was called after this code was queued.
265 // If we are a child of combined regions, we don't create any terrain for us.
266 DetailLog("{0},BSTerrainManager.UpdateTerrain:AmACombineChild,taint", BSScene.DetailLogZero);
267
268 // Get rid of any terrain that may have been allocated for us.
269 ReleaseGroundPlaneAndTerrain();
270
271 // I hate doing this, but just bail
272 return;
273 }
274 });
275 }
276 else
277 {
278 // We don't know about this terrain so either we are creating a new terrain or
279 // our mega-prim child is giving us a new terrain to add to the phys world
280
281 // if this is a child terrain, calculate a unique terrain id
282 uint newTerrainID = id;
283 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
284 newTerrainID = ++m_terrainCount;
285
286 float[] heightMapX = heightMap;
287 Vector3 minCoordsX = minCoords;
288 Vector3 maxCoordsX = maxCoords;
289
290 DetailLog("{0},UpdateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}",
291 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
292
293 // Code that must happen at taint-time
294 PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateTerrain:NewTerrain", delegate()
295 {
296 DetailLog("{0},UpdateTerrain:NewTerrain,taint,baseX={1},baseY={2}",
297 BSScene.DetailLogZero, minCoordsX.X, minCoordsX.Y);
298 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
299 m_terrains.Add(terrainRegionBase, newTerrainPhys);
300
301 m_terrainModified = true;
302 });
303 }
304 }
305
306 // TODO: redo terrain implementation selection to allow other base types than heightMap.
307 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
308 {
309 PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}",
310 LogHeader, PhysicsScene.RegionName, terrainRegionBase,
311 (BSTerrainPhys.TerrainImplementation)PhysicsScene.Params.terrainImplementation);
312 BSTerrainPhys newTerrainPhys = null;
313 switch ((int)PhysicsScene.Params.terrainImplementation)
314 {
315 case (int)BSTerrainPhys.TerrainImplementation.Heightmap:
316 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id,
317 heightMap, minCoords, maxCoords);
318 break;
319 case (int)BSTerrainPhys.TerrainImplementation.Mesh:
320 newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id,
321 heightMap, minCoords, maxCoords);
322 break;
323 default:
324 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}",
325 LogHeader,
326 (int)PhysicsScene.Params.terrainImplementation,
327 PhysicsScene.Params.terrainImplementation,
328 PhysicsScene.RegionName, terrainRegionBase);
329 break;
330 }
331 return newTerrainPhys;
332 }
333
334
335 // Given an X and Y, find the height of the terrain.
336 // Since we could be handling multiple terrains for a mega-region,
337 // the base of the region is calcuated assuming all regions are
338 // the same size and that is the default.
339 // Once the heightMapInfo is found, we have all the information to
340 // compute the offset into the array.
341 private float lastHeightTX = 999999f;
342 private float lastHeightTY = 999999f;
343 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
344 public float GetTerrainHeightAtXYZ(Vector3 loc)
345 {
346 float tX = loc.X;
347 float tY = loc.Y;
348 // You'd be surprized at the number of times this routine is called
349 // with the same parameters as last time.
350 if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY)
351 return lastHeight;
352
353 lastHeightTX = tX;
354 lastHeightTY = tY;
355 float ret = HEIGHT_GETHEIGHT_RET;
356
357 int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
358 int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
359 Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f);
360
361 BSTerrainPhys physTerrain;
362 if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain))
363 {
364 ret = physTerrain.GetHeightAtXYZ(loc - terrainBaseXYZ);
365 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,loc={1},base={2},height={3}",
366 BSScene.DetailLogZero, loc, terrainBaseXYZ, ret);
367 }
368 else
369 {
370 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
371 LogHeader, PhysicsScene.RegionName, tX, tY);
372 }
373 m_terrainModified = false;
374 lastHeight = ret;
375 return ret;
376 }
377
378 // Although no one seems to check this, I do support combining.
379 public bool SupportsCombining()
380 {
381 return true;
382 }
383
384 // This routine is called two ways:
385 // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum
386 // extent of the combined regions. This is to inform the parent of the size
387 // of the combined regions.
388 // and one with 'offset' as the offset of the child region to the base region,
389 // 'pScene' pointing to the parent and 'extents' of zero. This informs the
390 // child of its relative base and new parent.
391 public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
392 {
393 m_worldOffset = offset;
394 m_worldMax = extents;
395 MegaRegionParentPhysicsScene = pScene;
396 if (pScene != null)
397 {
398 // We are a child.
399 // We want m_worldMax to be the highest coordinate of our piece of terrain.
400 m_worldMax = offset + DefaultRegionSize;
401 }
402 DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}",
403 BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax);
404 }
405
406 // Unhook all the combining that I know about.
407 public void UnCombine(PhysicsScene pScene)
408 {
409 // Just like ODE, we don't do anything yet.
410 DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero);
411 }
412
413
414 private void DetailLog(string msg, params Object[] args)
415 {
416 PhysicsScene.PhysicsLogging.Write(msg, args);
417 }
418}
419}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
new file mode 100755
index 0000000..dca7150
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.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 copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework;
33using OpenSim.Region.CoreModules;
34using OpenSim.Region.Physics.Manager;
35
36using Nini.Config;
37using log4net;
38
39using OpenMetaverse;
40
41namespace OpenSim.Region.Physics.BulletSPlugin
42{
43public sealed class BSTerrainMesh : BSTerrainPhys
44{
45 static string LogHeader = "[BULLETSIM TERRAIN MESH]";
46
47 private float[] m_savedHeightMap;
48 int m_sizeX;
49 int m_sizeY;
50
51 BulletShape m_terrainShape;
52 BulletBody m_terrainBody;
53
54 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
55 : base(physicsScene, regionBase, id)
56 {
57 }
58
59 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */)
60 : base(physicsScene, regionBase, id)
61 {
62 }
63
64 // Create terrain mesh from a heightmap.
65 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
66 Vector3 minCoords, Vector3 maxCoords)
67 : base(physicsScene, regionBase, id)
68 {
69 int indicesCount;
70 int[] indices;
71 int verticesCount;
72 float[] vertices;
73
74 m_savedHeightMap = initialMap;
75
76 m_sizeX = (int)(maxCoords.X - minCoords.X);
77 m_sizeY = (int)(maxCoords.Y - minCoords.Y);
78
79 if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap,
80 m_sizeX, m_sizeY,
81 (float)m_sizeX, (float)m_sizeY,
82 Vector3.Zero, 1.0f,
83 out indicesCount, out indices, out verticesCount, out vertices))
84 {
85 // DISASTER!!
86 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID);
87 PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase);
88 // Something is very messed up and a crash is in our future.
89 return;
90 }
91
92 m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
93 indicesCount, indices, verticesCount, vertices),
94 BSPhysicsShapeType.SHAPE_MESH);
95 if (m_terrainShape.ptr == IntPtr.Zero)
96 {
97 // DISASTER!!
98 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID);
99 physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
100 // Something is very messed up and a crash is in our future.
101 return;
102 }
103
104 Vector3 pos = regionBase;
105 Quaternion rot = Quaternion.Identity;
106
107 m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot));
108 if (m_terrainBody.ptr == IntPtr.Zero)
109 {
110 // DISASTER!!
111 physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
112 // Something is very messed up and a crash is in our future.
113 return;
114 }
115
116 // Set current terrain attributes
117 BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction);
118 BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, PhysicsScene.Params.terrainHitFraction);
119 BulletSimAPI.SetRestitution2(m_terrainBody.ptr, PhysicsScene.Params.terrainRestitution);
120 BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
121
122 // Static objects are not very massive.
123 BulletSimAPI.SetMassProps2(m_terrainBody.ptr, 0f, Vector3.Zero);
124
125 // Return the new terrain to the world of physical objects
126 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr);
127
128 // redo its bounding box now that it is in the world
129 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr);
130
131 BulletSimAPI.SetCollisionFilterMask2(m_terrainBody.ptr,
132 (uint)CollisionFilterGroups.TerrainFilter,
133 (uint)CollisionFilterGroups.TerrainMask);
134
135 // Make it so the terrain will not move or be considered for movement.
136 BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
137 }
138
139 public override void Dispose()
140 {
141 if (m_terrainBody.ptr != IntPtr.Zero)
142 {
143 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr);
144 // Frees both the body and the shape.
145 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_terrainBody.ptr);
146 }
147 }
148
149 public override float GetHeightAtXYZ(Vector3 pos)
150 {
151 // For the moment use the saved heightmap to get the terrain height.
152 // TODO: raycast downward to find the true terrain below the position.
153 float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
154
155 int mapIndex = (int)pos.Y * m_sizeY + (int)pos.X;
156 try
157 {
158 ret = m_savedHeightMap[mapIndex];
159 }
160 catch
161 {
162 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
163 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
164 LogHeader, TerrainBase, pos);
165 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
166 }
167 return ret;
168 }
169
170 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
171 // Return 'true' if successfully created.
172 public static bool ConvertHeightmapToMesh(
173 BSScene physicsScene,
174 float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap
175 float extentX, float extentY, // zero based range for output vertices
176 Vector3 extentBase, // base to be added to all vertices
177 float magnification, // number of vertices to create between heightMap coords
178 out int indicesCountO, out int[] indicesO,
179 out int verticesCountO, out float[] verticesO)
180 {
181 bool ret = false;
182
183 int indicesCount = 0;
184 int verticesCount = 0;
185 int[] indices = new int[0];
186 float[] vertices = new float[0];
187
188 // Simple mesh creation which assumes magnification == 1.
189 // TODO: do a more general solution that scales, adds new vertices and smoothes the result.
190
191 try
192 {
193 // One vertice per heightmap value plus the vertices off the top and bottom edge.
194 int totalVertices = (sizeX + 1) * (sizeY + 1);
195 vertices = new float[totalVertices * 3];
196 int totalIndices = sizeX * sizeY * 6;
197 indices = new int[totalIndices];
198
199 float magX = (float)sizeX / extentX;
200 float magY = (float)sizeY / extentY;
201 physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}",
202 BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY);
203 // Note that sizeX+1 vertices are created since there is land between this and the next region.
204 for (int yy = 0; yy <= sizeY; yy++)
205 {
206 for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we got through sizeX + 1 times
207 {
208 int offset = yy * sizeX + xx;
209 // Extend the height from the height from the last row or column
210 if (yy == sizeY) offset -= sizeX;
211 if (xx == sizeX) offset -= 1;
212 float height = heightMap[offset];
213 vertices[verticesCount + 0] = (float)xx * magX + extentBase.X;
214 vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y;
215 vertices[verticesCount + 2] = height + extentBase.Z;
216 verticesCount += 3;
217 }
218 }
219 verticesCount = verticesCount / 3;
220 physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeVerts,verCount={1}",
221 BSScene.DetailLogZero, verticesCount);
222
223 for (int yy = 0; yy < sizeY; yy++)
224 {
225 for (int xx = 0; xx < sizeX; xx++)
226 {
227 int offset = yy * sizeX + xx;
228 // Each vertices is presumed to be the upper left corner of a box of two triangles
229 indices[indicesCount + 0] = offset;
230 indices[indicesCount + 1] = offset + 1;
231 indices[indicesCount + 2] = offset + sizeX + 1; // accounting for the extra column
232 indices[indicesCount + 3] = offset + 1;
233 indices[indicesCount + 4] = offset + sizeX + 2;
234 indices[indicesCount + 5] = offset + sizeX + 1;
235 indicesCount += 6;
236 }
237 }
238 physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,completeIndices,indCount={1}", // DEEBUG DEBUG DEBUG
239 LogHeader, indicesCount); // DEBUG
240 ret = true;
241 }
242 catch (Exception e)
243 {
244 physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}",
245 LogHeader, physicsScene.RegionName, extentBase, e);
246 }
247
248 indicesCountO = indicesCount;
249 indicesO = indices;
250 verticesCountO = verticesCount;
251 verticesO = vertices;
252
253 return ret;
254 }
255}
256}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 504bd3c..e60a760 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -33,52 +33,184 @@ using OpenMetaverse;
33namespace OpenSim.Region.Physics.BulletSPlugin { 33namespace OpenSim.Region.Physics.BulletSPlugin {
34 34
35// Classes to allow some type checking for the API 35// Classes to allow some type checking for the API
36// These hold pointers to allocated objects in the unmanaged space.
37
38// The physics engine controller class created at initialization
36public struct BulletSim 39public struct BulletSim
37{ 40{
38 public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; } 41 public BulletSim(uint worldId, BSScene bss, IntPtr xx)
39 public uint ID; 42 {
43 ptr = xx;
44 worldID = worldId;
45 physicsScene = bss;
46 }
47 public IntPtr ptr;
48 public uint worldID;
40 // The scene is only in here so very low level routines have a handle to print debug/error messages 49 // The scene is only in here so very low level routines have a handle to print debug/error messages
41 public BSScene scene; 50 public BSScene physicsScene;
42 public IntPtr Ptr;
43} 51}
44 52
53// An allocated Bullet btRigidBody
45public struct BulletBody 54public struct BulletBody
46{ 55{
47 public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; } 56 public BulletBody(uint id, IntPtr xx)
48 public IntPtr Ptr; 57 {
58 ID = id;
59 ptr = xx;
60 collisionFilter = 0;
61 collisionMask = 0;
62 }
63 public IntPtr ptr;
49 public uint ID; 64 public uint ID;
65 public CollisionFilterGroups collisionFilter;
66 public CollisionFilterGroups collisionMask;
67 public override string ToString()
68 {
69 StringBuilder buff = new StringBuilder();
70 buff.Append("<id=");
71 buff.Append(ID.ToString());
72 buff.Append(",p=");
73 buff.Append(ptr.ToString("X"));
74 if (collisionFilter != 0 || collisionMask != 0)
75 {
76 buff.Append(",f=");
77 buff.Append(collisionFilter.ToString("X"));
78 buff.Append(",m=");
79 buff.Append(collisionMask.ToString("X"));
80 }
81 buff.Append(">");
82 return buff.ToString();
83 }
84}
85
86public struct BulletShape
87{
88 public BulletShape(IntPtr xx)
89 {
90 ptr = xx;
91 type=BSPhysicsShapeType.SHAPE_UNKNOWN;
92 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
93 isNativeShape = false;
94 }
95 public BulletShape(IntPtr xx, BSPhysicsShapeType typ)
96 {
97 ptr = xx;
98 type = typ;
99 shapeKey = 0;
100 isNativeShape = false;
101 }
102 public IntPtr ptr;
103 public BSPhysicsShapeType type;
104 public System.UInt64 shapeKey;
105 public bool isNativeShape;
106 public override string ToString()
107 {
108 StringBuilder buff = new StringBuilder();
109 buff.Append("<p=");
110 buff.Append(ptr.ToString("X"));
111 buff.Append(",s=");
112 buff.Append(type.ToString());
113 buff.Append(",k=");
114 buff.Append(shapeKey.ToString("X"));
115 buff.Append(",n=");
116 buff.Append(isNativeShape.ToString());
117 buff.Append(">");
118 return buff.ToString();
119 }
50} 120}
51 121
122 // Constraint type values as defined by Bullet
123public enum ConstraintType : int
124{
125 POINT2POINT_CONSTRAINT_TYPE = 3,
126 HINGE_CONSTRAINT_TYPE,
127 CONETWIST_CONSTRAINT_TYPE,
128 D6_CONSTRAINT_TYPE,
129 SLIDER_CONSTRAINT_TYPE,
130 CONTACT_CONSTRAINT_TYPE,
131 D6_SPRING_CONSTRAINT_TYPE,
132 MAX_CONSTRAINT_TYPE
133}
134
135// An allocated Bullet btConstraint
52public struct BulletConstraint 136public struct BulletConstraint
53{ 137{
54 public BulletConstraint(IntPtr xx) { Ptr = xx; } 138 public BulletConstraint(IntPtr xx)
139 {
140 ptr = xx;
141 }
142 public IntPtr ptr;
143}
144
145// An allocated HeightMapThing which holds various heightmap info.
146// Made a class rather than a struct so there would be only one
147// instance of this and C# will pass around pointers rather
148// than making copies.
149public class BulletHeightMapInfo
150{
151 public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) {
152 ID = id;
153 Ptr = xx;
154 heightMap = hm;
155 terrainRegionBase = Vector3.Zero;
156 minCoords = new Vector3(100f, 100f, 25f);
157 maxCoords = new Vector3(101f, 101f, 26f);
158 minZ = maxZ = 0f;
159 sizeX = sizeY = 256f;
160 }
161 public uint ID;
55 public IntPtr Ptr; 162 public IntPtr Ptr;
163 public float[] heightMap;
164 public Vector3 terrainRegionBase;
165 public Vector3 minCoords;
166 public Vector3 maxCoords;
167 public float sizeX, sizeY;
168 public float minZ, maxZ;
169 public BulletShape terrainShape;
170 public BulletBody terrainBody;
56} 171}
57 172
58// =============================================================================== 173// ===============================================================================
59[StructLayout(LayoutKind.Sequential)] 174[StructLayout(LayoutKind.Sequential)]
60public struct ConvexHull 175public struct ConvexHull
61{ 176{
62 Vector3 Offset; 177 Vector3 Offset;
63 int VertexCount; 178 int VertexCount;
64 Vector3[] Vertices; 179 Vector3[] Vertices;
65} 180}
181public enum BSPhysicsShapeType
182{
183 SHAPE_UNKNOWN = 0,
184 SHAPE_CAPSULE = 1,
185 SHAPE_BOX = 2,
186 SHAPE_CONE = 3,
187 SHAPE_CYLINDER = 4,
188 SHAPE_SPHERE = 5,
189 SHAPE_MESH = 6,
190 SHAPE_HULL = 7,
191 // following defined by BulletSim
192 SHAPE_GROUNDPLANE = 20,
193 SHAPE_TERRAIN = 21,
194 SHAPE_COMPOUND = 22,
195 SHAPE_HEIGHTMAP = 23,
196};
197
198// The native shapes have predefined shape hash keys
199public enum FixedShapeKey : ulong
200{
201 KEY_NONE = 0,
202 KEY_BOX = 1,
203 KEY_SPHERE = 2,
204 KEY_CONE = 3,
205 KEY_CYLINDER = 4,
206 KEY_CAPSULE = 5,
207}
208
66[StructLayout(LayoutKind.Sequential)] 209[StructLayout(LayoutKind.Sequential)]
67public struct ShapeData 210public struct ShapeData
68{ 211{
69 public enum PhysicsShapeType
70 {
71 SHAPE_UNKNOWN = 0,
72 SHAPE_AVATAR = 1,
73 SHAPE_BOX = 2,
74 SHAPE_CONE = 3,
75 SHAPE_CYLINDER = 4,
76 SHAPE_SPHERE = 5,
77 SHAPE_MESH = 6,
78 SHAPE_HULL = 7
79 };
80 public uint ID; 212 public uint ID;
81 public PhysicsShapeType Type; 213 public BSPhysicsShapeType Type;
82 public Vector3 Position; 214 public Vector3 Position;
83 public Quaternion Rotation; 215 public Quaternion Rotation;
84 public Vector3 Velocity; 216 public Vector3 Velocity;
@@ -91,13 +223,15 @@ public struct ShapeData
91 public float Restitution; 223 public float Restitution;
92 public float Collidable; // true of things bump into this 224 public float Collidable; // true of things bump into this
93 public float Static; // true if a static object. Otherwise gravity, etc. 225 public float Static; // true if a static object. Otherwise gravity, etc.
226 public float Solid; // true if object cannot be passed through
227 public Vector3 Size;
94 228
95 // note that bools are passed as floats since bool size changes by language and architecture 229 // note that bools are passed as floats since bool size changes by language and architecture
96 public const float numericTrue = 1f; 230 public const float numericTrue = 1f;
97 public const float numericFalse = 0f; 231 public const float numericFalse = 0f;
98} 232}
99[StructLayout(LayoutKind.Sequential)] 233[StructLayout(LayoutKind.Sequential)]
100public struct SweepHit 234public struct SweepHit
101{ 235{
102 public uint ID; 236 public uint ID;
103 public float Fraction; 237 public float Fraction;
@@ -149,13 +283,16 @@ public struct ConfigurationParameters
149 public float ccdSweptSphereRadius; 283 public float ccdSweptSphereRadius;
150 public float contactProcessingThreshold; 284 public float contactProcessingThreshold;
151 285
286 public float terrainImplementation;
152 public float terrainFriction; 287 public float terrainFriction;
153 public float terrainHitFraction; 288 public float terrainHitFraction;
154 public float terrainRestitution; 289 public float terrainRestitution;
155 public float avatarFriction; 290 public float avatarFriction;
291 public float avatarStandingFriction;
156 public float avatarDensity; 292 public float avatarDensity;
157 public float avatarRestitution; 293 public float avatarRestitution;
158 public float avatarCapsuleRadius; 294 public float avatarCapsuleWidth;
295 public float avatarCapsuleDepth;
159 public float avatarCapsuleHeight; 296 public float avatarCapsuleHeight;
160 public float avatarContactProcessingThreshold; 297 public float avatarContactProcessingThreshold;
161 298
@@ -168,18 +305,45 @@ public struct ConfigurationParameters
168 public float shouldEnableFrictionCaching; 305 public float shouldEnableFrictionCaching;
169 public float numberOfSolverIterations; 306 public float numberOfSolverIterations;
170 307
308 public float linksetImplementation;
171 public float linkConstraintUseFrameOffset; 309 public float linkConstraintUseFrameOffset;
172 public float linkConstraintEnableTransMotor; 310 public float linkConstraintEnableTransMotor;
173 public float linkConstraintTransMotorMaxVel; 311 public float linkConstraintTransMotorMaxVel;
174 public float linkConstraintTransMotorMaxForce; 312 public float linkConstraintTransMotorMaxForce;
175 public float linkConstraintERP; 313 public float linkConstraintERP;
176 public float linkConstraintCFM; 314 public float linkConstraintCFM;
315 public float linkConstraintSolverIterations;
316
317 public float physicsLoggingFrames;
177 318
178 public const float numericTrue = 1f; 319 public const float numericTrue = 1f;
179 public const float numericFalse = 0f; 320 public const float numericFalse = 0f;
180} 321}
181 322
182// Values used by Bullet and BulletSim to control collisions 323
324// The states a bullet collision object can have
325public enum ActivationState : uint
326{
327 ACTIVE_TAG = 1,
328 ISLAND_SLEEPING,
329 WANTS_DEACTIVATION,
330 DISABLE_DEACTIVATION,
331 DISABLE_SIMULATION,
332}
333
334public enum CollisionObjectTypes : int
335{
336 CO_COLLISION_OBJECT = 1 << 0,
337 CO_RIGID_BODY = 1 << 1,
338 CO_GHOST_OBJECT = 1 << 2,
339 CO_SOFT_BODY = 1 << 3,
340 CO_HF_FLUID = 1 << 4,
341 CO_USER_TYPE = 1 << 5,
342}
343
344// Values used by Bullet and BulletSim to control object properties.
345// Bullet's "CollisionFlags" has more to do with operations on the
346// object (if collisions happen, if gravity effects it, ...).
183public enum CollisionFlags : uint 347public enum CollisionFlags : uint
184{ 348{
185 CF_STATIC_OBJECT = 1 << 0, 349 CF_STATIC_OBJECT = 1 << 0,
@@ -191,9 +355,54 @@ public enum CollisionFlags : uint
191 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, 355 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
192 // Following used by BulletSim to control collisions 356 // Following used by BulletSim to control collisions
193 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, 357 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
194 BS_VOLUME_DETECT_OBJECT = 1 << 11, 358 BS_FLOATS_ON_WATER = 1 << 11,
195 BS_PHANTOM_OBJECT = 1 << 12, 359 BS_NONE = 0,
196 BS_PHYSICAL_OBJECT = 1 << 13, 360 BS_ALL = 0xFFFFFFFF,
361
362 // These are the collision flags switched depending on physical state.
363 // The other flags are used for other things and should not be fooled with.
364 BS_ACTIVE = CF_STATIC_OBJECT
365 | CF_KINEMATIC_OBJECT
366 | CF_NO_CONTACT_RESPONSE
367};
368
369// Values for collisions groups and masks
370public enum CollisionFilterGroups : uint
371{
372 // Don't use the bit definitions!! Define the use in a
373 // filter/mask definition below. This way collision interactions
374 // are more easily debugged.
375 BNoneFilter = 0,
376 BDefaultFilter = 1 << 0,
377 BStaticFilter = 1 << 1,
378 BKinematicFilter = 1 << 2,
379 BDebrisFilter = 1 << 3,
380 BSensorTrigger = 1 << 4,
381 BCharacterFilter = 1 << 5,
382 BAllFilter = 0xFFFFFFFF,
383 // Filter groups defined by BulletSim
384 BGroundPlaneFilter = 1 << 10,
385 BTerrainFilter = 1 << 11,
386 BRaycastFilter = 1 << 12,
387 BSolidFilter = 1 << 13,
388 BLinksetFilter = 1 << 14,
389
390 // The collsion filters and masked are defined in one place -- don't want them scattered
391 AvatarFilter = BCharacterFilter,
392 AvatarMask = BAllFilter,
393 ObjectFilter = BSolidFilter,
394 ObjectMask = BAllFilter,
395 StaticObjectFilter = BStaticFilter,
396 StaticObjectMask = BAllFilter & ~BStaticFilter, // static objects don't collide with each other
397 LinksetFilter = BLinksetFilter,
398 LinksetMask = BAllFilter & ~BLinksetFilter, // linkset objects don't collide with each other
399 VolumeDetectFilter = BSensorTrigger,
400 VolumeDetectMask = ~BSensorTrigger,
401 TerrainFilter = BTerrainFilter,
402 TerrainMask = BAllFilter & ~BStaticFilter, // static objects on the ground don't collide
403 GroundPlaneFilter = BGroundPlaneFilter,
404 GroundPlaneMask = BAllFilter
405
197}; 406};
198 407
199// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 408// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
@@ -221,250 +430,285 @@ public enum ConstraintParamAxis : int
221// =============================================================================== 430// ===============================================================================
222static class BulletSimAPI { 431static class BulletSimAPI {
223 432
224[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 433// Link back to the managed code for outputting log messages
225[return: MarshalAs(UnmanagedType.LPStr)] 434[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
226public static extern string GetVersion(); 435public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
227 436
437// ===============================================================================
438// Initialization and simulation
228[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 439[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
229public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, 440public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
230 int maxCollisions, IntPtr collisionArray, 441 int maxCollisions, IntPtr collisionArray,
231 int maxUpdates, IntPtr updateArray); 442 int maxUpdates, IntPtr updateArray,
443 DebugLogCallback logRoutine);
232 444
233[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 445[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
234public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); 446public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
235 447
236[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 448[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
237public static extern void Shutdown(uint worldID); 449public static extern void SetHeightMap2(IntPtr world, float[] heightmap);
238 450
239[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 451[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
240public static extern bool UpdateParameter(uint worldID, uint localID, 452public static extern void Shutdown2(IntPtr sim);
241 [MarshalAs(UnmanagedType.LPStr)]string paramCode, float value);
242 453
243// ===============================================================================
244[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 454[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
245public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, 455public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep,
246 out int updatedEntityCount, 456 out int updatedEntityCount,
247 out IntPtr updatedEntitiesPtr, 457 out IntPtr updatedEntitiesPtr,
248 out int collidersCount, 458 out int collidersCount,
249 out IntPtr collidersPtr); 459 out IntPtr collidersPtr);
250 460
251[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 461[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
252public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, 462public static extern bool PushUpdate2(IntPtr obj);
253 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls
254 );
255 463
464// =====================================================================================
465// Mesh, hull, shape and body creation helper routines
256[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
257public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey, 467public static extern IntPtr CreateMeshShape2(IntPtr world,
258 int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, 468 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
259 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices 469 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
260 );
261 470
262[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 471[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
263public static extern bool DestroyHull(uint worldID, System.UInt64 meshKey); 472public static extern IntPtr CreateHullShape2(IntPtr world,
473 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
264 474
265[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 475[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
266public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey); 476public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape);
267 477
268[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
269public static extern bool CreateObject(uint worldID, ShapeData shapeData); 479public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData);
270 480
271/* Remove old functionality
272[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 481[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
273public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); 482public static extern bool IsNativeShape2(IntPtr shape);
274 483
275[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 484[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
276public static extern void AddConstraint(uint worldID, uint id1, uint id2, 485public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale);
277 Vector3 frame1, Quaternion frame1rot,
278 Vector3 frame2, Quaternion frame2rot,
279 Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular);
280 486
281[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
282public static extern bool RemoveConstraintByID(uint worldID, uint id1); 488public static extern IntPtr CreateCompoundShape2(IntPtr sim, bool enableDynamicAabbTree);
283 489
284[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 490[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
285public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); 491public static extern int GetNumberOfCompoundChildren2(IntPtr cShape);
286 */
287 492
288[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
289public static extern Vector3 GetObjectPosition(uint WorldID, uint id); 494public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot);
290 495
291[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
292public static extern Quaternion GetObjectOrientation(uint WorldID, uint id); 497public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx);
293 498
294[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 499[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
295public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation); 500public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx);
296 501
297[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 502[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
298public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 velocity); 503public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
299 504
300[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
301public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity); 506public static extern void RecalculateCompoundShapeLocalAabb2(IntPtr cShape);
302 507
303[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 508[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
304public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force); 509public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id);
305 510
306[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 511[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
307public static extern bool SetObjectScaleMass(uint worldID, uint id, Vector3 scale, float mass, bool isDynamic); 512public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, uint id, IntPtr constructionInfo);
308 513
309[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 514[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
310public static extern bool SetObjectCollidable(uint worldID, uint id, bool phantom); 515public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
311 516
312[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 517[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
313public static extern bool SetObjectDynamic(uint worldID, uint id, bool isDynamic, float mass); 518public static extern int GetBodyType2(IntPtr obj);
314 519
315[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 520[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
316public static extern bool SetObjectGhost(uint worldID, uint id, bool ghostly); 521public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
317 522
318[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 523[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
319public static extern bool SetObjectProperties(uint worldID, uint id, bool isStatic, bool isSolid, bool genCollisions, float mass); 524public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, uint id, Vector3 pos, Quaternion rot);
320 525
321[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 526[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
322public static extern bool SetObjectBuoyancy(uint worldID, uint id, float buoyancy); 527public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
323 528
324[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 529[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
325public static extern bool HasObject(uint worldID, uint id); 530public static extern IntPtr AllocateBodyInfo2(IntPtr obj);
326 531
327[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 532[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
328public static extern bool DestroyObject(uint worldID, uint id); 533public static extern void ReleaseBodyInfo2(IntPtr obj);
329 534
330// ===============================================================================
331[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 535[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
332public static extern SweepHit ConvexSweepTest(uint worldID, uint id, Vector3 to, float extraMargin); 536public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
333 537
538// =====================================================================================
539// Terrain creation and helper routines
334[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 540[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
335public static extern RaycastHit RayTest(uint worldID, uint id, Vector3 from, Vector3 to); 541public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords,
542 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
336 543
337[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 544[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
338public static extern Vector3 RecoverFromPenetration(uint worldID, uint id); 545public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords,
546 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
339 547
340// ===============================================================================
341[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 548[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
342public static extern void DumpBulletStatistics(); 549public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo);
343 550
344// Log a debug message
345[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
346public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
347[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 551[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
348public static extern void SetDebugLogCallback(DebugLogCallback callback); 552public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
349 553
350// =============================================================================== 554[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
351// =============================================================================== 555public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo);
352// ===============================================================================
353// A new version of the API that enables moving all the logic out of the C++ code and into
354// the C# code. This will make modifications easier for the next person.
355// This interface passes the actual pointers to the objects in the unmanaged
356// address space. All the management (calls for creation/destruction/lookup)
357// is done in the C# code.
358// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt
359// and the old code is removed.
360 556
557// =====================================================================================
558// Constraint creation and helper routines
361[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 559[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
362public static extern IntPtr GetSimHandle2(uint worldID); 560public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
561 Vector3 frame1loc, Quaternion frame1rot,
562 Vector3 frame2loc, Quaternion frame2rot,
563 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
363 564
364[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 565[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
365public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id); 566public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr obj1, IntPtr obj2,
567 Vector3 joinPoint,
568 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
366 569
367[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 570[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
368public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); 571public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
572 Vector3 pivotinA, Vector3 pivotinB,
573 Vector3 axisInA, Vector3 axisInB,
574 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
369 575
370// ===============================================================================
371[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 576[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
372public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, 577public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse);
373 int maxCollisions, IntPtr collisionArray,
374 int maxUpdates, IntPtr updateArray);
375 578
376[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 579[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
377public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); 580public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations);
378 581
379[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 582[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
380public static extern void SetHeightmap2(IntPtr world, float[] heightmap); 583public static extern bool SetFrames2(IntPtr constrain,
584 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
381 585
382[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 586[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
383public static extern void Shutdown2(IntPtr sim); 587public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
384 588
385[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 589[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
386public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep, 590public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
387 out int updatedEntityCount,
388 out IntPtr updatedEntitiesPtr,
389 out int collidersCount,
390 out IntPtr collidersPtr);
391 591
392[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 592[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
393public static extern bool PushUpdate2(IntPtr obj); 593public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
394 594
395/*
396[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 595[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
397public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices ); 596public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
398 597
399[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 598[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
400public static extern bool BuildHull2(IntPtr world, IntPtr mesh); 599public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold);
401 600
402[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 601[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
403public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh); 602public static extern bool CalculateTransforms2(IntPtr constrain);
404 603
405[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 604[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
406public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh); 605public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
407 606
408[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 607[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
409public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData); 608public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
410*/
411 609
610// =====================================================================================
611// btCollisionWorld entries
412[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 612[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
413public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, 613public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj);
414 Vector3 frame1loc, Quaternion frame1rot,
415 Vector3 frame2loc, Quaternion frame2rot,
416 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
417 614
418[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 615[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
419public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr obj1, IntPtr obj2, 616public static extern void UpdateAabbs2(IntPtr world);
420 Vector3 joinPoint,
421 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
422 617
423[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 618[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
424public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, 619public static extern bool GetForceUpdateAllAabbs2(IntPtr world);
425 Vector3 pivotinA, Vector3 pivotinB,
426 Vector3 axisInA, Vector3 axisInB,
427 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
428 620
429[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 621[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
430public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse); 622public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force);
431 623
624// =====================================================================================
625// btDynamicsWorld entries
432[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 626[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
433public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations); 627public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
434 628
435[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 629[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
436public static extern bool SetFrames2(IntPtr constrain, 630public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
437 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
438 631
439[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 632[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
440public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); 633public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects);
441 634
442[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 635[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
443public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi); 636public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain);
637// =====================================================================================
638// btCollisionObject entries
639[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
640public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain);
444 641
445[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 642[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
446public static extern bool UseFrameOffset2(IntPtr constrain, float enable); 643public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict);
447 644
448[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 645[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
449public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce); 646public static extern bool HasAnisotripicFriction2(IntPtr constrain);
450 647
451[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 648[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
452public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold); 649public static extern void SetContactProcessingThreshold2(IntPtr obj, float val);
453 650
454[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 651[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
455public static extern bool CalculateTransforms2(IntPtr constrain); 652public static extern float GetContactProcessingThreshold2(IntPtr obj);
456 653
457[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 654[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
458public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis); 655public static extern bool IsStaticObject2(IntPtr obj);
459 656
460[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 657[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
461public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain); 658public static extern bool IsKinematicObject2(IntPtr obj);
659
660[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
661public static extern bool IsStaticOrKinematicObject2(IntPtr obj);
662
663[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
664public static extern bool HasContactResponse2(IntPtr obj);
665
666[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
667public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape);
462 668
463[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 669[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
464public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj); 670public static extern IntPtr GetCollisionShape2(IntPtr obj);
465 671
466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 672[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
467public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj); 673public static extern int GetActivationState2(IntPtr obj);
674
675[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
676public static extern void SetActivationState2(IntPtr obj, int state);
677
678[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
679public static extern void SetDeactivationTime2(IntPtr obj, float dtime);
680
681[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
682public static extern float GetDeactivationTime2(IntPtr obj);
683
684[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
685public static extern void ForceActivationState2(IntPtr obj, ActivationState state);
686
687[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
688public static extern void Activate2(IntPtr obj, bool forceActivation);
689
690[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
691public static extern bool IsActive2(IntPtr obj);
692
693[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
694public static extern void SetRestitution2(IntPtr obj, float val);
695
696[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
697public static extern float GetRestitution2(IntPtr obj);
698
699[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
700public static extern void SetFriction2(IntPtr obj, float val);
701
702[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
703public static extern float GetFriction2(IntPtr obj);
704
705 /* Haven't defined the type 'Transform'
706[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
707public static extern Transform GetWorldTransform2(IntPtr obj);
708
709[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
710public static extern void setWorldTransform2(IntPtr obj, Transform trans);
711 */
468 712
469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 713[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
470public static extern Vector3 GetPosition2(IntPtr obj); 714public static extern Vector3 GetPosition2(IntPtr obj);
@@ -473,85 +717,296 @@ public static extern Vector3 GetPosition2(IntPtr obj);
473public static extern Quaternion GetOrientation2(IntPtr obj); 717public static extern Quaternion GetOrientation2(IntPtr obj);
474 718
475[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 719[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
476public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); 720public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation);
477 721
478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 722[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
479public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity); 723public static extern IntPtr GetBroadphaseHandle2(IntPtr obj);
480 724
481[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 725[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
482public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); 726public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle);
483 727
728 /*
484[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 729[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
485public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); 730public static extern Transform GetInterpolationWorldTransform2(IntPtr obj);
486 731
487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 732[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
488public static extern bool AddObjectForce2(IntPtr obj, Vector3 force); 733public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans);
734 */
489 735
490[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 736[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
491public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); 737public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel);
492 738
493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 739[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
494public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val); 740public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel);
495 741
496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 742[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
497public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping); 743public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel);
498 744
499[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 745[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
500public static extern bool SetDeactivationTime2(IntPtr obj, float val); 746public static extern float GetHitFraction2(IntPtr obj);
501 747
502[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 748[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
503public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); 749public static extern void SetHitFraction2(IntPtr obj, float val);
504 750
505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 751[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
506public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val); 752public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
507 753
508[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 754[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
509public static extern bool SetFriction2(IntPtr obj, float val); 755public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
510 756
511[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 757[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
512public static extern bool SetRestitution2(IntPtr obj, float val); 758public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
513 759
514[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 760[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
515public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val); 761public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
516 762
517[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 763[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
518public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); 764public static extern float GetCcdMotionThreshold2(IntPtr obj);
519 765
520[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 766[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
521public static extern CollisionFlags GetCollisionFlags2(IntPtr obj); 767public static extern void SetCcdMotionThreshold2(IntPtr obj, float val);
768
769[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
770public static extern float GetCcdSweptSphereRadius2(IntPtr obj);
771
772[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
773public static extern void SetCcdSweptSphereRadius2(IntPtr obj, float val);
774
775[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
776public static extern IntPtr GetUserPointer2(IntPtr obj);
777
778[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
779public static extern void SetUserPointer2(IntPtr obj, IntPtr val);
780
781// =====================================================================================
782// btRigidBody entries
783[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
784public static extern void ApplyGravity2(IntPtr obj);
785
786[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
787public static extern void SetGravity2(IntPtr obj, Vector3 val);
788
789[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
790public static extern Vector3 GetGravity2(IntPtr obj);
791
792[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
793public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
794
795[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
796public static extern void SetLinearDamping2(IntPtr obj, float lin_damping);
797
798[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
799public static extern void SetAngularDamping2(IntPtr obj, float ang_damping);
800
801[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
802public static extern float GetLinearDamping2(IntPtr obj);
803
804[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
805public static extern float GetAngularDamping2(IntPtr obj);
806
807[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
808public static extern float GetLinearSleepingThreshold2(IntPtr obj);
809
810[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
811public static extern float GetAngularSleepingThreshold2(IntPtr obj);
812
813[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
814public static extern void ApplyDamping2(IntPtr obj, float timeStep);
815
816[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
817public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
818
819[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
820public static extern Vector3 GetLinearFactor2(IntPtr obj);
821
822[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
823public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor);
824
825 /*
826[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
827public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans);
828 */
829
830[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
831public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot);
832
833// Add a force to the object as if its mass is one.
834[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
835public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force);
836
837// Set the force being applied to the object as if its mass is one.
838[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
839public static extern void SetObjectForce2(IntPtr obj, Vector3 force);
840
841[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
842public static extern Vector3 GetTotalForce2(IntPtr obj);
843
844[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
845public static extern Vector3 GetTotalTorque2(IntPtr obj);
846
847[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
848public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj);
849
850[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
851public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert);
852
853[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
854public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
855
856[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
857public static extern void ApplyTorque2(IntPtr obj, Vector3 torque);
858
859// Apply force at the given point. Will add torque to the object.
860[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
861public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos);
862
863// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass.
864[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
865public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp);
866
867// Apply impulse to the object's torque. Force is scaled by object's mass.
868[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
869public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp);
870
871// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces.
872[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
873public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos);
874
875[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
876public static extern void ClearForces2(IntPtr obj);
877
878[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
879public static extern void ClearAllForces2(IntPtr obj);
880
881[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
882public static extern void UpdateInertiaTensor2(IntPtr obj);
883
884[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
885public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj);
886
887 /*
888[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
889public static extern Transform GetCenterOfMassTransform2(IntPtr obj);
890 */
891
892[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
893public static extern Vector3 GetLinearVelocity2(IntPtr obj);
894
895[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
896public static extern Vector3 GetAngularVelocity2(IntPtr obj);
897
898[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
899public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val);
900
901[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
902public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity);
903
904[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
905public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos);
906
907[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
908public static extern void Translate2(IntPtr obj, Vector3 trans);
909
910[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
911public static extern void UpdateDeactivation2(IntPtr obj, float timeStep);
912
913[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
914public static extern bool WantsSleeping2(IntPtr obj);
915
916[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
917public static extern void SetAngularFactor2(IntPtr obj, float factor);
918
919[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
920public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor);
921
922[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
923public static extern Vector3 GetAngularFactor2(IntPtr obj);
924
925[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
926public static extern bool IsInWorld2(IntPtr obj);
927
928[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
929public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain);
930
931[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
932public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain);
933
934[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
935public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
936
937[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
938public static extern int GetNumConstraintRefs2(IntPtr obj);
939
940[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
941public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask);
942
943// =====================================================================================
944// btCollisionShape entries
945
946[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
947public static extern float GetAngularMotionDisc2(IntPtr shape);
948
949[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
950public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor);
951
952[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
953public static extern bool IsPolyhedral2(IntPtr shape);
954
955[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
956public static extern bool IsConvex2d2(IntPtr shape);
957
958[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
959public static extern bool IsConvex2(IntPtr shape);
960
961[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
962public static extern bool IsNonMoving2(IntPtr shape);
963
964[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
965public static extern bool IsConcave2(IntPtr shape);
966
967[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
968public static extern bool IsCompound2(IntPtr shape);
969
970[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
971public static extern bool IsSoftBody2(IntPtr shape);
972
973[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
974public static extern bool IsInfinite2(IntPtr shape);
522 975
523[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 976[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
524public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags); 977public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale);
525 978
526[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 979[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
527public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags); 980public static extern Vector3 GetLocalScaling2(IntPtr shape);
528 981
529[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 982[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
530public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); 983public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass);
531 984
532[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 985[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
533public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); 986public static extern int GetShapeType2(IntPtr shape);
534 987
535[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 988[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
536public static extern bool UpdateInertiaTensor2(IntPtr obj); 989public static extern void SetMargin2(IntPtr shape, float val);
537 990
538[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 991[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
539public static extern bool SetGravity2(IntPtr obj, Vector3 val); 992public static extern float GetMargin2(IntPtr shape);
540 993
994// =====================================================================================
995// Debugging
541[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 996[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
542public static extern IntPtr ClearForces2(IntPtr obj); 997public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
543 998
544[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 999[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
545public static extern IntPtr ClearAllForces2(IntPtr obj); 1000public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape);
546 1001
547[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1002[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
548public static extern bool SetMargin2(IntPtr obj, float val); 1003public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain);
549 1004
550[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1005[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
551public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); 1006public static extern void DumpAllInfo2(IntPtr sim);
552 1007
553[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1008[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
554public static extern bool DestroyObject2(IntPtr world, uint id); 1009public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
555 1010
556[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1011[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
557public static extern void DumpPhysicsStatistics2(IntPtr sim); 1012public static extern void DumpPhysicsStatistics2(IntPtr sim);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..0d1db3b
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.Physics.BulletSPlugin")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("520ea11b-20cb-449d-ba05-c01015fed841")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
index 4285e8c..5ff945d 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("1.0.0.0")] 35[assembly: AssemblyVersion("0.7.5.*")]
36[assembly: AssemblyFileVersion("1.0.0.0")] 36[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/Physics/Manager/AssemblyInfo.cs b/OpenSim/Region/Physics/Manager/AssemblyInfo.cs
index 1f9bf03..36b4235 100644
--- a/OpenSim/Region/Physics/Manager/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/Manager/AssemblyInfo.cs
@@ -39,7 +39,7 @@ using System.Runtime.InteropServices;
39[assembly : AssemblyConfiguration("")] 39[assembly : AssemblyConfiguration("")]
40[assembly : AssemblyCompany("http://opensimulator.org")] 40[assembly : AssemblyCompany("http://opensimulator.org")]
41[assembly : AssemblyProduct("PhysicsManager")] 41[assembly : AssemblyProduct("PhysicsManager")]
42[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")] 42[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")]
43[assembly : AssemblyTrademark("")] 43[assembly : AssemblyTrademark("")]
44[assembly : AssemblyCulture("")] 44[assembly : AssemblyCulture("")]
45 45
@@ -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.6.5.*")] 58[assembly : AssemblyVersion("0.7.5.*")]
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index 14f65b8..5af6373 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -340,6 +340,12 @@ namespace OpenSim.Region.Physics.Manager
340 /// Getting this returns the velocity calculated by physics scene updates, using factors such as target velocity, 340 /// Getting this returns the velocity calculated by physics scene updates, using factors such as target velocity,
341 /// time to accelerate and collisions. 341 /// time to accelerate and collisions.
342 /// </remarks> 342 /// </remarks>
343 public virtual Vector3 TargetVelocity
344 {
345 get { return Velocity; }
346 set { Velocity = value; }
347 }
348
343 public abstract Vector3 Velocity { get; set; } 349 public abstract Vector3 Velocity { get; set; }
344 350
345 public abstract Vector3 Torque { get; set; } 351 public abstract Vector3 Torque { get; set; }
diff --git a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4cc1731
--- /dev/null
+++ b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.Physics.Meshing")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("4b7e35c2-a9dd-4b10-b778-eb417f4f6884")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs
index d65929a..3c4f06a 100644
--- a/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs
@@ -39,7 +39,7 @@ using System.Runtime.InteropServices;
39[assembly : AssemblyConfiguration("")] 39[assembly : AssemblyConfiguration("")]
40[assembly : AssemblyCompany("http://opensimulator.org")] 40[assembly : AssemblyCompany("http://opensimulator.org")]
41[assembly : AssemblyProduct("OdePlugin")] 41[assembly : AssemblyProduct("OdePlugin")]
42[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")] 42[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")]
43[assembly : AssemblyTrademark("")] 43[assembly : AssemblyTrademark("")]
44[assembly : AssemblyCulture("")] 44[assembly : AssemblyCulture("")]
45 45
@@ -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.6.5.*")] 58[assembly : AssemblyVersion("0.7.5.*")]
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index f3b0630..319f6ab 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -100,7 +100,7 @@ namespace OpenSim.Region.Physics.OdePlugin
100 private bool m_hackSentFly = false; 100 private bool m_hackSentFly = false;
101 private int m_requestedUpdateFrequency = 0; 101 private int m_requestedUpdateFrequency = 0;
102 private Vector3 m_taintPosition; 102 private Vector3 m_taintPosition;
103 103 internal bool m_avatarplanted = false;
104 /// <summary> 104 /// <summary>
105 /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force 105 /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force
106 /// while calculatios are going on 106 /// while calculatios are going on
@@ -413,7 +413,7 @@ namespace OpenSim.Region.Physics.OdePlugin
413 set 413 set
414 { 414 {
415 m_iscollidingObj = value; 415 m_iscollidingObj = value;
416 if (value) 416 if (value && !m_avatarplanted)
417 m_pidControllerActive = false; 417 m_pidControllerActive = false;
418 else 418 else
419 m_pidControllerActive = true; 419 m_pidControllerActive = true;
@@ -661,6 +661,20 @@ namespace OpenSim.Region.Physics.OdePlugin
661 set { return; } 661 set { return; }
662 } 662 }
663 663
664 public override Vector3 TargetVelocity
665 {
666 get
667 {
668 return m_taintTargetVelocity;
669 }
670
671 set
672 {
673 Velocity = value;
674 }
675 }
676
677
664 public override Vector3 Velocity 678 public override Vector3 Velocity
665 { 679 {
666 get 680 get
@@ -1394,4 +1408,4 @@ namespace OpenSim.Region.Physics.OdePlugin
1394 m_eventsubscription += p; 1408 m_eventsubscription += p;
1395 } 1409 }
1396 } 1410 }
1397} \ No newline at end of file 1411}
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index 2e78de5..a59f63f 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -67,6 +67,14 @@ namespace OpenSim.Region.Physics.OdePlugin
67 private int m_expectedCollisionContacts = 0; 67 private int m_expectedCollisionContacts = 0;
68 68
69 /// <summary> 69 /// <summary>
70 /// Gets collide bits so that we can still perform land collisions if a mesh fails to load.
71 /// </summary>
72 private int BadMeshAssetCollideBits
73 {
74 get { return m_isphysical ? (int)CollisionCategories.Land : 0; }
75 }
76
77 /// <summary>
70 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. 78 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
71 /// </summary> 79 /// </summary>
72 public override bool IsPhysical 80 public override bool IsPhysical
@@ -156,7 +164,7 @@ namespace OpenSim.Region.Physics.OdePlugin
156 164
157 private PrimitiveBaseShape _pbs; 165 private PrimitiveBaseShape _pbs;
158 private OdeScene _parent_scene; 166 private OdeScene _parent_scene;
159 167
160 /// <summary> 168 /// <summary>
161 /// The physics space which contains prim geometries 169 /// The physics space which contains prim geometries
162 /// </summary> 170 /// </summary>
@@ -3333,7 +3341,6 @@ Console.WriteLine(" JointCreateFixed");
3333 m_material = pMaterial; 3341 m_material = pMaterial;
3334 } 3342 }
3335 3343
3336
3337 private void CheckMeshAsset() 3344 private void CheckMeshAsset()
3338 { 3345 {
3339 if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero) 3346 if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero)
@@ -3343,14 +3350,14 @@ Console.WriteLine(" JointCreateFixed");
3343 { 3350 {
3344 RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod; 3351 RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod;
3345 if (assetProvider != null) 3352 if (assetProvider != null)
3346 assetProvider(_pbs.SculptTexture, MeshAssetReveived); 3353 assetProvider(_pbs.SculptTexture, MeshAssetReceived);
3347 }); 3354 });
3348 } 3355 }
3349 } 3356 }
3350 3357
3351 void MeshAssetReveived(AssetBase asset) 3358 private void MeshAssetReceived(AssetBase asset)
3352 { 3359 {
3353 if (asset.Data != null && asset.Data.Length > 0) 3360 if (asset != null && asset.Data != null && asset.Data.Length > 0)
3354 { 3361 {
3355 if (!_pbs.SculptEntry) 3362 if (!_pbs.SculptEntry)
3356 return; 3363 return;
@@ -3363,6 +3370,12 @@ Console.WriteLine(" JointCreateFixed");
3363 m_taintshape = true; 3370 m_taintshape = true;
3364 _parent_scene.AddPhysicsActorTaint(this); 3371 _parent_scene.AddPhysicsActorTaint(this);
3365 } 3372 }
3373 else
3374 {
3375 m_log.WarnFormat(
3376 "[ODE PRIM]: Could not get mesh/sculpt asset {0} for {1} at {2} in {3}",
3377 _pbs.SculptTexture, Name, _position, _parent_scene.Name);
3378 }
3366 } 3379 }
3367 } 3380 }
3368} \ No newline at end of file 3381}
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index 7a50c4c..d53bd90 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -501,6 +501,8 @@ namespace OpenSim.Region.Physics.OdePlugin
501 public int physics_logging_interval = 0; 501 public int physics_logging_interval = 0;
502 public bool physics_logging_append_existing_logfile = false; 502 public bool physics_logging_append_existing_logfile = false;
503 503
504 private bool avplanted = false;
505 private bool av_av_collisions_off = false;
504 506
505 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); 507 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f);
506 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); 508 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
@@ -644,6 +646,9 @@ namespace OpenSim.Region.Physics.OdePlugin
644 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); 646 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f);
645 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); 647 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f);
646 avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); 648 avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f);
649 avplanted = physicsconfig.GetBoolean("av_planted", false);
650 av_av_collisions_off = physicsconfig.GetBoolean("av_av_collisions_off", false);
651
647 IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); 652 IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false);
648 653
649 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); 654 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80);
@@ -663,6 +668,8 @@ namespace OpenSim.Region.Physics.OdePlugin
663 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); 668 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f);
664 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); 669 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
665 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); 670 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
671
672
666 673
667 if (Environment.OSVersion.Platform == PlatformID.Unix) 674 if (Environment.OSVersion.Platform == PlatformID.Unix)
668 { 675 {
@@ -1309,6 +1316,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1309 if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) 1316 if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect))
1310 skipThisContact = true; // No collision on volume detect prims 1317 skipThisContact = true; // No collision on volume detect prims
1311 1318
1319 if (av_av_collisions_off)
1320 if ((p1 is OdeCharacter) && (p2 is OdeCharacter))
1321 skipThisContact = true;
1322
1312 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) 1323 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect))
1313 skipThisContact = true; // No collision on volume detect prims 1324 skipThisContact = true; // No collision on volume detect prims
1314 1325
@@ -1972,7 +1983,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1972 1983
1973 newAv.Flying = isFlying; 1984 newAv.Flying = isFlying;
1974 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; 1985 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1975 1986 newAv.m_avatarplanted = avplanted;
1987
1976 return newAv; 1988 return newAv;
1977 } 1989 }
1978 1990
@@ -1987,6 +1999,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1987 1999
1988 internal void AddCharacter(OdeCharacter chr) 2000 internal void AddCharacter(OdeCharacter chr)
1989 { 2001 {
2002 chr.m_avatarplanted = avplanted;
1990 if (!_characters.Contains(chr)) 2003 if (!_characters.Contains(chr))
1991 { 2004 {
1992 _characters.Add(chr); 2005 _characters.Add(chr);
@@ -4307,4 +4320,4 @@ namespace OpenSim.Region.Physics.OdePlugin
4307 m_stats[ODEPrimUpdateFrameMsStatName] = 0; 4320 m_stats[ODEPrimUpdateFrameMsStatName] = 0;
4308 } 4321 }
4309 } 4322 }
4310} \ No newline at end of file 4323}
diff --git a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs
index af24567..d07df02 100644
--- a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs
@@ -39,7 +39,7 @@ using System.Runtime.InteropServices;
39[assembly : AssemblyConfiguration("")] 39[assembly : AssemblyConfiguration("")]
40[assembly : AssemblyCompany("http://opensimulator.org")] 40[assembly : AssemblyCompany("http://opensimulator.org")]
41[assembly : AssemblyProduct("POSPlugin")] 41[assembly : AssemblyProduct("POSPlugin")]
42[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")] 42[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers")]
43[assembly : AssemblyTrademark("")] 43[assembly : AssemblyTrademark("")]
44[assembly : AssemblyCulture("")] 44[assembly : AssemblyCulture("")]
45 45
@@ -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.6.5.*")] 58[assembly : AssemblyVersion("0.7.5.*")]
diff --git a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
index 1e9b8bc..b67422f 100644
--- a/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
+++ b/OpenSim/Region/Physics/UbitMeshing/Mesh.cs
@@ -205,12 +205,35 @@ namespace OpenSim.Region.Physics.Meshing
205 205
206 } 206 }
207 207
208 private float fRound(float f)
209 {
210 int i;
211 if (f == 0f)
212 return f;
213 else if (f > 0f)
214 i = (int)(1e5f * f + 0.5f);
215 else
216 i = (int)(1e5f * f - 0.5f);
217
218 return ((float)i * 1e-5f);
219 }
208 220
209 public void Add(Triangle triangle) 221 public void Add(Triangle triangle)
210 { 222 {
211 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero) 223 if (m_indicesPtr != IntPtr.Zero || m_verticesPtr != IntPtr.Zero)
212 throw new NotSupportedException("Attempt to Add to a pinned Mesh"); 224 throw new NotSupportedException("Attempt to Add to a pinned Mesh");
213 225
226 // round down
227 triangle.v1.X = fRound(triangle.v1.X);
228 triangle.v1.Y = fRound(triangle.v1.Y);
229 triangle.v1.Z = fRound(triangle.v1.Z);
230 triangle.v2.X = fRound(triangle.v2.X);
231 triangle.v2.Y = fRound(triangle.v2.Y);
232 triangle.v2.Z = fRound(triangle.v2.Z);
233 triangle.v3.X = fRound(triangle.v3.X);
234 triangle.v3.Y = fRound(triangle.v3.Y);
235 triangle.v3.Z = fRound(triangle.v3.Z);
236
214 if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z) 237 if ((triangle.v1.X == triangle.v2.X && triangle.v1.Y == triangle.v2.Y && triangle.v1.Z == triangle.v2.Z)
215 || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z) 238 || (triangle.v1.X == triangle.v3.X && triangle.v1.Y == triangle.v3.Y && triangle.v1.Z == triangle.v3.Z)
216 || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z) 239 || (triangle.v2.X == triangle.v3.X && triangle.v2.Y == triangle.v3.Y && triangle.v2.Z == triangle.v3.Z)
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
index f5bf05d..3d5be3e 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
@@ -79,14 +79,27 @@ namespace OpenSim.Region.Physics.OdePlugin
79 private Vector3 _target_velocity; 79 private Vector3 _target_velocity;
80 private Vector3 _acceleration; 80 private Vector3 _acceleration;
81 private Vector3 m_rotationalVelocity; 81 private Vector3 m_rotationalVelocity;
82 private Vector3 m_size;
83 private Quaternion m_orientation;
82 private float m_mass = 80f; 84 private float m_mass = 80f;
83 public float m_density = 60f; 85 public float m_density = 60f;
84 private bool m_pidControllerActive = true; 86 private bool m_pidControllerActive = true;
85 public float PID_D = 800.0f; 87 public float PID_D = 800.0f;
86 public float PID_P = 900.0f; 88 public float PID_P = 900.0f;
87 //private static float POSTURE_SERVO = 10000.0f; 89 //private static float POSTURE_SERVO = 10000.0f;
88 public float CAPSULE_RADIUS = 0.37f; 90
89 public float CAPSULE_LENGTH = 2.140599f; 91
92 private float m_invElipSizeX;
93 private float m_invElipSizeY;
94
95 private float feetOff = 0;
96 private float feetSZ = 0.5f;
97 const float feetScale = 0.9f;
98 const float invFeetScale = 1.0f / 0.9f;
99 const float sizeZAdjust = 0.15f;
100 private float boneOff = 0;
101
102
90 public float walkDivisor = 1.3f; 103 public float walkDivisor = 1.3f;
91 public float runDivisor = 0.8f; 104 public float runDivisor = 0.8f;
92 private bool flying = false; 105 private bool flying = false;
@@ -123,10 +136,16 @@ namespace OpenSim.Region.Physics.OdePlugin
123 // we do land collisions not ode | CollisionCategories.Land); 136 // we do land collisions not ode | CollisionCategories.Land);
124 public IntPtr Body = IntPtr.Zero; 137 public IntPtr Body = IntPtr.Zero;
125 private OdeScene _parent_scene; 138 private OdeScene _parent_scene;
126 public IntPtr Shell = IntPtr.Zero; 139 public IntPtr topbox = IntPtr.Zero;
140 public IntPtr midbox = IntPtr.Zero;
141 public IntPtr feetbox = IntPtr.Zero;
142 public IntPtr bonebox = IntPtr.Zero;
143
127 public IntPtr Amotor = IntPtr.Zero; 144 public IntPtr Amotor = IntPtr.Zero;
145
128 public d.Mass ShellMass; 146 public d.Mass ShellMass;
129// public bool collidelock = false; 147
148
130 149
131 public int m_eventsubscription = 0; 150 public int m_eventsubscription = 0;
132 private int m_cureventsubscription = 0; 151 private int m_cureventsubscription = 0;
@@ -139,7 +158,9 @@ namespace OpenSim.Region.Physics.OdePlugin
139 158
140 float mu; 159 float mu;
141 160
142 public OdeCharacter(String avName, OdeScene parent_scene, Vector3 pos, Vector3 size, float pid_d, float pid_p, float capsule_radius, float density, float walk_divisor, float rundivisor) 161
162
163 public OdeCharacter(String avName, OdeScene parent_scene, Vector3 pos, Vector3 pSize, float pid_d, float pid_p, float density, float walk_divisor, float rundivisor)
143 { 164 {
144 m_uuid = UUID.Random(); 165 m_uuid = UUID.Random();
145 166
@@ -165,9 +186,20 @@ namespace OpenSim.Region.Physics.OdePlugin
165 186
166 PID_D = pid_d; 187 PID_D = pid_d;
167 PID_P = pid_p; 188 PID_P = pid_p;
168 CAPSULE_RADIUS = capsule_radius; 189
190 m_size.X = pSize.X;
191 m_size.Y = pSize.Y;
192 m_size.Z = pSize.Z;
193
194 if(m_size.X <0.01f)
195 m_size.X = 0.01f;
196 if(m_size.Y <0.01f)
197 m_size.Y = 0.01f;
198 if(m_size.Z <0.01f)
199 m_size.Z = 0.01f;
200
201 m_orientation = Quaternion.Identity;
169 m_density = density; 202 m_density = density;
170 m_mass = 80f; // sure we have a default
171 203
172 // force lower density for testing 204 // force lower density for testing
173 m_density = 3.0f; 205 m_density = 3.0f;
@@ -177,8 +209,7 @@ namespace OpenSim.Region.Physics.OdePlugin
177 walkDivisor = walk_divisor; 209 walkDivisor = walk_divisor;
178 runDivisor = rundivisor; 210 runDivisor = rundivisor;
179 211
180 CAPSULE_LENGTH = size.Z * 1.15f - CAPSULE_RADIUS * 2.0f; 212 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; ; // sure we have a default
181 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
182 213
183 m_isPhysical = false; // current status: no ODE information exists 214 m_isPhysical = false; // current status: no ODE information exists
184 215
@@ -420,13 +451,21 @@ namespace OpenSim.Region.Physics.OdePlugin
420 /// </summary> 451 /// </summary>
421 public override Vector3 Size 452 public override Vector3 Size
422 { 453 {
423 get { 454 get
424 float d = CAPSULE_RADIUS * 2; 455 {
425 return new Vector3(d, d, (CAPSULE_LENGTH +d)/1.15f); } 456 return m_size;
457 }
426 set 458 set
427 { 459 {
428 if (value.IsFinite()) 460 if (value.IsFinite())
429 { 461 {
462 if(value.X <0.01f)
463 value.X = 0.01f;
464 if(value.Y <0.01f)
465 value.Y = 0.01f;
466 if(value.Z <0.01f)
467 value.Z = 0.01f;
468
430 AddChange(changes.Size, value); 469 AddChange(changes.Size, value);
431 } 470 }
432 else 471 else
@@ -452,8 +491,7 @@ namespace OpenSim.Region.Physics.OdePlugin
452 { 491 {
453 get 492 get
454 { 493 {
455 float AVvolume = (float)(Math.PI * CAPSULE_RADIUS * CAPSULE_RADIUS * (1.3333333333f * CAPSULE_RADIUS + CAPSULE_LENGTH)); 494 return m_density * m_size.X * m_size.Y * m_size.Z;
456 return m_density * AVvolume;
457 } 495 }
458 } 496 }
459 public override void link(PhysicsActor obj) 497 public override void link(PhysicsActor obj)
@@ -571,9 +609,14 @@ namespace OpenSim.Region.Physics.OdePlugin
571 609
572 public override Quaternion Orientation 610 public override Quaternion Orientation
573 { 611 {
574 get { return Quaternion.Identity; } 612 get { return m_orientation; }
575 set 613 set
576 { 614 {
615 // fakeori = value;
616 // givefakeori++;
617
618 value.Normalize();
619 AddChange(changes.Orientation, value);
577 } 620 }
578 } 621 }
579 622
@@ -625,32 +668,65 @@ namespace OpenSim.Region.Physics.OdePlugin
625 AddChange(changes.Momentum, momentum); 668 AddChange(changes.Momentum, momentum);
626 } 669 }
627 670
628
629 // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
630 // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
631 // place that is safe to call this routine AvatarGeomAndBodyCreation.
632 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ) 671 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
633 { 672 {
673 // sizes one day should came from visual parameters
674 float sz = m_size.Z + sizeZAdjust;
675
676 m_invElipSizeX = 1.0f / m_size.X;
677 m_invElipSizeY = 1.0f / m_size.Y;
678
679 float topsx = m_size.X;
680 float midsx = m_size.X;
681 float feetsx = m_size.X * feetScale;
682 float bonesx = feetsx * 0.2f;
683
684 float topsy = m_size.Y * 0.5f;
685 float midsy = m_size.Y;
686 float feetsy = m_size.Y * feetScale;
687 float bonesy = feetsy * 0.2f;
688
689 float topsz = sz * 0.15f;
690 float feetsz = sz * 0.3f;
691 if (feetsz > 0.6f)
692 feetsz = 0.6f;
693
694 float midsz = sz - topsz - feetsz;
695 float bonesz = sz;
696
697 float bot = -sz * 0.5f;
698
699 boneOff = bot + 0.3f;
700
701 float feetz = bot + feetsz * 0.5f;
702 bot += feetsz;
703
704 feetOff = bot;
705 feetSZ = feetsz;
706
707 float midz = bot + midsz * 0.5f;
708 bot += midsz;
709 float topz = bot + topsz * 0.5f;
710
634 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); 711 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
635 if (CAPSULE_LENGTH <= 0)
636 {
637 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
638 CAPSULE_LENGTH = 0.01f;
639 712
640 } 713 feetbox = d.CreateBox(_parent_scene.ActiveSpace, feetsx, feetsy, feetsz);
714 d.GeomSetCategoryBits(feetbox, (uint)m_collisionCategories);
715 d.GeomSetCollideBits(feetbox, (uint)m_collisionFlags);
641 716
642 if (CAPSULE_RADIUS <= 0) 717 midbox = d.CreateBox(_parent_scene.ActiveSpace, midsx, midsy, midsz);
643 { 718 d.GeomSetCategoryBits(midbox, (uint)m_collisionCategories);
644 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!"); 719 d.GeomSetCollideBits(midbox, (uint)m_collisionFlags);
645 CAPSULE_RADIUS = 0.01f;
646 720
647 } 721 topbox = d.CreateBox(_parent_scene.ActiveSpace, topsx, topsy, topsz);
648 Shell = d.CreateCapsule(_parent_scene.ActiveSpace, CAPSULE_RADIUS, CAPSULE_LENGTH); 722 d.GeomSetCategoryBits(topbox, (uint)m_collisionCategories);
723 d.GeomSetCollideBits(topbox, (uint)m_collisionFlags);
649 724
650 d.GeomSetCategoryBits(Shell, (uint)m_collisionCategories); 725 bonebox = d.CreateBox(_parent_scene.ActiveSpace, bonesx, bonesy, bonesz);
651 d.GeomSetCollideBits(Shell, (uint)m_collisionFlags); 726 d.GeomSetCategoryBits(bonebox, (uint)m_collisionCategories);
727 d.GeomSetCollideBits(bonebox, (uint)m_collisionFlags);
652 728
653 d.MassSetCapsule(out ShellMass, m_density, 3, CAPSULE_RADIUS, CAPSULE_LENGTH); 729 d.MassSetBox(out ShellMass, m_density, m_size.X , m_size.Y, m_size.Z);
654 730
655 m_mass = ShellMass.mass; // update mass 731 m_mass = ShellMass.mass; // update mass
656 732
@@ -681,7 +757,14 @@ namespace OpenSim.Region.Physics.OdePlugin
681 _position.Z = npositionZ; 757 _position.Z = npositionZ;
682 758
683 d.BodySetMass(Body, ref ShellMass); 759 d.BodySetMass(Body, ref ShellMass);
684 d.GeomSetBody(Shell, Body); 760 d.GeomSetBody(feetbox, Body);
761 d.GeomSetBody(midbox, Body);
762 d.GeomSetBody(topbox, Body);
763 d.GeomSetBody(bonebox, Body);
764
765 d.GeomSetOffsetPosition(feetbox, 0, 0, feetz);
766 d.GeomSetOffsetPosition(midbox, 0, 0, midz);
767 d.GeomSetOffsetPosition(topbox, 0, 0, topz);
685 768
686 // The purpose of the AMotor here is to keep the avatar's physical 769 // The purpose of the AMotor here is to keep the avatar's physical
687 // surrogate from rotating while moving 770 // surrogate from rotating while moving
@@ -741,15 +824,152 @@ namespace OpenSim.Region.Physics.OdePlugin
741 Body = IntPtr.Zero; 824 Body = IntPtr.Zero;
742 } 825 }
743 826
744 //kill the Geometry 827 //kill the Geoms
745 if (Shell != IntPtr.Zero) 828 if (topbox != IntPtr.Zero)
829 {
830 _parent_scene.actor_name_map.Remove(topbox);
831 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
832 d.GeomDestroy(topbox);
833 topbox = IntPtr.Zero;
834 }
835 if (midbox != IntPtr.Zero)
836 {
837 _parent_scene.actor_name_map.Remove(midbox);
838 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
839 d.GeomDestroy(midbox);
840 midbox = IntPtr.Zero;
841 }
842 if (feetbox != IntPtr.Zero)
843 {
844 _parent_scene.actor_name_map.Remove(feetbox);
845 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
846 d.GeomDestroy(feetbox);
847 feetbox = IntPtr.Zero;
848 }
849
850 if (bonebox != IntPtr.Zero)
746 { 851 {
747// _parent_scene.geom_name_map.Remove(Shell); 852 _parent_scene.actor_name_map.Remove(bonebox);
748 _parent_scene.actor_name_map.Remove(Shell);
749 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); 853 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
750 d.GeomDestroy(Shell); 854 d.GeomDestroy(bonebox);
751 Shell = IntPtr.Zero; 855 bonebox = IntPtr.Zero;
856 }
857
858 }
859
860 public bool Collide(IntPtr me, bool reverse, ref d.ContactGeom contact)
861 {
862
863 if (me == bonebox) // inner bone
864 {
865 if (contact.pos.Z - _position.Z < boneOff)
866 IsColliding = true;
867 return true;
752 } 868 }
869
870 if (me == topbox) // keep a box head
871 return true;
872
873 // rotate elipsoide assuming only rotation around Z
874 float ca = m_orientation.W * m_orientation.W - m_orientation.Z * m_orientation.Z;
875 float sa = 2 * m_orientation.W * m_orientation.Z;
876
877 float isx;
878 float isy;
879
880 if (me == feetbox) // feet have narrow bounds
881 {
882
883 isx = m_invElipSizeX * invFeetScale;
884 isy = m_invElipSizeY * invFeetScale;
885 }
886 else
887 {
888 isx = m_invElipSizeX;
889 isy = m_invElipSizeY;
890 }
891
892 float a = isx * ca - isy * sa;
893 float b = isx * sa + isy * ca;
894
895 float offx = contact.pos.X - _position.X;
896 float er = offx * a;
897 er *= er;
898
899 float offy = contact.pos.Y - _position.Y;
900 float ty = offy * b;
901 er += ty * ty;
902
903 if (me == midbox)
904 {
905 if (er > 4.0f) // no collision
906 return false;
907 if (er < 0.2f)
908 return true;
909
910 float t = offx * offx + offy * offy;
911 t = (float)Math.Sqrt(t);
912 t = 1 / t;
913 offx *= t;
914 offy *= t;
915
916 if (reverse)
917 {
918 contact.normal.X = offx;
919 contact.normal.Y = offy;
920 }
921 else
922 {
923 contact.normal.X = -offx;
924 contact.normal.Y = -offy;
925 }
926
927 contact.normal.Z = 0;
928 return true;
929 }
930
931 else if (me == feetbox)
932 {
933 float c = feetSZ * 2;
934 float h = contact.pos.Z - _position.Z;
935 float offz = h - feetOff; // distance from top of feetbox
936
937 float tz = offz / c;
938 er += tz * tz;
939
940 if (er > 4.0f) // no collision
941 return false;
942
943 if (er > 0.2f)
944 {
945 float t = offx * offx + offy * offy + offz * offz;
946 t = (float)Math.Sqrt(t);
947 t = 1 / t;
948 offx *= t;
949 offy *= t;
950 offz *= t;
951
952 if (reverse)
953 {
954 contact.normal.X = offx;
955 contact.normal.Y = offy;
956 contact.normal.Z = offz;
957 }
958 else
959 {
960 contact.normal.X = -offx;
961 contact.normal.Y = -offy;
962 contact.normal.Z = -offz;
963 }
964 }
965
966 if(h < boneOff)
967 IsColliding = true;
968 }
969 else
970 return false;
971
972 return true;
753 } 973 }
754 974
755 /// <summary> 975 /// <summary>
@@ -769,10 +989,10 @@ namespace OpenSim.Region.Physics.OdePlugin
769 // so force it back to identity 989 // so force it back to identity
770 990
771 d.Quaternion qtmp; 991 d.Quaternion qtmp;
772 qtmp.W = 1; 992 qtmp.W = m_orientation.W;
773 qtmp.X = 0; 993 qtmp.X = m_orientation.X;
774 qtmp.Y = 0; 994 qtmp.Y = m_orientation.Y;
775 qtmp.Z = 0; 995 qtmp.Z = m_orientation.Z;
776 d.BodySetQuaternion(Body, ref qtmp); 996 d.BodySetQuaternion(Body, ref qtmp);
777 997
778 if (m_pidControllerActive == false) 998 if (m_pidControllerActive == false)
@@ -836,9 +1056,8 @@ namespace OpenSim.Region.Physics.OdePlugin
836 //****************************************** 1056 //******************************************
837 // colide with land 1057 // colide with land
838 d.AABB aabb; 1058 d.AABB aabb;
839 d.GeomGetAABB(Shell, out aabb); 1059 d.GeomGetAABB(feetbox, out aabb);
840 float chrminZ = aabb.MinZ; 1060 float chrminZ = aabb.MinZ - 0.04f; // move up a bit
841
842 Vector3 posch = localpos; 1061 Vector3 posch = localpos;
843 1062
844 float ftmp; 1063 float ftmp;
@@ -1176,20 +1395,14 @@ namespace OpenSim.Region.Physics.OdePlugin
1176 { 1395 {
1177 if (NewStatus) 1396 if (NewStatus)
1178 { 1397 {
1179 // Create avatar capsule and related ODE data 1398 AvatarGeomAndBodyDestroy();
1180 if ((Shell != IntPtr.Zero))
1181 {
1182 // a lost shell ?
1183 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
1184 + (Shell != IntPtr.Zero ? "Shell " : "")
1185 + (Body != IntPtr.Zero ? "Body " : "")
1186 + (Amotor != IntPtr.Zero ? "Amotor " : ""));
1187 AvatarGeomAndBodyDestroy();
1188 }
1189 1399
1190 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z); 1400 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z);
1191 1401
1192 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; 1402 _parent_scene.actor_name_map[topbox] = (PhysicsActor)this;
1403 _parent_scene.actor_name_map[midbox] = (PhysicsActor)this;
1404 _parent_scene.actor_name_map[feetbox] = (PhysicsActor)this;
1405 _parent_scene.actor_name_map[bonebox] = (PhysicsActor)this;
1193 _parent_scene.AddCharacter(this); 1406 _parent_scene.AddCharacter(this);
1194 } 1407 }
1195 else 1408 else
@@ -1218,37 +1431,29 @@ namespace OpenSim.Region.Physics.OdePlugin
1218 { 1431 {
1219 } 1432 }
1220 1433
1221 private void changeSize(Vector3 Size) 1434 private void changeSize(Vector3 pSize)
1222 { 1435 {
1223 if (Size.IsFinite()) 1436 if (pSize.IsFinite())
1224 { 1437 {
1225 float caplen = Size.Z; 1438 // for now only look to Z changes since viewers also don't change X and Y
1439 if (pSize.Z != m_size.Z)
1440 {
1441 AvatarGeomAndBodyDestroy();
1226 1442
1227 caplen = caplen * 1.15f - CAPSULE_RADIUS * 2.0f;
1228 1443
1229 if (caplen != CAPSULE_LENGTH) 1444 float oldsz = m_size.Z;
1230 { 1445 m_size = pSize;
1231 if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero)
1232 {
1233 AvatarGeomAndBodyDestroy();
1234 1446
1235 float prevCapsule = CAPSULE_LENGTH;
1236 CAPSULE_LENGTH = caplen;
1237 1447
1238 AvatarGeomAndBodyCreation(_position.X, _position.Y, 1448 AvatarGeomAndBodyCreation(_position.X, _position.Y,
1239 _position.Z + (CAPSULE_LENGTH - prevCapsule) * 0.5f); 1449 _position.Z + (m_size.Z - oldsz) * 0.5f);
1240 1450
1241 Velocity = Vector3.Zero; 1451 Velocity = Vector3.Zero;
1242 1452
1243 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; 1453 _parent_scene.actor_name_map[topbox] = (PhysicsActor)this;
1244 } 1454 _parent_scene.actor_name_map[midbox] = (PhysicsActor)this;
1245 else 1455 _parent_scene.actor_name_map[feetbox] = (PhysicsActor)this;
1246 { 1456 _parent_scene.actor_name_map[bonebox] = (PhysicsActor)this;
1247 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
1248 + (Shell == IntPtr.Zero ? "Shell " : "")
1249 + (Body == IntPtr.Zero ? "Body " : "")
1250 + (Amotor == IntPtr.Zero ? "Amotor " : ""));
1251 }
1252 } 1457 }
1253 m_freemove = false; 1458 m_freemove = false;
1254 m_pidControllerActive = true; 1459 m_pidControllerActive = true;
@@ -1270,6 +1475,14 @@ namespace OpenSim.Region.Physics.OdePlugin
1270 1475
1271 private void changeOrientation(Quaternion newOri) 1476 private void changeOrientation(Quaternion newOri)
1272 { 1477 {
1478 d.Quaternion myrot = new d.Quaternion();
1479 myrot.X = newOri.X;
1480 myrot.Y = newOri.Y;
1481 myrot.Z = newOri.Z;
1482 myrot.W = newOri.W;
1483 float t = d.JointGetAMotorAngle(Amotor, 2);
1484 d.BodySetQuaternion(Body,ref myrot);
1485 m_orientation = newOri;
1273 } 1486 }
1274 1487
1275 private void changeVelocity(Vector3 newVel) 1488 private void changeVelocity(Vector3 newVel)
@@ -1359,7 +1572,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1359 1572
1360 public bool DoAChange(changes what, object arg) 1573 public bool DoAChange(changes what, object arg)
1361 { 1574 {
1362 if (Shell == IntPtr.Zero && what != changes.Add && what != changes.Remove) 1575 if (topbox == IntPtr.Zero && what != changes.Add && what != changes.Remove)
1363 { 1576 {
1364 return false; 1577 return false;
1365 } 1578 }
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
index dc247a9..7dddab6 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Region.Physics.OdePlugin
84 84
85 private Vector3 _position; 85 private Vector3 _position;
86 private Vector3 _velocity; 86 private Vector3 _velocity;
87 private Vector3 _torque; 87 private Vector3 m_torque;
88 private Vector3 m_lastVelocity; 88 private Vector3 m_lastVelocity;
89 private Vector3 m_lastposition; 89 private Vector3 m_lastposition;
90 private Vector3 m_rotationalVelocity; 90 private Vector3 m_rotationalVelocity;
@@ -597,7 +597,7 @@ namespace OpenSim.Region.Physics.OdePlugin
597 if (!IsPhysical || Body == IntPtr.Zero) 597 if (!IsPhysical || Body == IntPtr.Zero)
598 return Vector3.Zero; 598 return Vector3.Zero;
599 599
600 return _torque; 600 return m_torque;
601 } 601 }
602 602
603 set 603 set
@@ -2425,10 +2425,10 @@ namespace OpenSim.Region.Physics.OdePlugin
2425 { 2425 {
2426 if (!childPrim) 2426 if (!childPrim)
2427 { 2427 {
2428 m_force = Vector3.Zero; 2428// m_force = Vector3.Zero;
2429 m_forceacc = Vector3.Zero; 2429 m_forceacc = Vector3.Zero;
2430 m_angularForceacc = Vector3.Zero; 2430 m_angularForceacc = Vector3.Zero;
2431 _torque = Vector3.Zero; 2431// m_torque = Vector3.Zero;
2432 _velocity = Vector3.Zero; 2432 _velocity = Vector3.Zero;
2433 _acceleration = Vector3.Zero; 2433 _acceleration = Vector3.Zero;
2434 m_rotationalVelocity = Vector3.Zero; 2434 m_rotationalVelocity = Vector3.Zero;
@@ -2968,7 +2968,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2968 d.BodyEnable(Body); 2968 d.BodyEnable(Body);
2969 2969
2970 } 2970 }
2971 _torque = newtorque; 2971 m_torque = newtorque;
2972 } 2972 }
2973 } 2973 }
2974 2974
@@ -3364,7 +3364,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3364 3364
3365 Vector3 trq; 3365 Vector3 trq;
3366 3366
3367 trq = _torque; 3367 trq = m_torque;
3368 trq += m_angularForceacc; 3368 trq += m_angularForceacc;
3369 m_angularForceacc = Vector3.Zero; 3369 m_angularForceacc = Vector3.Zero;
3370 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0) 3370 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0)
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
index 54bc29f..003a91c 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
@@ -840,6 +840,8 @@ namespace OpenSim.Region.Physics.OdePlugin
840 { 840 {
841 case (int)ActorTypes.Agent: 841 case (int)ActorTypes.Agent:
842 { 842 {
843 dop1foot = true;
844
843 AvanormOverride = true; 845 AvanormOverride = true;
844 Vector3 tmp = p2.Position - p1.Position; 846 Vector3 tmp = p2.Position - p1.Position;
845 normoverride = p2.Velocity - p1.Velocity; 847 normoverride = p2.Velocity - p1.Velocity;
@@ -883,6 +885,10 @@ namespace OpenSim.Region.Physics.OdePlugin
883 switch (p2.PhysicsActorType) 885 switch (p2.PhysicsActorType)
884 { 886 {
885 case (int)ActorTypes.Agent: 887 case (int)ActorTypes.Agent:
888
889
890 dop2foot = true;
891
886 AvanormOverride = true; 892 AvanormOverride = true;
887 893
888 Vector3 tmp = p2.Position - p1.Position; 894 Vector3 tmp = p2.Position - p1.Position;
@@ -1017,6 +1023,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1017 IntPtr Joint; 1023 IntPtr Joint;
1018 1024
1019 int i = 0; 1025 int i = 0;
1026 int ncontacts = 0;
1020 while(true) 1027 while(true)
1021 { 1028 {
1022 1029
@@ -1031,7 +1038,28 @@ namespace OpenSim.Region.Physics.OdePlugin
1031 else 1038 else
1032 1039
1033 { 1040 {
1041 if(dop1foot)
1042 {
1043 if (!(((OdeCharacter)p1).Collide(g1,false, ref curContact)))
1044 {
1045 if (++i >= count)
1046 break;
1047 else
1048 continue;
1049 }
1050 }
1051 else if(dop2foot)
1052 {
1053 if(!(((OdeCharacter) p2).Collide(g2,true,ref curContact)))
1054 {
1055 if (++i >= count)
1056 break;
1057 else
1058 continue;
1059 }
1060 }
1034 1061
1062/*
1035 if (AvanormOverride) 1063 if (AvanormOverride)
1036 { 1064 {
1037 if (curContact.depth > 0.3f) 1065 if (curContact.depth > 0.3f)
@@ -1081,34 +1109,31 @@ namespace OpenSim.Region.Physics.OdePlugin
1081 { 1109 {
1082 float sz = p2.Size.Z; 1110 float sz = p2.Size.Z;
1083 Vector3 vtmp = p2.Position; 1111 Vector3 vtmp = p2.Position;
1084 float ppos = curContact.pos.Z - vtmp.Z + (sz - avCapRadius) * 0.5f; 1112 vtmp.Z -= sz * 0.5f;
1113 vtmp.Z += 0.5f;
1114 float ppos = vtmp.Z - curContact.pos.Z;
1085 if (ppos > 0f) 1115 if (ppos > 0f)
1086 { 1116 {
1087 if (!p2.Flying) 1117 if (!p2.Flying)
1088 { 1118 {
1089 d.AABB aabb;
1090 d.GeomGetAABB(g1, out aabb);
1091 float tmp = vtmp.Z - sz * .18f; 1119 float tmp = vtmp.Z - sz * .18f;
1092 1120 vtmp.X = curContact.pos.X - vtmp.X;
1093 if (aabb.MaxZ < tmp) 1121 vtmp.Y = curContact.pos.Y - vtmp.Y;
1094 { 1122 vtmp.Z = curContact.pos.Z - vtmp.Z;
1095 vtmp.X = curContact.pos.X - vtmp.X; 1123 vtmp.Normalize();
1096 vtmp.Y = curContact.pos.Y - vtmp.Y; 1124 curContact.normal.X = vtmp.X;
1097 vtmp.Z = -0.2f; 1125 curContact.normal.Y = vtmp.Y;
1098 vtmp.Normalize(); 1126 curContact.normal.Z = vtmp.Z;
1099 curContact.normal.X = vtmp.X;
1100 curContact.normal.Y = vtmp.Y;
1101 curContact.normal.Z = vtmp.Z;
1102 }
1103 } 1127 }
1104 } 1128 }
1105 else 1129// else
1106 p2.IsColliding = true; 1130 p2.IsColliding = true;
1107 1131
1108 } 1132 }
1109 } 1133 }
1110 } 1134 }
1111 1135*/
1136 ncontacts++;
1112 Joint = CreateContacJoint(ref curContact, mu, bounce, cfm, erpscale, dscale); 1137 Joint = CreateContacJoint(ref curContact, mu, bounce, cfm, erpscale, dscale);
1113 d.JointAttach(Joint, b1, b2); 1138 d.JointAttach(Joint, b1, b2);
1114 1139
@@ -1134,7 +1159,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1134 } 1159 }
1135 } 1160 }
1136 1161
1137 collision_accounting_events(p1, p2, maxDepthContact); 1162 if(ncontacts > 0)
1163 collision_accounting_events(p1, p2, maxDepthContact);
1138 1164
1139/* 1165/*
1140 if (notskipedcount > geomContactPointsStartthrottle) 1166 if (notskipedcount > geomContactPointsStartthrottle)
@@ -1234,14 +1260,17 @@ namespace OpenSim.Region.Physics.OdePlugin
1234 { 1260 {
1235 foreach (OdeCharacter chr in _characters) 1261 foreach (OdeCharacter chr in _characters)
1236 { 1262 {
1237 if (chr == null || chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero) 1263 if (chr == null || chr.Body == IntPtr.Zero)
1238 continue; 1264 continue;
1239 1265
1240 chr.IsColliding = false; 1266 chr.IsColliding = false;
1241 // chr.CollidingGround = false; not done here 1267 // chr.CollidingGround = false; not done here
1242 chr.CollidingObj = false; 1268 chr.CollidingObj = false;
1243 // do colisions with static space 1269 // do colisions with static space
1244 d.SpaceCollide2(StaticSpace, chr.Shell, IntPtr.Zero, nearCallback); 1270 d.SpaceCollide2(StaticSpace, chr.topbox, IntPtr.Zero, nearCallback);
1271 d.SpaceCollide2(StaticSpace, chr.midbox, IntPtr.Zero, nearCallback);
1272 d.SpaceCollide2(StaticSpace, chr.feetbox, IntPtr.Zero, nearCallback);
1273 d.SpaceCollide2(StaticSpace, chr.bonebox, IntPtr.Zero, nearCallback);
1245 // no coll with gnd 1274 // no coll with gnd
1246 } 1275 }
1247 } 1276 }
@@ -1334,7 +1363,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1334 pos.X = position.X; 1363 pos.X = position.X;
1335 pos.Y = position.Y; 1364 pos.Y = position.Y;
1336 pos.Z = position.Z; 1365 pos.Z = position.Z;
1337 OdeCharacter newAv = new OdeCharacter(avName, this, pos, size, avPIDD, avPIDP, avCapRadius, avDensity, avMovementDivisorWalk, avMovementDivisorRun); 1366 OdeCharacter newAv = new OdeCharacter(avName, this, pos, size, avPIDD, avPIDP, avDensity, avMovementDivisorWalk, avMovementDivisorRun);
1338 newAv.Flying = isFlying; 1367 newAv.Flying = isFlying;
1339 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; 1368 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1340 1369
diff --git a/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs b/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..085eb59
--- /dev/null
+++ b/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.RegionCombinerModule")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("73c166d2-c9d8-4ab8-af4e-89c41b4b58a9")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 3144d76..905540d 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -39,11 +39,8 @@ using OpenSim.Framework.Console;
39using OpenSim.Region.Physics.Manager; 39using OpenSim.Region.Physics.Manager;
40using Mono.Addins; 40using Mono.Addins;
41 41
42[assembly: Addin("RegionCombinerModule", "0.1")]
43[assembly: AddinDependency("OpenSim", "0.5")]
44namespace OpenSim.Region.RegionCombinerModule 42namespace OpenSim.Region.RegionCombinerModule
45{ 43{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
47 public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule 44 public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule
48 { 45 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -722,21 +719,21 @@ namespace OpenSim.Region.RegionCombinerModule
722 rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn); 719 rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn);
723 720
724 // Sets up the CoarseLocationUpdate forwarder for this root region 721 // Sets up the CoarseLocationUpdate forwarder for this root region
725 scene.EventManager.OnNewPresence += SetCourseLocationDelegate; 722 scene.EventManager.OnNewPresence += SetCoarseLocationDelegate;
726 723
727 // Adds this root region to a dictionary of regions that are connectable 724 // Adds this root region to a dictionary of regions that are connectable
728 m_regions.Add(scene.RegionInfo.originRegionID, rootConn); 725 m_regions.Add(scene.RegionInfo.originRegionID, rootConn);
729 } 726 }
730 } 727 }
731 728
732 private void SetCourseLocationDelegate(ScenePresence presence) 729 private void SetCoarseLocationDelegate(ScenePresence presence)
733 { 730 {
734 presence.SetSendCourseLocationMethod(SendCourseLocationUpdates); 731 presence.SetSendCoarseLocationMethod(SendCoarseLocationUpdates);
735 } 732 }
736 733
737 // This delegate was refactored for non-combined regions. 734 // This delegate was refactored for non-combined regions.
738 // This combined region version will not use the pre-compiled lists of locations and ids 735 // This combined region version will not use the pre-compiled lists of locations and ids
739 private void SendCourseLocationUpdates(UUID sceneId, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs) 736 private void SendCoarseLocationUpdates(UUID sceneId, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
740 { 737 {
741 RegionConnections connectiondata = null; 738 RegionConnections connectiondata = null;
742 lock (m_regions) 739 lock (m_regions)
@@ -759,18 +756,18 @@ namespace OpenSim.Region.RegionCombinerModule
759 } 756 }
760 }); 757 });
761 758
762 DistributeCourseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); 759 DistributeCoarseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence);
763 } 760 }
764 761
765 private void DistributeCourseLocationUpdates(List<Vector3> locations, List<UUID> uuids, 762 private void DistributeCoarseLocationUpdates(List<Vector3> locations, List<UUID> uuids,
766 RegionConnections connectiondata, ScenePresence rootPresence) 763 RegionConnections connectiondata, ScenePresence rootPresence)
767 { 764 {
768 RegionData[] rdata = connectiondata.ConnectedRegions.ToArray(); 765 RegionData[] rdata = connectiondata.ConnectedRegions.ToArray();
769 //List<IClientAPI> clients = new List<IClientAPI>(); 766 //List<IClientAPI> clients = new List<IClientAPI>();
770 Dictionary<Vector2, RegionCourseLocationStruct> updates = new Dictionary<Vector2, RegionCourseLocationStruct>(); 767 Dictionary<Vector2, RegionCoarseLocationStruct> updates = new Dictionary<Vector2, RegionCoarseLocationStruct>();
771 768
772 // Root Region entry 769 // Root Region entry
773 RegionCourseLocationStruct rootupdatedata = new RegionCourseLocationStruct(); 770 RegionCoarseLocationStruct rootupdatedata = new RegionCoarseLocationStruct();
774 rootupdatedata.Locations = new List<Vector3>(); 771 rootupdatedata.Locations = new List<Vector3>();
775 rootupdatedata.Uuids = new List<UUID>(); 772 rootupdatedata.Uuids = new List<UUID>();
776 rootupdatedata.Offset = Vector2.Zero; 773 rootupdatedata.Offset = Vector2.Zero;
@@ -784,7 +781,7 @@ namespace OpenSim.Region.RegionCombinerModule
784 foreach (RegionData regiondata in rdata) 781 foreach (RegionData regiondata in rdata)
785 { 782 {
786 Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y); 783 Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y);
787 RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); 784 RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct();
788 updatedata.Locations = new List<Vector3>(); 785 updatedata.Locations = new List<Vector3>();
789 updatedata.Uuids = new List<UUID>(); 786 updatedata.Uuids = new List<UUID>();
790 updatedata.Offset = offset; 787 updatedata.Offset = offset;
@@ -810,7 +807,7 @@ namespace OpenSim.Region.RegionCombinerModule
810 if (!updates.ContainsKey(offset)) 807 if (!updates.ContainsKey(offset))
811 { 808 {
812 // This shouldn't happen 809 // This shouldn't happen
813 RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); 810 RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct();
814 updatedata.Locations = new List<Vector3>(); 811 updatedata.Locations = new List<Vector3>();
815 updatedata.Uuids = new List<UUID>(); 812 updatedata.Uuids = new List<UUID>();
816 updatedata.Offset = offset; 813 updatedata.Offset = offset;
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs
index 53a678f..224ac99 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs
@@ -33,7 +33,7 @@ using OpenSim.Framework;
33namespace OpenSim.Region.RegionCombinerModule 33namespace OpenSim.Region.RegionCombinerModule
34{ 34{
35 35
36 struct RegionCourseLocationStruct 36 struct RegionCoarseLocationStruct
37 { 37 {
38 public List<Vector3> Locations; 38 public List<Vector3> Locations;
39 public List<UUID> Uuids; 39 public List<UUID> Uuids;
diff --git a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml
new file mode 100644
index 0000000..13cb8b6
--- /dev/null
+++ b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml
@@ -0,0 +1,14 @@
1<Addin id="OpenSim.RegionModules.RegionCombinerModule" version="0.3">
2 <Runtime>
3 <Import assembly="OpenSim.Region.RegionCombinerModule.dll"/>
4 </Runtime>
5
6 <Dependencies>
7 <Addin id="OpenSim" version="0.5" />
8 </Dependencies>
9
10 <Extension path = "/OpenSim/RegionModules">
11 <RegionModule id="RegionCombinerModule" type="OpenSim.Region.RegionCombinerModule.RegionCombinerModule" />
12 </Extension>
13
14</Addin>
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index 94fd940..6879ebb 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -317,8 +317,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
317 comms.DeleteListener(itemID); 317 comms.DeleteListener(itemID);
318 318
319 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>(); 319 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>();
320 xmlrpc.DeleteChannels(itemID); 320 if (xmlrpc != null)
321 xmlrpc.CancelSRDRequests(itemID); 321 {
322 xmlrpc.DeleteChannels(itemID);
323 xmlrpc.CancelSRDRequests(itemID);
324 }
322 325
323 // Remove Sensors 326 // Remove Sensors
324 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID); 327 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 82de06f..6b63d94 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -59,6 +59,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
59using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; 59using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
60using PrimType = OpenSim.Region.Framework.Scenes.PrimType; 60using PrimType = OpenSim.Region.Framework.Scenes.PrimType;
61using AssetLandmark = OpenSim.Framework.AssetLandmark; 61using AssetLandmark = OpenSim.Framework.AssetLandmark;
62using RegionFlags = OpenSim.Framework.RegionFlags;
62 63
63using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; 64using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
64using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; 65using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
@@ -112,6 +113,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
112 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = 113 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
113 new Dictionary<UUID, UserInfoCacheEntry>(); 114 new Dictionary<UUID, UserInfoCacheEntry>();
114 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 115 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
116 protected ISoundModule m_SoundModule = null;
115 117
116// protected Timer m_ShoutSayTimer; 118// protected Timer m_ShoutSayTimer;
117 protected int m_SayShoutCount = 0; 119 protected int m_SayShoutCount = 0;
@@ -159,6 +161,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
159 m_TransferModule = 161 m_TransferModule =
160 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); 162 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
161 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); 163 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
164 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
162 165
163 AsyncCommands = new AsyncCommandManager(ScriptEngine); 166 AsyncCommands = new AsyncCommandManager(ScriptEngine);
164 } 167 }
@@ -341,7 +344,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
341 return GetLinkParts(m_host, linkType); 344 return GetLinkParts(m_host, linkType);
342 } 345 }
343 346
344 private List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) 347 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
345 { 348 {
346 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 349 List<SceneObjectPart> ret = new List<SceneObjectPart>();
347 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 350 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
@@ -426,12 +429,40 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
426 return key; 429 return key;
427 } 430 }
428 431
429 // convert a LSL_Rotation to a Quaternion 432 /// <summary>
430 public static Quaternion Rot2Quaternion(LSL_Rotation r) 433 /// Return the UUID of the asset matching the specified key or name
434 /// and asset type.
435 /// </summary>
436 /// <param name="k"></param>
437 /// <param name="type"></param>
438 /// <returns></returns>
439 protected UUID KeyOrName(string k, AssetType type)
431 { 440 {
432 Quaternion q = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); 441 UUID key;
433 q.Normalize(); 442
434 return q; 443 if (!UUID.TryParse(k, out key))
444 {
445 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k);
446 if (item != null && item.Type == (int)type)
447 key = item.AssetID;
448 }
449 else
450 {
451 lock (m_host.TaskInventory)
452 {
453 foreach (KeyValuePair<UUID, TaskInventoryItem> item in m_host.TaskInventory)
454 {
455 if (item.Value.Type == (int)type && item.Value.Name == k)
456 {
457 key = item.Value.ItemID;
458 break;
459 }
460 }
461 }
462 }
463
464
465 return key;
435 } 466 }
436 467
437 //These are the implementations of the various ll-functions used by the LSL scripts. 468 //These are the implementations of the various ll-functions used by the LSL scripts.
@@ -1240,9 +1271,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1240 public LSL_Float llGround(LSL_Vector offset) 1271 public LSL_Float llGround(LSL_Vector offset)
1241 { 1272 {
1242 m_host.AddScriptLPS(1); 1273 m_host.AddScriptLPS(1);
1243 Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, 1274 Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
1244 (float)offset.y,
1245 (float)offset.z);
1246 1275
1247 //Get the slope normal. This gives us the equation of the plane tangent to the slope. 1276 //Get the slope normal. This gives us the equation of the plane tangent to the slope.
1248 LSL_Vector vsn = llGroundNormal(offset); 1277 LSL_Vector vsn = llGroundNormal(offset);
@@ -1492,31 +1521,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1492 if (part == null || part.ParentGroup.IsDeleted) 1521 if (part == null || part.ParentGroup.IsDeleted)
1493 return; 1522 return;
1494 1523
1495 if (scale.x < 0.01) 1524 // First we need to check whether or not we need to clamp the size of a physics-enabled prim
1496 scale.x = 0.01;
1497 if (scale.y < 0.01)
1498 scale.y = 0.01;
1499 if (scale.z < 0.01)
1500 scale.z = 0.01;
1501
1502 PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; 1525 PhysicsActor pa = part.ParentGroup.RootPart.PhysActor;
1503
1504 if (pa != null && pa.IsPhysical) 1526 if (pa != null && pa.IsPhysical)
1505 { 1527 {
1506 if (scale.x > World.m_maxPhys) 1528 scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x));
1507 scale.x = World.m_maxPhys; 1529 scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y));
1508 if (scale.y > World.m_maxPhys) 1530 scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z));
1509 scale.y = World.m_maxPhys; 1531 }
1510 if (scale.z > World.m_maxPhys) 1532 else
1511 scale.z = World.m_maxPhys; 1533 {
1534 // If not physical, then we clamp the scale to the non-physical min/max
1535 scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x));
1536 scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y));
1537 scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z));
1512 } 1538 }
1513
1514 if (scale.x > World.m_maxNonphys)
1515 scale.x = World.m_maxNonphys;
1516 if (scale.y > World.m_maxNonphys)
1517 scale.y = World.m_maxNonphys;
1518 if (scale.z > World.m_maxNonphys)
1519 scale.z = World.m_maxNonphys;
1520 1539
1521 Vector3 tmp = part.Scale; 1540 Vector3 tmp = part.Scale;
1522 tmp.X = (float)scale.x; 1541 tmp.X = (float)scale.x;
@@ -1590,7 +1609,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1590 if (face == ScriptBaseClass.ALL_SIDES) 1609 if (face == ScriptBaseClass.ALL_SIDES)
1591 face = SceneObjectPart.ALL_SIDES; 1610 face = SceneObjectPart.ALL_SIDES;
1592 1611
1593 m_host.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 1612 m_host.SetFaceColorAlpha(face, color, null);
1594 } 1613 }
1595 1614
1596 public void SetTexGen(SceneObjectPart part, int face,int style) 1615 public void SetTexGen(SceneObjectPart part, int face,int style)
@@ -2202,7 +2221,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2202 pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region. 2221 pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
2203 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. 2222 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
2204 pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region. 2223 pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
2205 pos.z > 4096 // return FALSE if altitude than 4096m 2224 pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
2206 ) 2225 )
2207 ) 2226 )
2208 { 2227 {
@@ -2213,14 +2232,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2213 // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read. 2232 // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read.
2214 2233
2215 Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition; 2234 Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition;
2216 LandData here = World.GetLandData((float)objectPos.X, (float)objectPos.Y); 2235 LandData here = World.GetLandData(objectPos);
2217 LandData there = World.GetLandData((float)pos.x, (float)pos.y); 2236 LandData there = World.GetLandData(pos);
2218 2237
2219 // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits. 2238 // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits.
2220 2239
2221 bool sameParcel = here.GlobalID == there.GlobalID; 2240 bool sameParcel = here.GlobalID == there.GlobalID;
2222 2241
2223 if (!sameParcel && !World.Permissions.CanObjectEntry(m_host.UUID, false, new Vector3((float)pos.x, (float)pos.y, (float)pos.z))) 2242 if (!sameParcel && !World.Permissions.CanRezObject(
2243 m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos))
2224 { 2244 {
2225 return 0; 2245 return 0;
2226 } 2246 }
@@ -2279,16 +2299,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2279 if (part.ParentGroup.RootPart == part) 2299 if (part.ParentGroup.RootPart == part)
2280 { 2300 {
2281 SceneObjectGroup parent = part.ParentGroup; 2301 SceneObjectGroup parent = part.ParentGroup;
2282 Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z); 2302 if (!World.Permissions.CanObjectEntry(parent.UUID, false, (Vector3)toPos))
2283 if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest))
2284 return; 2303 return;
2285 Util.FireAndForget(delegate(object x) { 2304 Util.FireAndForget(delegate(object x) {
2286 parent.UpdateGroupPosition(dest); 2305 parent.UpdateGroupPosition((Vector3)toPos);
2287 }); 2306 });
2288 } 2307 }
2289 else 2308 else
2290 { 2309 {
2291 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z); 2310 part.OffsetPosition = (Vector3)toPos;
2292 SceneObjectGroup parent = part.ParentGroup; 2311 SceneObjectGroup parent = part.ParentGroup;
2293 parent.HasGroupChanged = true; 2312 parent.HasGroupChanged = true;
2294 parent.ScheduleGroupForTerseUpdate(); 2313 parent.ScheduleGroupForTerseUpdate();
@@ -2298,8 +2317,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2298 public LSL_Vector llGetPos() 2317 public LSL_Vector llGetPos()
2299 { 2318 {
2300 m_host.AddScriptLPS(1); 2319 m_host.AddScriptLPS(1);
2301 Vector3 pos = m_host.GetWorldPosition(); 2320 return m_host.GetWorldPosition();
2302 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2303 } 2321 }
2304 2322
2305 public LSL_Vector llGetLocalPos() 2323 public LSL_Vector llGetLocalPos()
@@ -2326,7 +2344,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2326 pos = part.AbsolutePosition; 2344 pos = part.AbsolutePosition;
2327 } 2345 }
2328 2346
2329 return new LSL_Vector(pos.X, pos.Y, pos.Z); 2347// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
2348
2349 return new LSL_Vector(pos);
2330 } 2350 }
2331 2351
2332 public void llSetRot(LSL_Rotation rot) 2352 public void llSetRot(LSL_Rotation rot)
@@ -2334,26 +2354,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2334 m_host.AddScriptLPS(1); 2354 m_host.AddScriptLPS(1);
2335 2355
2336 // try to let this work as in SL... 2356 // try to let this work as in SL...
2337 if (m_host.LinkNum < 2) 2357 if (m_host.ParentID == 0)
2338 { 2358 {
2339 // Special case: If we are root, rotate complete SOG to new 2359 // special case: If we are root, rotate complete SOG to new rotation
2340 // rotation. 2360 SetRot(m_host, rot);
2341 // We are root if the link number is 0 (single prim) or 1
2342 // (root prim). ParentID may be nonzero in attachments and
2343 // using it would cause attachments and HUDs to rotate
2344 // to the wrong positions.
2345
2346 SetRot(m_host, Rot2Quaternion(rot));
2347 } 2361 }
2348 else 2362 else
2349 { 2363 {
2350 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. 2364 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
2351 SceneObjectPart rootPart; 2365 SceneObjectPart rootPart = m_host.ParentGroup.RootPart;
2352 if (m_host.ParentGroup != null) // better safe than sorry 2366 if (rootPart != null) // better safe than sorry
2353 { 2367 {
2354 rootPart = m_host.ParentGroup.RootPart; 2368 SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot);
2355 if (rootPart != null)
2356 SetRot(m_host, rootPart.RotationOffset * Rot2Quaternion(rot));
2357 } 2369 }
2358 } 2370 }
2359 2371
@@ -2363,8 +2375,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2363 public void llSetLocalRot(LSL_Rotation rot) 2375 public void llSetLocalRot(LSL_Rotation rot)
2364 { 2376 {
2365 m_host.AddScriptLPS(1); 2377 m_host.AddScriptLPS(1);
2366 2378 SetRot(m_host, rot);
2367 SetRot(m_host, Rot2Quaternion(rot));
2368 ScriptSleep(200); 2379 ScriptSleep(200);
2369 } 2380 }
2370 2381
@@ -2476,7 +2487,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2476 if (local != 0) 2487 if (local != 0)
2477 force *= llGetRot(); 2488 force *= llGetRot();
2478 2489
2479 m_host.ParentGroup.RootPart.SetForce(new Vector3((float)force.x, (float)force.y, (float)force.z)); 2490 m_host.ParentGroup.RootPart.SetForce(force);
2480 } 2491 }
2481 } 2492 }
2482 2493
@@ -2488,10 +2499,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2488 2499
2489 if (!m_host.ParentGroup.IsDeleted) 2500 if (!m_host.ParentGroup.IsDeleted)
2490 { 2501 {
2491 Vector3 tmpForce = m_host.ParentGroup.RootPart.GetForce(); 2502 force = m_host.ParentGroup.RootPart.GetForce();
2492 force.x = tmpForce.X;
2493 force.y = tmpForce.Y;
2494 force.z = tmpForce.Z;
2495 } 2503 }
2496 2504
2497 return force; 2505 return force;
@@ -2500,8 +2508,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2500 public LSL_Integer llTarget(LSL_Vector position, double range) 2508 public LSL_Integer llTarget(LSL_Vector position, double range)
2501 { 2509 {
2502 m_host.AddScriptLPS(1); 2510 m_host.AddScriptLPS(1);
2503 return m_host.ParentGroup.registerTargetWaypoint( 2511 return m_host.ParentGroup.registerTargetWaypoint(position,
2504 new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range); 2512 (float)range);
2505 } 2513 }
2506 2514
2507 public void llTargetRemove(int number) 2515 public void llTargetRemove(int number)
@@ -2513,8 +2521,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2513 public LSL_Integer llRotTarget(LSL_Rotation rot, double error) 2521 public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
2514 { 2522 {
2515 m_host.AddScriptLPS(1); 2523 m_host.AddScriptLPS(1);
2516 return m_host.ParentGroup.registerRotTargetWaypoint( 2524 return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error);
2517 new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), (float)error);
2518 } 2525 }
2519 2526
2520 public void llRotTargetRemove(int number) 2527 public void llRotTargetRemove(int number)
@@ -2526,7 +2533,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2526 public void llMoveToTarget(LSL_Vector target, double tau) 2533 public void llMoveToTarget(LSL_Vector target, double tau)
2527 { 2534 {
2528 m_host.AddScriptLPS(1); 2535 m_host.AddScriptLPS(1);
2529 m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau); 2536 m_host.MoveToTarget(target, (float)tau);
2530 } 2537 }
2531 2538
2532 public void llStopMoveToTarget() 2539 public void llStopMoveToTarget()
@@ -2539,7 +2546,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2539 { 2546 {
2540 m_host.AddScriptLPS(1); 2547 m_host.AddScriptLPS(1);
2541 //No energy force yet 2548 //No energy force yet
2542 Vector3 v = new Vector3((float)force.x, (float)force.y, (float)force.z); 2549 Vector3 v = force;
2543 if (v.Length() > 20000.0f) 2550 if (v.Length() > 20000.0f)
2544 { 2551 {
2545 v.Normalize(); 2552 v.Normalize();
@@ -2552,13 +2559,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2552 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2559 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2553 { 2560 {
2554 m_host.AddScriptLPS(1); 2561 m_host.AddScriptLPS(1);
2555 m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); 2562 m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0);
2556 } 2563 }
2557 2564
2558 public void llSetTorque(LSL_Vector torque, int local) 2565 public void llSetTorque(LSL_Vector torque, int local)
2559 { 2566 {
2560 m_host.AddScriptLPS(1); 2567 m_host.AddScriptLPS(1);
2561 m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); 2568 m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0);
2562 } 2569 }
2563 2570
2564 public LSL_Vector llGetTorque() 2571 public LSL_Vector llGetTorque()
@@ -2668,63 +2675,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2668 m_host.AddScriptLPS(1); 2675 m_host.AddScriptLPS(1);
2669 2676
2670 // send the sound, once, to all clients in range 2677 // send the sound, once, to all clients in range
2671 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, false, false); 2678 if (m_SoundModule != null)
2679 {
2680 m_SoundModule.SendSound(m_host.UUID,
2681 KeyOrName(sound, AssetType.Sound), volume, false, 0,
2682 0, false, false);
2683 }
2672 } 2684 }
2673 2685
2674 // Xantor 20080528 we should do this differently.
2675 // 1) apply the sound to the object
2676 // 2) schedule full update
2677 // just sending the sound out once doesn't work so well when other avatars come in view later on
2678 // or when the prim gets moved, changed, sat on, whatever
2679 // see large number of mantises (mantes?)
2680 // 20080530 Updated to remove code duplication
2681 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
2682 public void llLoopSound(string sound, double volume) 2686 public void llLoopSound(string sound, double volume)
2683 { 2687 {
2684 m_host.AddScriptLPS(1); 2688 m_host.AddScriptLPS(1);
2685 2689 if (m_SoundModule != null)
2686 if (m_host.Sound != UUID.Zero) 2690 {
2687 llStopSound(); 2691 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound),
2688 2692 volume, 20, false);
2689 m_host.Sound = KeyOrName(sound); 2693 }
2690 m_host.SoundGain = volume;
2691 m_host.SoundFlags = 1; // looping
2692 m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
2693
2694 m_host.ScheduleFullUpdate();
2695 m_host.SendFullUpdateToAllClients();
2696 } 2694 }
2697 2695
2698 public void llLoopSoundMaster(string sound, double volume) 2696 public void llLoopSoundMaster(string sound, double volume)
2699 { 2697 {
2700 m_host.AddScriptLPS(1); 2698 m_host.AddScriptLPS(1);
2701 m_host.ParentGroup.LoopSoundMasterPrim = m_host; 2699 if (m_SoundModule != null)
2702 lock (m_host.ParentGroup.LoopSoundSlavePrims)
2703 { 2700 {
2704 foreach (SceneObjectPart prim in m_host.ParentGroup.LoopSoundSlavePrims) 2701 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound),
2705 { 2702 volume, 20, true);
2706 if (prim.Sound != UUID.Zero)
2707 llStopSound();
2708
2709 prim.Sound = KeyOrName(sound);
2710 prim.SoundGain = volume;
2711 prim.SoundFlags = 1; // looping
2712 prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
2713
2714 prim.ScheduleFullUpdate();
2715 prim.SendFullUpdateToAllClients();
2716 }
2717 } 2703 }
2718 if (m_host.Sound != UUID.Zero)
2719 llStopSound();
2720
2721 m_host.Sound = KeyOrName(sound);
2722 m_host.SoundGain = volume;
2723 m_host.SoundFlags = 1; // looping
2724 m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
2725
2726 m_host.ScheduleFullUpdate();
2727 m_host.SendFullUpdateToAllClients();
2728 } 2704 }
2729 2705
2730 public void llLoopSoundSlave(string sound, double volume) 2706 public void llLoopSoundSlave(string sound, double volume)
@@ -2741,61 +2717,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2741 m_host.AddScriptLPS(1); 2717 m_host.AddScriptLPS(1);
2742 2718
2743 // send the sound, once, to all clients in range 2719 // send the sound, once, to all clients in range
2744 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, true, false); 2720 if (m_SoundModule != null)
2721 {
2722 m_SoundModule.SendSound(m_host.UUID,
2723 KeyOrName(sound, AssetType.Sound), volume, false, 0,
2724 0, true, false);
2725 }
2745 } 2726 }
2746 2727
2747 public void llTriggerSound(string sound, double volume) 2728 public void llTriggerSound(string sound, double volume)
2748 { 2729 {
2749 m_host.AddScriptLPS(1); 2730 m_host.AddScriptLPS(1);
2750 // send the sound, once, to all clients in range 2731 // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory.
2751 m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, 0, false, false); 2732 if (m_SoundModule != null)
2733 {
2734 m_SoundModule.SendSound(m_host.UUID,
2735 KeyOrName(sound, AssetType.Sound), volume, true, 0, 0,
2736 false, false);
2737 }
2752 } 2738 }
2753 2739
2754 // Xantor 20080528: Clear prim data of sound instead
2755 public void llStopSound() 2740 public void llStopSound()
2756 { 2741 {
2757 m_host.AddScriptLPS(1); 2742 m_host.AddScriptLPS(1);
2758 if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) 2743
2759 { 2744 if (m_SoundModule != null)
2760 if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) 2745 m_SoundModule.StopSound(m_host.UUID);
2761 {
2762 foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims)
2763 {
2764 part.Sound = UUID.Zero;
2765 part.SoundGain = 0;
2766 part.SoundFlags = 0;
2767 part.SoundRadius = 0;
2768 part.ScheduleFullUpdate();
2769 part.SendFullUpdateToAllClients();
2770 }
2771 m_host.ParentGroup.LoopSoundMasterPrim = null;
2772 m_host.ParentGroup.LoopSoundSlavePrims.Clear();
2773 }
2774 else
2775 {
2776 m_host.Sound = UUID.Zero;
2777 m_host.SoundGain = 0;
2778 m_host.SoundFlags = 0;
2779 m_host.SoundRadius = 0;
2780 m_host.ScheduleFullUpdate();
2781 m_host.SendFullUpdateToAllClients();
2782 }
2783 }
2784 else
2785 {
2786 m_host.Sound = UUID.Zero;
2787 m_host.SoundGain = 0;
2788 m_host.SoundFlags = 0;
2789 m_host.SoundRadius = 0;
2790 m_host.ScheduleFullUpdate();
2791 m_host.SendFullUpdateToAllClients();
2792 }
2793 } 2746 }
2794 2747
2795 public void llPreloadSound(string sound) 2748 public void llPreloadSound(string sound)
2796 { 2749 {
2797 m_host.AddScriptLPS(1); 2750 m_host.AddScriptLPS(1);
2798 m_host.PreloadSound(sound); 2751 if (m_SoundModule != null)
2752 m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0);
2799 ScriptSleep(1000); 2753 ScriptSleep(1000);
2800 } 2754 }
2801 2755
@@ -3059,7 +3013,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3059 } 3013 }
3060 3014
3061 bool result = money.ObjectGiveMoney( 3015 bool result = money.ObjectGiveMoney(
3062 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); 3016 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount, UUID.Zero);
3063 3017
3064 if (result) 3018 if (result)
3065 return 1; 3019 return 1;
@@ -3123,13 +3077,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3123 return; 3077 return;
3124 } 3078 }
3125 3079
3126 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
3127 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z);
3128
3129 // need the magnitude later 3080 // need the magnitude later
3130 // float velmag = (float)Util.GetMagnitude(llvel); 3081 // float velmag = (float)Util.GetMagnitude(llvel);
3131 3082
3132 SceneObjectGroup new_group = World.RezObject(m_host, item, llpos, Rot2Quaternion(rot), llvel, param); 3083 SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param);
3133 3084
3134 // If either of these are null, then there was an unknown error. 3085 // If either of these are null, then there was an unknown error.
3135 if (new_group == null) 3086 if (new_group == null)
@@ -3156,11 +3107,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3156 3107
3157 PhysicsActor pa = new_group.RootPart.PhysActor; 3108 PhysicsActor pa = new_group.RootPart.PhysActor;
3158 3109
3159 if (pa != null && pa.IsPhysical && llvel != Vector3.Zero) 3110 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3160 { 3111 {
3161 float groupmass = new_group.GetMass(); 3112 float groupmass = new_group.GetMass();
3162 llvel *= -groupmass; 3113 vel *= -groupmass;
3163 llApplyImpulse(new LSL_Vector(llvel.X, llvel.Y,llvel.Z), 0); 3114 llApplyImpulse(vel, 0);
3164 } 3115 }
3165 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3116 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3166 return; 3117 return;
@@ -3211,7 +3162,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3211 return; 3162 return;
3212 } 3163 }
3213 3164
3214 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping); 3165 m_host.StartLookAt((Quaternion)(r3 * r2 * r1), (float)strength, (float)damping);
3215 } 3166 }
3216 } 3167 }
3217 3168
@@ -3637,7 +3588,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3637 } 3588 }
3638 else 3589 else
3639 { 3590 {
3640 m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping); 3591 m_host.RotLookAt(target, (float)strength, (float)damping);
3641 } 3592 }
3642 } 3593 }
3643 3594
@@ -3718,7 +3669,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3718 3669
3719 protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) 3670 protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain)
3720 { 3671 {
3721 part.UpdateAngularVelocity(new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate))); 3672 part.UpdateAngularVelocity(axis * spinrate);
3722 } 3673 }
3723 3674
3724 public LSL_Integer llGetStartParameter() 3675 public LSL_Integer llGetStartParameter()
@@ -3932,7 +3883,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3932 try 3883 try
3933 { 3884 {
3934 foreach (SceneObjectPart part in parts) 3885 foreach (SceneObjectPart part in parts)
3935 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3886 part.SetFaceColorAlpha(face, color, null);
3936 } 3887 }
3937 finally 3888 finally
3938 { 3889 {
@@ -4158,6 +4109,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4158 } 4109 }
4159 4110
4160 /// <summary> 4111 /// <summary>
4112 /// Returns the name of the child prim or seated avatar matching the
4113 /// specified link number.
4114 /// </summary>
4115 /// <param name="linknum">
4116 /// The number of a link in the linkset or a link-related constant.
4117 /// </param>
4118 /// <returns>
4119 /// The name determined to match the specified link number.
4120 /// </returns>
4121 /// <remarks>
4161 /// The rules governing the returned name are not simple. The only 4122 /// The rules governing the returned name are not simple. The only
4162 /// time a blank name is returned is if the target prim has a blank 4123 /// time a blank name is returned is if the target prim has a blank
4163 /// name. If no prim with the given link number can be found then 4124 /// name. If no prim with the given link number can be found then
@@ -4185,10 +4146,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4185 /// Mentions NULL_KEY being returned 4146 /// Mentions NULL_KEY being returned
4186 /// http://wiki.secondlife.com/wiki/LlGetLinkName 4147 /// http://wiki.secondlife.com/wiki/LlGetLinkName
4187 /// Mentions using the LINK_* constants, some of which are negative 4148 /// Mentions using the LINK_* constants, some of which are negative
4188 /// </summary> 4149 /// </remarks>
4189 public LSL_String llGetLinkName(int linknum) 4150 public LSL_String llGetLinkName(int linknum)
4190 { 4151 {
4191 m_host.AddScriptLPS(1); 4152 m_host.AddScriptLPS(1);
4153 // simplest case, this prims link number
4154 if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS)
4155 return m_host.Name;
4156
4192 // parse for sitting avatare-names 4157 // parse for sitting avatare-names
4193 List<String> nametable = new List<String>(); 4158 List<String> nametable = new List<String>();
4194 World.ForEachRootScenePresence(delegate(ScenePresence presence) 4159 World.ForEachRootScenePresence(delegate(ScenePresence presence)
@@ -4212,10 +4177,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4212 return nametable[totalprims - linknum]; 4177 return nametable[totalprims - linknum];
4213 } 4178 }
4214 4179
4215 // simplest case, this prims link number
4216 if (m_host.LinkNum == linknum)
4217 return m_host.Name;
4218
4219 // Single prim 4180 // Single prim
4220 if (m_host.LinkNum == 0) 4181 if (m_host.LinkNum == 0)
4221 { 4182 {
@@ -4364,7 +4325,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4364 World.RegionInfo.RegionName+" "+ 4325 World.RegionInfo.RegionName+" "+
4365 m_host.AbsolutePosition.ToString(), 4326 m_host.AbsolutePosition.ToString(),
4366 agentItem.ID, true, m_host.AbsolutePosition, 4327 agentItem.ID, true, m_host.AbsolutePosition,
4367 bucket); 4328 bucket, true);
4368 4329
4369 ScenePresence sp; 4330 ScenePresence sp;
4370 4331
@@ -4402,9 +4363,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4402 public void llSetText(string text, LSL_Vector color, double alpha) 4363 public void llSetText(string text, LSL_Vector color, double alpha)
4403 { 4364 {
4404 m_host.AddScriptLPS(1); 4365 m_host.AddScriptLPS(1);
4405 Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f), 4366 Vector3 av3 = Util.Clip(color, 0.0f, 1.0f);
4406 Util.Clip((float)color.y, 0.0f, 1.0f),
4407 Util.Clip((float)color.z, 0.0f, 1.0f));
4408 if (text.Length > 254) 4367 if (text.Length > 254)
4409 text = text.Remove(254); 4368 text = text.Remove(254);
4410 4369
@@ -4631,14 +4590,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4631 ScriptSleep(5000); 4590 ScriptSleep(5000);
4632 } 4591 }
4633 4592
4634 public void llTeleportAgent(string agent, string destination, LSL_Vector pos, LSL_Vector lookAt) 4593 public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt)
4635 { 4594 {
4636 m_host.AddScriptLPS(1); 4595 m_host.AddScriptLPS(1);
4637 UUID agentId = new UUID(); 4596 UUID agentId = new UUID();
4638 4597
4639 Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
4640 Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z);
4641
4642 if (UUID.TryParse(agent, out agentId)) 4598 if (UUID.TryParse(agent, out agentId))
4643 { 4599 {
4644 ScenePresence presence = World.GetScenePresence(agentId); 4600 ScenePresence presence = World.GetScenePresence(agentId);
@@ -4667,15 +4623,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4667 } 4623 }
4668 } 4624 }
4669 4625
4670 public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector pos, LSL_Vector lookAt) 4626 public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt)
4671 { 4627 {
4672 m_host.AddScriptLPS(1); 4628 m_host.AddScriptLPS(1);
4673 UUID agentId = new UUID(); 4629 UUID agentId = new UUID();
4674 4630
4675 ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); 4631 ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y);
4676 4632
4677 Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
4678 Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z);
4679 if (UUID.TryParse(agent, out agentId)) 4633 if (UUID.TryParse(agent, out agentId))
4680 { 4634 {
4681 ScenePresence presence = World.GetScenePresence(agentId); 4635 ScenePresence presence = World.GetScenePresence(agentId);
@@ -4777,16 +4731,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4777 return; 4731 return;
4778 } 4732 }
4779 // TODO: Parameter check logic required. 4733 // TODO: Parameter check logic required.
4780 UUID soundId = UUID.Zero; 4734 m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound);
4781 if (!UUID.TryParse(impact_sound, out soundId))
4782 {
4783 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(impact_sound);
4784
4785 if (item != null && item.Type == (int)AssetType.Sound)
4786 soundId = item.AssetID;
4787 }
4788
4789 m_host.CollisionSound = soundId;
4790 m_host.CollisionSoundVolume = (float)impact_volume; 4735 m_host.CollisionSoundVolume = (float)impact_volume;
4791 m_host.CollisionSoundType = 1; 4736 m_host.CollisionSoundType = 1;
4792 } 4737 }
@@ -4972,7 +4917,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4972 distance_attenuation = 1f / normalized_units; 4917 distance_attenuation = 1f / normalized_units;
4973 } 4918 }
4974 4919
4975 Vector3 applied_linear_impulse = new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z); 4920 Vector3 applied_linear_impulse = impulse;
4976 { 4921 {
4977 float impulse_length = applied_linear_impulse.Length(); 4922 float impulse_length = applied_linear_impulse.Length();
4978 4923
@@ -5620,25 +5565,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5620 /// separated list. There is a space after 5565 /// separated list. There is a space after
5621 /// each comma. 5566 /// each comma.
5622 /// </summary> 5567 /// </summary>
5623
5624 public LSL_String llList2CSV(LSL_List src) 5568 public LSL_String llList2CSV(LSL_List src)
5625 { 5569 {
5626
5627 string ret = String.Empty;
5628 int x = 0;
5629
5630 m_host.AddScriptLPS(1); 5570 m_host.AddScriptLPS(1);
5631 5571
5632 if (src.Data.Length > 0) 5572 return string.Join(", ",
5633 { 5573 (new List<object>(src.Data)).ConvertAll<string>(o =>
5634 ret = src.Data[x++].ToString(); 5574 {
5635 for (; x < src.Data.Length; x++) 5575 return o.ToString();
5636 { 5576 }).ToArray());
5637 ret += ", "+src.Data[x].ToString();
5638 }
5639 }
5640
5641 return ret;
5642 } 5577 }
5643 5578
5644 /// <summary> 5579 /// <summary>
@@ -5937,27 +5872,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5937 /// Returns the index of the first occurrence of test 5872 /// Returns the index of the first occurrence of test
5938 /// in src. 5873 /// in src.
5939 /// </summary> 5874 /// </summary>
5940 5875 /// <param name="src">Source list</param>
5876 /// <param name="test">List to search for</param>
5877 /// <returns>
5878 /// The index number of the point in src where test was found if it was found.
5879 /// Otherwise returns -1
5880 /// </returns>
5941 public LSL_Integer llListFindList(LSL_List src, LSL_List test) 5881 public LSL_Integer llListFindList(LSL_List src, LSL_List test)
5942 { 5882 {
5943
5944 int index = -1; 5883 int index = -1;
5945 int length = src.Length - test.Length + 1; 5884 int length = src.Length - test.Length + 1;
5946 5885
5947 m_host.AddScriptLPS(1); 5886 m_host.AddScriptLPS(1);
5948 5887
5949 // If either list is empty, do not match 5888 // If either list is empty, do not match
5950
5951 if (src.Length != 0 && test.Length != 0) 5889 if (src.Length != 0 && test.Length != 0)
5952 { 5890 {
5953 for (int i = 0; i < length; i++) 5891 for (int i = 0; i < length; i++)
5954 { 5892 {
5955 if (src.Data[i].Equals(test.Data[0])) 5893 // Why this piece of insanity? This is because most script constants are C# value types (e.g. int)
5894 // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code
5895 // and so the comparison fails even if the LSL_Integer conceptually has the same value.
5896 // Therefore, here we test Equals on both the source and destination objects.
5897 // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)).
5898 if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i]))
5956 { 5899 {
5957 int j; 5900 int j;
5958 for (j = 1; j < test.Length; j++) 5901 for (j = 1; j < test.Length; j++)
5959 if (!src.Data[i+j].Equals(test.Data[j])) 5902 if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j])))
5960 break; 5903 break;
5904
5961 if (j == test.Length) 5905 if (j == test.Length)
5962 { 5906 {
5963 index = i; 5907 index = i;
@@ -5968,19 +5912,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5968 } 5912 }
5969 5913
5970 return index; 5914 return index;
5971
5972 } 5915 }
5973 5916
5974 public LSL_String llGetObjectName() 5917 public LSL_String llGetObjectName()
5975 { 5918 {
5976 m_host.AddScriptLPS(1); 5919 m_host.AddScriptLPS(1);
5977 return m_host.Name!=null?m_host.Name:String.Empty; 5920 return m_host.Name !=null ? m_host.Name : String.Empty;
5978 } 5921 }
5979 5922
5980 public void llSetObjectName(string name) 5923 public void llSetObjectName(string name)
5981 { 5924 {
5982 m_host.AddScriptLPS(1); 5925 m_host.AddScriptLPS(1);
5983 m_host.Name = name!=null?name:String.Empty; 5926 m_host.Name = name != null ? name : String.Empty;
5984 } 5927 }
5985 5928
5986 public LSL_String llGetDate() 5929 public LSL_String llGetDate()
@@ -6154,7 +6097,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6154 flags |= ScriptBaseClass.AGENT_SITTING; 6097 flags |= ScriptBaseClass.AGENT_SITTING;
6155 } 6098 }
6156 6099
6157 if (agent.Animator.Animations.DefaultAnimation.AnimID 6100 if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID
6158 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 6101 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
6159 { 6102 {
6160 flags |= ScriptBaseClass.AGENT_SITTING; 6103 flags |= ScriptBaseClass.AGENT_SITTING;
@@ -6311,19 +6254,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6311 m_host.AddScriptLPS(1); 6254 m_host.AddScriptLPS(1);
6312 6255
6313 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6256 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6314 if (parts.Count > 0) 6257
6258 try
6315 { 6259 {
6316 try 6260 foreach (SceneObjectPart part in parts)
6317 {
6318 foreach (var part in parts)
6319 {
6320 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6321 }
6322 }
6323 finally
6324 { 6261 {
6262 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6325 } 6263 }
6326 } 6264 }
6265 finally
6266 {
6267 }
6327 } 6268 }
6328 6269
6329 private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate) 6270 private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate)
@@ -6352,10 +6293,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6352 LSL_Vector bottom_south_west) 6293 LSL_Vector bottom_south_west)
6353 { 6294 {
6354 m_host.AddScriptLPS(1); 6295 m_host.AddScriptLPS(1);
6355 float radius1 = (float)llVecDist(llGetPos(), top_north_east); 6296 if (m_SoundModule != null)
6356 float radius2 = (float)llVecDist(llGetPos(), bottom_south_west); 6297 {
6357 float radius = Math.Abs(radius1 - radius2); 6298 m_SoundModule.TriggerSoundLimited(m_host.UUID,
6358 m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, radius, false, false); 6299 KeyOrName(sound, AssetType.Sound), volume,
6300 bottom_south_west, top_north_east);
6301 }
6359 } 6302 }
6360 6303
6361 public void llEjectFromLand(string pest) 6304 public void llEjectFromLand(string pest)
@@ -6541,9 +6484,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6541 6484
6542 //Plug the x,y coordinates of the slope normal into the equation of the plane to get 6485 //Plug the x,y coordinates of the slope normal into the equation of the plane to get
6543 //the height of that point on the plane. The resulting vector gives the slope. 6486 //the height of that point on the plane. The resulting vector gives the slope.
6544 Vector3 vsl = new Vector3(); 6487 Vector3 vsl = vsn;
6545 vsl.X = (float)vsn.x;
6546 vsl.Y = (float)vsn.y;
6547 vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); 6488 vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z));
6548 vsl.Normalize(); 6489 vsl.Normalize();
6549 //Normalization might be overkill here 6490 //Normalization might be overkill here
@@ -6554,9 +6495,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6554 public LSL_Vector llGroundNormal(LSL_Vector offset) 6495 public LSL_Vector llGroundNormal(LSL_Vector offset)
6555 { 6496 {
6556 m_host.AddScriptLPS(1); 6497 m_host.AddScriptLPS(1);
6557 Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, 6498 Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
6558 (float)offset.y,
6559 (float)offset.z);
6560 // Clamp to valid position 6499 // Clamp to valid position
6561 if (pos.X < 0) 6500 if (pos.X < 0)
6562 pos.X = 0; 6501 pos.X = 0;
@@ -6721,7 +6660,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6721 6660
6722 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6661 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6723 6662
6724 foreach (var part in parts) 6663 foreach (SceneObjectPart part in parts)
6725 { 6664 {
6726 SetParticleSystem(part, rules); 6665 SetParticleSystem(part, rules);
6727 } 6666 }
@@ -6965,16 +6904,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6965 if (m_TransferModule != null) 6904 if (m_TransferModule != null)
6966 { 6905 {
6967 byte[] bucket = new byte[] { (byte)AssetType.Folder }; 6906 byte[] bucket = new byte[] { (byte)AssetType.Folder };
6968 6907
6908 Vector3 pos = m_host.AbsolutePosition;
6909
6969 GridInstantMessage msg = new GridInstantMessage(World, 6910 GridInstantMessage msg = new GridInstantMessage(World,
6970 m_host.UUID, m_host.Name + ", an object owned by " + 6911 m_host.OwnerID, m_host.Name, destID,
6971 resolveName(m_host.OwnerID) + ",", destID,
6972 (byte)InstantMessageDialog.TaskInventoryOffered, 6912 (byte)InstantMessageDialog.TaskInventoryOffered,
6973 false, category + "\n" + m_host.Name + " is located at " + 6913 false, string.Format("'{0}'", category),
6974 World.RegionInfo.RegionName + " " + 6914// We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06
6975 m_host.AbsolutePosition.ToString(), 6915// false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z),
6976 folderID, true, m_host.AbsolutePosition, 6916 folderID, false, pos,
6977 bucket); 6917 bucket, false);
6978 6918
6979 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 6919 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
6980 } 6920 }
@@ -7010,8 +6950,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7010 6950
7011 if (!m_host.ParentGroup.IsDeleted) 6951 if (!m_host.ParentGroup.IsDeleted)
7012 { 6952 {
7013 m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, 6953 m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec);
7014 new Vector3((float)vec.x, (float)vec.y, (float)vec.z));
7015 } 6954 }
7016 } 6955 }
7017 6956
@@ -7023,7 +6962,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7023 6962
7024 if (!m_host.ParentGroup.IsDeleted) 6963 if (!m_host.ParentGroup.IsDeleted)
7025 { 6964 {
7026 m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, Rot2Quaternion(rot)); 6965 m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot);
7027 } 6966 }
7028 } 6967 }
7029 6968
@@ -7053,8 +6992,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7053 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) 6992 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
7054 rot.s = 1; // ZERO_ROTATION = 0,0,0,1 6993 rot.s = 1; // ZERO_ROTATION = 0,0,0,1
7055 6994
7056 part.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); 6995 part.SitTargetPosition = offset;
7057 part.SitTargetOrientation = Rot2Quaternion(rot); 6996 part.SitTargetOrientation = rot;
7058 part.ParentGroup.HasGroupChanged = true; 6997 part.ParentGroup.HasGroupChanged = true;
7059 } 6998 }
7060 6999
@@ -7157,13 +7096,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7157 public void llSetCameraEyeOffset(LSL_Vector offset) 7096 public void llSetCameraEyeOffset(LSL_Vector offset)
7158 { 7097 {
7159 m_host.AddScriptLPS(1); 7098 m_host.AddScriptLPS(1);
7160 m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); 7099 m_host.SetCameraEyeOffset(offset);
7161 } 7100 }
7162 7101
7163 public void llSetCameraAtOffset(LSL_Vector offset) 7102 public void llSetCameraAtOffset(LSL_Vector offset)
7164 { 7103 {
7165 m_host.AddScriptLPS(1); 7104 m_host.AddScriptLPS(1);
7166 m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); 7105 m_host.SetCameraAtOffset(offset);
7106 }
7107
7108 public void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at)
7109 {
7110 m_host.AddScriptLPS(1);
7111
7112 if (link == ScriptBaseClass.LINK_SET ||
7113 link == ScriptBaseClass.LINK_ALL_CHILDREN ||
7114 link == ScriptBaseClass.LINK_ALL_OTHERS) return;
7115
7116 SceneObjectPart part = null;
7117
7118 switch (link)
7119 {
7120 case ScriptBaseClass.LINK_ROOT:
7121 part = m_host.ParentGroup.RootPart;
7122 break;
7123 case ScriptBaseClass.LINK_THIS:
7124 part = m_host;
7125 break;
7126 default:
7127 part = m_host.ParentGroup.GetLinkNumPart(link);
7128 break;
7129 }
7130
7131 if (null != part)
7132 {
7133 part.SetCameraEyeOffset(eye);
7134 part.SetCameraAtOffset(at);
7135 }
7167 } 7136 }
7168 7137
7169 public LSL_String llDumpList2String(LSL_List src, string seperator) 7138 public LSL_String llDumpList2String(LSL_List src, string seperator)
@@ -7185,7 +7154,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7185 public LSL_Integer llScriptDanger(LSL_Vector pos) 7154 public LSL_Integer llScriptDanger(LSL_Vector pos)
7186 { 7155 {
7187 m_host.AddScriptLPS(1); 7156 m_host.AddScriptLPS(1);
7188 bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)); 7157 bool result = World.ScriptDanger(m_host.LocalId, pos);
7189 if (result) 7158 if (result)
7190 { 7159 {
7191 return 1; 7160 return 1;
@@ -7767,7 +7736,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7767 { 7736 {
7768 m_host.AddScriptLPS(1); 7737 m_host.AddScriptLPS(1);
7769 7738
7770 setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules); 7739 setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams");
7771 7740
7772 ScriptSleep(200); 7741 ScriptSleep(200);
7773 } 7742 }
@@ -7776,10 +7745,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7776 { 7745 {
7777 m_host.AddScriptLPS(1); 7746 m_host.AddScriptLPS(1);
7778 7747
7779 setLinkPrimParams(linknumber, rules); 7748 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
7749
7750 ScriptSleep(200);
7780 } 7751 }
7781 7752
7782 private void setLinkPrimParams(int linknumber, LSL_List rules) 7753 private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
7783 { 7754 {
7784 List<object> parts = new List<object>(); 7755 List<object> parts = new List<object>();
7785 List<SceneObjectPart> prims = GetLinkParts(linknumber); 7756 List<SceneObjectPart> prims = GetLinkParts(linknumber);
@@ -7790,15 +7761,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7790 parts.Add(p); 7761 parts.Add(p);
7791 7762
7792 LSL_List remaining = null; 7763 LSL_List remaining = null;
7764 uint rulesParsed = 0;
7793 7765
7794 if (parts.Count > 0) 7766 if (parts.Count > 0)
7795 { 7767 {
7796 foreach (object part in parts) 7768 foreach (object part in parts)
7797 { 7769 {
7798 if (part is SceneObjectPart) 7770 if (part is SceneObjectPart)
7799 remaining = SetPrimParams((SceneObjectPart)part, rules); 7771 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7800 else 7772 else
7801 remaining = SetPrimParams((ScenePresence)part, rules); 7773 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7802 } 7774 }
7803 7775
7804 while ((object)remaining != null && remaining.Length > 2) 7776 while ((object)remaining != null && remaining.Length > 2)
@@ -7817,9 +7789,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7817 foreach (object part in parts) 7789 foreach (object part in parts)
7818 { 7790 {
7819 if (part is SceneObjectPart) 7791 if (part is SceneObjectPart)
7820 remaining = SetPrimParams((SceneObjectPart)part, rules); 7792 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7821 else 7793 else
7822 remaining = SetPrimParams((ScenePresence)part, rules); 7794 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7823 } 7795 }
7824 } 7796 }
7825 } 7797 }
@@ -7857,6 +7829,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7857 7829
7858 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7830 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7859 { 7831 {
7832 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
7860 llSetLinkPrimitiveParamsFast(linknumber, rules); 7833 llSetLinkPrimitiveParamsFast(linknumber, rules);
7861 ScriptSleep(200); 7834 ScriptSleep(200);
7862 } 7835 }
@@ -7884,195 +7857,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7884 return new Vector3((float)x, (float)y, (float)z); 7857 return new Vector3((float)x, (float)y, (float)z);
7885 } 7858 }
7886 7859
7887 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules) 7860 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
7888 {
7889 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7890
7891 int idx = 0;
7892
7893 bool positionChanged = false;
7894 Vector3 finalPos = Vector3.Zero;
7895
7896 try
7897 {
7898 while (idx < rules.Length)
7899 {
7900 int code = rules.GetLSLIntegerItem(idx++);
7901
7902 int remain = rules.Length - idx;
7903
7904 switch (code)
7905 {
7906 case (int)ScriptBaseClass.PRIM_POSITION:
7907 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
7908 {
7909 if (remain < 1)
7910 return null;
7911
7912 LSL_Vector v;
7913 v = rules.GetVector3Item(idx++);
7914
7915 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7916 if (part == null)
7917 break;
7918
7919 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7920 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7921 if (part.LinkNum > 1)
7922 {
7923 localRot = GetPartLocalRot(part);
7924 localPos = GetPartLocalPos(part);
7925 }
7926
7927 v -= localPos;
7928 v /= localRot;
7929
7930 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
7931
7932 v = v + 2 * sitOffset;
7933
7934 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7935 av.SendAvatarDataToAllAgents();
7936
7937 }
7938 break;
7939
7940 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
7941 case (int)ScriptBaseClass.PRIM_ROTATION:
7942 {
7943 if (remain < 1)
7944 return null;
7945
7946 LSL_Rotation r;
7947 r = rules.GetQuaternionItem(idx++);
7948
7949 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7950 if (part == null)
7951 break;
7952
7953 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7954 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7955
7956 if (part.LinkNum > 1)
7957 localRot = GetPartLocalRot(part);
7958
7959 r = r * llGetRootRotation() / localRot;
7960 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7961 av.SendAvatarDataToAllAgents();
7962 }
7963 break;
7964
7965 // parse rest doing nothing but number of parameters error check
7966 case (int)ScriptBaseClass.PRIM_SIZE:
7967 case (int)ScriptBaseClass.PRIM_MATERIAL:
7968 case (int)ScriptBaseClass.PRIM_PHANTOM:
7969 case (int)ScriptBaseClass.PRIM_PHYSICS:
7970 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
7971 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7972 case (int)ScriptBaseClass.PRIM_NAME:
7973 case (int)ScriptBaseClass.PRIM_DESC:
7974 if (remain < 1)
7975 return null;
7976 idx++;
7977 break;
7978
7979 case (int)ScriptBaseClass.PRIM_GLOW:
7980 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
7981 case (int)ScriptBaseClass.PRIM_TEXGEN:
7982 if (remain < 2)
7983 return null;
7984 idx += 2;
7985 break;
7986
7987 case (int)ScriptBaseClass.PRIM_TYPE:
7988 if (remain < 3)
7989 return null;
7990 code = (int)rules.GetLSLIntegerItem(idx++);
7991 remain = rules.Length - idx;
7992 switch (code)
7993 {
7994 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
7995 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
7996 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
7997 if (remain < 6)
7998 return null;
7999 idx += 6;
8000 break;
8001
8002 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
8003 if (remain < 5)
8004 return null;
8005 idx += 5;
8006 break;
8007
8008 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
8009 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
8010 case (int)ScriptBaseClass.PRIM_TYPE_RING:
8011 if (remain < 11)
8012 return null;
8013 idx += 11;
8014 break;
8015
8016 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
8017 if (remain < 2)
8018 return null;
8019 idx += 2;
8020 break;
8021 }
8022 break;
8023
8024 case (int)ScriptBaseClass.PRIM_COLOR:
8025 case (int)ScriptBaseClass.PRIM_TEXT:
8026 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8027 case (int)ScriptBaseClass.PRIM_OMEGA:
8028 if (remain < 3)
8029 return null;
8030 idx += 3;
8031 break;
8032
8033 case (int)ScriptBaseClass.PRIM_TEXTURE:
8034 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
8035 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8036 if (remain < 5)
8037 return null;
8038 idx += 5;
8039 break;
8040
8041 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
8042 if (remain < 7)
8043 return null;
8044
8045 idx += 7;
8046 break;
8047
8048 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
8049 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
8050 return null;
8051
8052 return rules.GetSublist(idx, -1);
8053 }
8054 }
8055 }
8056
8057 finally
8058 {
8059 if (positionChanged)
8060 {
8061 av.OffsetPosition = finalPos;
8062// av.SendAvatarDataToAllAgents();
8063 av.SendTerseUpdateToAllClients();
8064 positionChanged = false;
8065 }
8066 }
8067 return null;
8068 }
8069
8070 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules)
8071 { 7861 {
8072 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 7862 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8073 return null; 7863 return null;
8074 7864
8075 int idx = 0; 7865 int idx = 0;
7866 int idxStart = 0;
8076 7867
8077 SceneObjectGroup parentgrp = part.ParentGroup; 7868 SceneObjectGroup parentgrp = part.ParentGroup;
8078 7869
@@ -8083,9 +7874,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8083 { 7874 {
8084 while (idx < rules.Length) 7875 while (idx < rules.Length)
8085 { 7876 {
7877 ++rulesParsed;
8086 int code = rules.GetLSLIntegerItem(idx++); 7878 int code = rules.GetLSLIntegerItem(idx++);
8087 7879
8088 int remain = rules.Length - idx; 7880 int remain = rules.Length - idx;
7881 idxStart = idx;
8089 7882
8090 int face; 7883 int face;
8091 LSL_Vector v; 7884 LSL_Vector v;
@@ -8115,18 +7908,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8115 return null; 7908 return null;
8116 7909
8117 LSL_Rotation q = rules.GetQuaternionItem(idx++); 7910 LSL_Rotation q = rules.GetQuaternionItem(idx++);
8118 SceneObjectPart rootPart = parentgrp.RootPart;
8119 // try to let this work as in SL... 7911 // try to let this work as in SL...
8120 if (rootPart == part) 7912 if (part.ParentID == 0)
8121 { 7913 {
8122 // special case: If we are root, rotate complete SOG to new rotation 7914 // special case: If we are root, rotate complete SOG to new rotation
8123 SetRot(part, Rot2Quaternion(q)); 7915 SetRot(part, q);
8124 } 7916 }
8125 else 7917 else
8126 { 7918 {
8127 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. 7919 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
8128 // sounds like sl bug that we need to replicate 7920 SceneObjectPart rootPart = part.ParentGroup.RootPart;
8129 SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q)); 7921 SetRot(part, rootPart.RotationOffset * (Quaternion)q);
8130 } 7922 }
8131 7923
8132 break; 7924 break;
@@ -8300,8 +8092,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8300 LSL_Vector color=rules.GetVector3Item(idx++); 8092 LSL_Vector color=rules.GetVector3Item(idx++);
8301 double alpha=(double)rules.GetLSLFloatItem(idx++); 8093 double alpha=(double)rules.GetLSLFloatItem(idx++);
8302 8094
8303 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 8095 part.SetFaceColorAlpha(face, color, alpha);
8304 SetAlpha(part, alpha, face);
8305 8096
8306 break; 8097 break;
8307 8098
@@ -8449,9 +8240,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8449 string primText = rules.GetLSLStringItem(idx++); 8240 string primText = rules.GetLSLStringItem(idx++);
8450 LSL_Vector primTextColor = rules.GetVector3Item(idx++); 8241 LSL_Vector primTextColor = rules.GetVector3Item(idx++);
8451 LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); 8242 LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++);
8452 Vector3 av3 = new Vector3(Util.Clip((float)primTextColor.x, 0.0f, 1.0f), 8243 Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f);
8453 Util.Clip((float)primTextColor.y, 0.0f, 1.0f),
8454 Util.Clip((float)primTextColor.z, 0.0f, 1.0f));
8455 part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); 8244 part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f));
8456 8245
8457 break; 8246 break;
@@ -8470,8 +8259,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8470 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 8259 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8471 if (remain < 1) 8260 if (remain < 1)
8472 return null; 8261 return null;
8473 LSL_Rotation lr = rules.GetQuaternionItem(idx++); 8262 SetRot(part, rules.GetQuaternionItem(idx++));
8474 SetRot(part, Rot2Quaternion(lr));
8475 break; 8263 break;
8476 case (int)ScriptBaseClass.PRIM_OMEGA: 8264 case (int)ScriptBaseClass.PRIM_OMEGA:
8477 if (remain < 3) 8265 if (remain < 3)
@@ -8481,7 +8269,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8481 LSL_Float gain = rules.GetLSLFloatItem(idx++); 8269 LSL_Float gain = rules.GetLSLFloatItem(idx++);
8482 TargetOmega(part, axis, (double)spinrate, (double)gain); 8270 TargetOmega(part, axis, (double)spinrate, (double)gain);
8483 break; 8271 break;
8484 8272 case (int)ScriptBaseClass.PRIM_SLICE:
8273 if (remain < 1)
8274 return null;
8275 LSL_Vector slice = rules.GetVector3Item(idx++);
8276 part.UpdateSlice((float)slice.x, (float)slice.y);
8277 break;
8485 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 8278 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
8486 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 8279 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
8487 return null; 8280 return null;
@@ -8490,6 +8283,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8490 } 8283 }
8491 } 8284 }
8492 } 8285 }
8286 catch (InvalidCastException e)
8287 {
8288 ShoutError(string.Format(
8289 "{0} error running rule #{1}: arg #{2} ",
8290 originFunc, rulesParsed, idx - idxStart) + e.Message);
8291 }
8493 finally 8292 finally
8494 { 8293 {
8495 if (positionChanged) 8294 if (positionChanged)
@@ -8498,12 +8297,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8498 { 8297 {
8499 SceneObjectGroup parent = part.ParentGroup; 8298 SceneObjectGroup parent = part.ParentGroup;
8500 Util.FireAndForget(delegate(object x) { 8299 Util.FireAndForget(delegate(object x) {
8501 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8300 parent.UpdateGroupPosition(currentPosition);
8502 }); 8301 });
8503 } 8302 }
8504 else 8303 else
8505 { 8304 {
8506 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z); 8305 part.OffsetPosition = currentPosition;
8507 SceneObjectGroup parent = part.ParentGroup; 8306 SceneObjectGroup parent = part.ParentGroup;
8508 parent.HasGroupChanged = true; 8307 parent.HasGroupChanged = true;
8509 parent.ScheduleGroupForTerseUpdate(); 8308 parent.ScheduleGroupForTerseUpdate();
@@ -8792,7 +8591,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8792 // and standing avatar since server 1.36 8591 // and standing avatar since server 1.36
8793 LSL_Vector lower; 8592 LSL_Vector lower;
8794 LSL_Vector upper; 8593 LSL_Vector upper;
8795 if (presence.Animator.Animations.DefaultAnimation.AnimID 8594 if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID
8796 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8595 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
8797 { 8596 {
8798 // This is for ground sitting avatars 8597 // This is for ground sitting avatars
@@ -8881,7 +8680,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8881 public LSL_List llGetPrimitiveParams(LSL_List rules) 8680 public LSL_List llGetPrimitiveParams(LSL_List rules)
8882 { 8681 {
8883 m_host.AddScriptLPS(1); 8682 m_host.AddScriptLPS(1);
8884 return GetLinkPrimitiveParams(m_host, rules); 8683
8684 LSL_List result = new LSL_List();
8685
8686 LSL_List remaining = GetPrimParams(m_host, rules, ref result);
8687
8688 while (remaining != null && remaining.Length > 2)
8689 {
8690 int linknumber = remaining.GetLSLIntegerItem(0);
8691 rules = remaining.GetSublist(1, -1);
8692 List<SceneObjectPart> parts = GetLinkParts(linknumber);
8693
8694 foreach (SceneObjectPart part in parts)
8695 remaining = GetPrimParams(part, rules, ref result);
8696 }
8697
8698 return result;
8885 } 8699 }
8886 8700
8887 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) 8701 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
@@ -8891,294 +8705,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8891 // acording to SL wiki this must indicate a single link number or link_root or link_this. 8705 // acording to SL wiki this must indicate a single link number or link_root or link_this.
8892 // keep other options as before 8706 // keep other options as before
8893 8707
8894 List<SceneObjectPart> parts = GetLinkParts(linknumber); 8708 List<SceneObjectPart> parts;
8895 List<ScenePresence> avatars = GetLinkAvatars(linknumber); 8709 List<ScenePresence> avatars;
8896 8710
8897 LSL_List res = new LSL_List(); 8711 LSL_List res = new LSL_List();
8712 LSL_List remaining = null;
8898 8713
8899 if (parts.Count > 0) 8714 while (rules.Length > 0)
8900 { 8715 {
8901 foreach (var part in parts) 8716 parts = GetLinkParts(linknumber);
8717 avatars = GetLinkAvatars(linknumber);
8718
8719 remaining = null;
8720 foreach (SceneObjectPart part in parts)
8902 { 8721 {
8903 LSL_List partRes = GetLinkPrimitiveParams(part, rules); 8722 remaining = GetPrimParams(part, rules, ref res);
8904 res += partRes;
8905 } 8723 }
8906 }
8907 if (avatars.Count > 0)
8908 {
8909 foreach (ScenePresence avatar in avatars) 8724 foreach (ScenePresence avatar in avatars)
8910 { 8725 {
8911 LSL_List avaRes = GetLinkPrimitiveParams(avatar, rules); 8726 remaining = GetPrimParams(avatar, rules, ref res);
8912 res += avaRes;
8913 } 8727 }
8914 }
8915 return res;
8916 }
8917 8728
8918 public LSL_List GetLinkPrimitiveParams(ScenePresence avatar, LSL_List rules) 8729 if (remaining != null && remaining.Length > 0)
8919 {
8920 // avatars case
8921 // replies as SL wiki
8922
8923 LSL_List res = new LSL_List();
8924// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
8925 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
8926
8927 int idx = 0;
8928 while (idx < rules.Length)
8929 {
8930 int code = (int)rules.GetLSLIntegerItem(idx++);
8931 int remain = rules.Length - idx;
8932
8933 switch (code)
8934 { 8730 {
8935 case (int)ScriptBaseClass.PRIM_MATERIAL: 8731 linknumber = remaining.GetLSLIntegerItem(0);
8936 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh)); 8732 rules = remaining.GetSublist(1, -1);
8937 break;
8938
8939 case (int)ScriptBaseClass.PRIM_PHYSICS:
8940 res.Add(new LSL_Integer(0));
8941 break;
8942
8943 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
8944 res.Add(new LSL_Integer(0));
8945 break;
8946
8947 case (int)ScriptBaseClass.PRIM_PHANTOM:
8948 res.Add(new LSL_Integer(0));
8949 break;
8950
8951 case (int)ScriptBaseClass.PRIM_POSITION:
8952
8953 Vector3 pos = avatar.OffsetPosition;
8954
8955 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
8956 pos -= sitOffset;
8957
8958 if( sitPart != null)
8959 pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation();
8960
8961 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
8962 break;
8963
8964 case (int)ScriptBaseClass.PRIM_SIZE:
8965 // as in llGetAgentSize above
8966 res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight));
8967 break;
8968
8969 case (int)ScriptBaseClass.PRIM_ROTATION:
8970 Quaternion rot = avatar.Rotation;
8971 if (sitPart != null)
8972 {
8973 rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation
8974 }
8975
8976 res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W));
8977 break;
8978
8979 case (int)ScriptBaseClass.PRIM_TYPE:
8980 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
8981 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
8982 res.Add(new LSL_Vector(0f,1.0f,0f));
8983 res.Add(new LSL_Float(0.0f));
8984 res.Add(new LSL_Vector(0, 0, 0));
8985 res.Add(new LSL_Vector(1.0f,1.0f,0f));
8986 res.Add(new LSL_Vector(0, 0, 0));
8987 break;
8988
8989 case (int)ScriptBaseClass.PRIM_TEXTURE:
8990 if (remain < 1)
8991 return res;
8992
8993 int face = (int)rules.GetLSLIntegerItem(idx++);
8994 if (face == ScriptBaseClass.ALL_SIDES)
8995 {
8996 for (face = 0; face < 21; face++)
8997 {
8998 res.Add(new LSL_String(""));
8999 res.Add(new LSL_Vector(0,0,0));
9000 res.Add(new LSL_Vector(0,0,0));
9001 res.Add(new LSL_Float(0.0));
9002 }
9003 }
9004 else
9005 {
9006 if (face >= 0 && face < 21)
9007 {
9008 res.Add(new LSL_String(""));
9009 res.Add(new LSL_Vector(0,0,0));
9010 res.Add(new LSL_Vector(0,0,0));
9011 res.Add(new LSL_Float(0.0));
9012 }
9013 }
9014 break;
9015
9016 case (int)ScriptBaseClass.PRIM_COLOR:
9017 if (remain < 1)
9018 return res;
9019
9020 face = (int)rules.GetLSLIntegerItem(idx++);
9021
9022 if (face == ScriptBaseClass.ALL_SIDES)
9023 {
9024 for (face = 0; face < 21; face++)
9025 {
9026 res.Add(new LSL_Vector(0,0,0));
9027 res.Add(new LSL_Float(0));
9028 }
9029 }
9030 else
9031 {
9032 res.Add(new LSL_Vector(0,0,0));
9033 res.Add(new LSL_Float(0));
9034 }
9035 break;
9036
9037 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
9038 if (remain < 1)
9039 return res;
9040 face = (int)rules.GetLSLIntegerItem(idx++);
9041
9042 if (face == ScriptBaseClass.ALL_SIDES)
9043 {
9044 for (face = 0; face < 21; face++)
9045 {
9046 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
9047 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
9048 }
9049 }
9050 else
9051 {
9052 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
9053 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
9054 }
9055 break;
9056
9057 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
9058 if (remain < 1)
9059 return res;
9060 face = (int)rules.GetLSLIntegerItem(idx++);
9061
9062 if (face == ScriptBaseClass.ALL_SIDES)
9063 {
9064 for (face = 0; face < 21; face++)
9065 {
9066 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
9067 }
9068 }
9069 else
9070 {
9071 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
9072 }
9073 break;
9074
9075 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
9076 res.Add(new LSL_Integer(0));
9077 res.Add(new LSL_Integer(0));// softness
9078 res.Add(new LSL_Float(0.0f)); // gravity
9079 res.Add(new LSL_Float(0.0f)); // friction
9080 res.Add(new LSL_Float(0.0f)); // wind
9081 res.Add(new LSL_Float(0.0f)); // tension
9082 res.Add(new LSL_Vector(0f,0f,0f));
9083 break;
9084
9085 case (int)ScriptBaseClass.PRIM_TEXGEN:
9086 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
9087 if (remain < 1)
9088 return res;
9089 face = (int)rules.GetLSLIntegerItem(idx++);
9090
9091 if (face == ScriptBaseClass.ALL_SIDES)
9092 {
9093 for (face = 0; face < 21; face++)
9094 {
9095 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
9096 }
9097 }
9098 else
9099 {
9100 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
9101 }
9102 break;
9103
9104 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
9105 res.Add(new LSL_Integer(0));
9106 res.Add(new LSL_Vector(0f,0f,0f));
9107 res.Add(new LSL_Float(0f)); // intensity
9108 res.Add(new LSL_Float(0f)); // radius
9109 res.Add(new LSL_Float(0f)); // falloff
9110 break;
9111
9112 case (int)ScriptBaseClass.PRIM_GLOW:
9113 if (remain < 1)
9114 return res;
9115 face = (int)rules.GetLSLIntegerItem(idx++);
9116
9117 if (face == ScriptBaseClass.ALL_SIDES)
9118 {
9119 for (face = 0; face < 21; face++)
9120 {
9121 res.Add(new LSL_Float(0f));
9122 }
9123 }
9124 else
9125 {
9126 res.Add(new LSL_Float(0f));
9127 }
9128 break;
9129
9130 case (int)ScriptBaseClass.PRIM_TEXT:
9131 res.Add(new LSL_String(""));
9132 res.Add(new LSL_Vector(0f,0f,0f));
9133 res.Add(new LSL_Float(1.0f));
9134 break;
9135
9136 case (int)ScriptBaseClass.PRIM_NAME:
9137 res.Add(new LSL_String(avatar.Name));
9138 break;
9139
9140 case (int)ScriptBaseClass.PRIM_DESC:
9141 res.Add(new LSL_String(""));
9142 break;
9143
9144 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
9145 Quaternion lrot = avatar.Rotation;
9146
9147 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
9148 {
9149 lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset
9150 }
9151 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
9152 break;
9153
9154 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
9155 Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part
9156 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
9157 lpos -= lsitOffset;
9158
9159 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
9160 {
9161 lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim
9162 }
9163 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
9164 break;
9165
9166 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
9167 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
9168 return res;
9169 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
9170 LSL_List new_rules = rules.GetSublist(idx, -1);
9171
9172 res += llGetLinkPrimitiveParams((int)new_linknumber, new_rules);
9173 return res;
9174 } 8733 }
9175 } 8734 }
8735
9176 return res; 8736 return res;
9177 } 8737 }
9178 8738
9179 public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules) 8739 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res)
9180 { 8740 {
9181 LSL_List res = new LSL_List();
9182 int idx=0; 8741 int idx=0;
9183 while (idx < rules.Length) 8742 while (idx < rules.Length)
9184 { 8743 {
@@ -9316,7 +8875,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9316 8875
9317 case (int)ScriptBaseClass.PRIM_TEXTURE: 8876 case (int)ScriptBaseClass.PRIM_TEXTURE:
9318 if (remain < 1) 8877 if (remain < 1)
9319 return res; 8878 return null;
9320 8879
9321 int face = (int)rules.GetLSLIntegerItem(idx++); 8880 int face = (int)rules.GetLSLIntegerItem(idx++);
9322 Primitive.TextureEntry tex = part.Shape.Textures; 8881 Primitive.TextureEntry tex = part.Shape.Textures;
@@ -9356,7 +8915,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9356 8915
9357 case (int)ScriptBaseClass.PRIM_COLOR: 8916 case (int)ScriptBaseClass.PRIM_COLOR:
9358 if (remain < 1) 8917 if (remain < 1)
9359 return res; 8918 return null;
9360 8919
9361 face=(int)rules.GetLSLIntegerItem(idx++); 8920 face=(int)rules.GetLSLIntegerItem(idx++);
9362 8921
@@ -9385,7 +8944,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9385 8944
9386 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8945 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
9387 if (remain < 1) 8946 if (remain < 1)
9388 return res; 8947 return null;
8948
9389 face = (int)rules.GetLSLIntegerItem(idx++); 8949 face = (int)rules.GetLSLIntegerItem(idx++);
9390 8950
9391 tex = part.Shape.Textures; 8951 tex = part.Shape.Textures;
@@ -9441,7 +9001,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9441 9001
9442 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 9002 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
9443 if (remain < 1) 9003 if (remain < 1)
9444 return res; 9004 return null;
9005
9445 face = (int)rules.GetLSLIntegerItem(idx++); 9006 face = (int)rules.GetLSLIntegerItem(idx++);
9446 9007
9447 tex = part.Shape.Textures; 9008 tex = part.Shape.Textures;
@@ -9495,7 +9056,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9495 case (int)ScriptBaseClass.PRIM_TEXGEN: 9056 case (int)ScriptBaseClass.PRIM_TEXGEN:
9496 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) 9057 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
9497 if (remain < 1) 9058 if (remain < 1)
9498 return res; 9059 return null;
9060
9499 face = (int)rules.GetLSLIntegerItem(idx++); 9061 face = (int)rules.GetLSLIntegerItem(idx++);
9500 9062
9501 tex = part.Shape.Textures; 9063 tex = part.Shape.Textures;
@@ -9543,7 +9105,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9543 9105
9544 case (int)ScriptBaseClass.PRIM_GLOW: 9106 case (int)ScriptBaseClass.PRIM_GLOW:
9545 if (remain < 1) 9107 if (remain < 1)
9546 return res; 9108 return null;
9109
9547 face = (int)rules.GetLSLIntegerItem(idx++); 9110 face = (int)rules.GetLSLIntegerItem(idx++);
9548 9111
9549 tex = part.Shape.Textures; 9112 tex = part.Shape.Textures;
@@ -9587,18 +9150,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9587 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 9150 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
9588 res.Add(new LSL_Vector(GetPartLocalPos(part))); 9151 res.Add(new LSL_Vector(GetPartLocalPos(part)));
9589 break; 9152 break;
9590 9153 case (int)ScriptBaseClass.PRIM_SLICE:
9154 PrimType prim_type = part.GetPrimType();
9155 bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING);
9156 res.Add(new LSL_Vector(
9157 (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0,
9158 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0,
9159 0
9160 ));
9161 break;
9591 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 9162 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
9592 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 9163 if(remain < 3)
9593 return res; 9164 return null;
9594 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); 9165
9595 LSL_List new_rules = rules.GetSublist(idx, -1); 9166 return rules.GetSublist(idx, -1);
9596 LSL_List tres = llGetLinkPrimitiveParams((int)new_linknumber, new_rules);
9597 res += tres;
9598 return res;
9599 } 9167 }
9600 } 9168 }
9601 return res; 9169
9170 return null;
9602 } 9171 }
9603 9172
9604 public LSL_List llGetPrimMediaParams(int face, LSL_List rules) 9173 public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
@@ -10511,11 +10080,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10511 10080
10512 GridRegion info; 10081 GridRegion info;
10513 10082
10514 if (m_ScriptEngine.World.RegionInfo.RegionName == simulator) //Det data for this simulator? 10083 if (World.RegionInfo.RegionName == simulator)
10515 10084 info = new GridRegion(World.RegionInfo);
10516 info = new GridRegion(m_ScriptEngine.World.RegionInfo);
10517 else 10085 else
10518 info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); 10086 info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator);
10519 10087
10520 switch (data) 10088 switch (data)
10521 { 10089 {
@@ -10525,9 +10093,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10525 ScriptSleep(1000); 10093 ScriptSleep(1000);
10526 return UUID.Zero.ToString(); 10094 return UUID.Zero.ToString();
10527 } 10095 }
10528 if (m_ScriptEngine.World.RegionInfo.RegionName != simulator) 10096
10097 bool isHypergridRegion = false;
10098
10099 if (World.RegionInfo.RegionName != simulator && info.RegionSecret != "")
10100 {
10101 // Hypergrid is currently placing real destination region co-ords into RegionSecret.
10102 // But other code can also use this field for a genuine RegionSecret! Therefore, if
10103 // anything is present we need to disambiguate.
10104 //
10105 // FIXME: Hypergrid should be storing this data in a different field.
10106 RegionFlags regionFlags
10107 = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags(
10108 info.ScopeID, info.RegionID);
10109 isHypergridRegion = (regionFlags & RegionFlags.Hyperlink) != 0;
10110 }
10111
10112 if (isHypergridRegion)
10529 { 10113 {
10530 //Hypergrid Region co-ordinates
10531 uint rx = 0, ry = 0; 10114 uint rx = 0, ry = 0;
10532 Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); 10115 Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry);
10533 10116
@@ -10538,7 +10121,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10538 } 10121 }
10539 else 10122 else
10540 { 10123 {
10541 //Local-cooridnates 10124 // Local grid co-oridnates
10542 reply = new LSL_Vector( 10125 reply = new LSL_Vector(
10543 info.RegionLocX, 10126 info.RegionLocX,
10544 info.RegionLocY, 10127 info.RegionLocY,
@@ -10992,20 +10575,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10992 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString())) 10575 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
10993 { 10576 {
10994 case ParcelMediaCommandEnum.Url: 10577 case ParcelMediaCommandEnum.Url:
10995 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10578 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL));
10996 break; 10579 break;
10997 case ParcelMediaCommandEnum.Desc: 10580 case ParcelMediaCommandEnum.Desc:
10998 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description)); 10581 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description));
10999 break; 10582 break;
11000 case ParcelMediaCommandEnum.Texture: 10583 case ParcelMediaCommandEnum.Texture:
11001 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString())); 10584 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString()));
11002 break; 10585 break;
11003 case ParcelMediaCommandEnum.Type: 10586 case ParcelMediaCommandEnum.Type:
11004 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaType)); 10587 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType));
11005 break; 10588 break;
11006 case ParcelMediaCommandEnum.Size: 10589 case ParcelMediaCommandEnum.Size:
11007 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaWidth)); 10590 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth));
11008 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaHeight)); 10591 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight));
11009 break; 10592 break;
11010 default: 10593 default:
11011 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; 10594 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
@@ -11175,9 +10758,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11175 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10758 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
11176 if (avatar != null) 10759 if (avatar != null)
11177 { 10760 {
11178 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, simname, 10761 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name,
11179 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10762 simname, pos, lookAt);
11180 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
11181 } 10763 }
11182 10764
11183 ScriptSleep(1000); 10765 ScriptSleep(1000);
@@ -11362,31 +10944,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11362 public LSL_Float llListStatistics(int operation, LSL_List src) 10944 public LSL_Float llListStatistics(int operation, LSL_List src)
11363 { 10945 {
11364 m_host.AddScriptLPS(1); 10946 m_host.AddScriptLPS(1);
11365 LSL_List nums = LSL_List.ToDoubleList(src);
11366 switch (operation) 10947 switch (operation)
11367 { 10948 {
11368 case ScriptBaseClass.LIST_STAT_RANGE: 10949 case ScriptBaseClass.LIST_STAT_RANGE:
11369 return nums.Range(); 10950 return src.Range();
11370 case ScriptBaseClass.LIST_STAT_MIN: 10951 case ScriptBaseClass.LIST_STAT_MIN:
11371 return nums.Min(); 10952 return src.Min();
11372 case ScriptBaseClass.LIST_STAT_MAX: 10953 case ScriptBaseClass.LIST_STAT_MAX:
11373 return nums.Max(); 10954 return src.Max();
11374 case ScriptBaseClass.LIST_STAT_MEAN: 10955 case ScriptBaseClass.LIST_STAT_MEAN:
11375 return nums.Mean(); 10956 return src.Mean();
11376 case ScriptBaseClass.LIST_STAT_MEDIAN: 10957 case ScriptBaseClass.LIST_STAT_MEDIAN:
11377 return nums.Median(); 10958 return LSL_List.ToDoubleList(src).Median();
11378 case ScriptBaseClass.LIST_STAT_NUM_COUNT: 10959 case ScriptBaseClass.LIST_STAT_NUM_COUNT:
11379 return nums.NumericLength(); 10960 return src.NumericLength();
11380 case ScriptBaseClass.LIST_STAT_STD_DEV: 10961 case ScriptBaseClass.LIST_STAT_STD_DEV:
11381 return nums.StdDev(); 10962 return src.StdDev();
11382 case ScriptBaseClass.LIST_STAT_SUM: 10963 case ScriptBaseClass.LIST_STAT_SUM:
11383 return nums.Sum(); 10964 return src.Sum();
11384 case ScriptBaseClass.LIST_STAT_SUM_SQUARES: 10965 case ScriptBaseClass.LIST_STAT_SUM_SQUARES:
11385 return nums.SumSqrs(); 10966 return src.SumSqrs();
11386 case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: 10967 case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN:
11387 return nums.GeometricMean(); 10968 return src.GeometricMean();
11388 case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: 10969 case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN:
11389 return nums.HarmonicMean(); 10970 return src.HarmonicMean();
11390 default: 10971 default:
11391 return 0.0; 10972 return 0.0;
11392 } 10973 }
@@ -11744,7 +11325,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11744 public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) 11325 public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param)
11745 { 11326 {
11746 m_host.AddScriptLPS(1); 11327 m_host.AddScriptLPS(1);
11747 LandData land = World.GetLandData((float)pos.x, (float)pos.y); 11328 LandData land = World.GetLandData(pos);
11748 if (land == null) 11329 if (land == null)
11749 { 11330 {
11750 return new LSL_List(0); 11331 return new LSL_List(0);
@@ -11912,13 +11493,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11912 else 11493 else
11913 rot = obj.GetWorldRotation(); 11494 rot = obj.GetWorldRotation();
11914 11495
11915 LSL_Rotation objrot = new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); 11496 LSL_Rotation objrot = new LSL_Rotation(rot);
11916 ret.Add(objrot); 11497 ret.Add(objrot);
11917 } 11498 }
11918 break; 11499 break;
11919 case ScriptBaseClass.OBJECT_VELOCITY: 11500 case ScriptBaseClass.OBJECT_VELOCITY:
11920 Vector3 ovel = obj.Velocity; 11501 ret.Add(new LSL_Vector(obj.Velocity));
11921 ret.Add(new LSL_Vector(ovel.X, ovel.Y, ovel.Z));
11922 break; 11502 break;
11923 case ScriptBaseClass.OBJECT_OWNER: 11503 case ScriptBaseClass.OBJECT_OWNER:
11924 ret.Add(new LSL_String(obj.OwnerID.ToString())); 11504 ret.Add(new LSL_String(obj.OwnerID.ToString()));
@@ -12005,12 +11585,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12005 11585
12006 internal void Deprecated(string command) 11586 internal void Deprecated(string command)
12007 { 11587 {
12008 throw new Exception("Command deprecated: " + command); 11588 throw new ScriptException("Command deprecated: " + command);
12009 } 11589 }
12010 11590
12011 internal void LSLError(string msg) 11591 internal void LSLError(string msg)
12012 { 11592 {
12013 throw new Exception("LSL Runtime Error: " + msg); 11593 throw new ScriptException("LSL Runtime Error: " + msg);
12014 } 11594 }
12015 11595
12016 public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); 11596 public delegate void AssetRequestCallback(UUID assetID, AssetBase asset);
@@ -12131,7 +11711,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12131 return tid.ToString(); 11711 return tid.ToString();
12132 } 11712 }
12133 11713
12134 public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) 11714 public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc)
12135 { 11715 {
12136 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); 11716 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
12137 if (obj == null) 11717 if (obj == null)
@@ -12140,28 +11720,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12140 if (obj.OwnerID != m_host.OwnerID) 11720 if (obj.OwnerID != m_host.OwnerID)
12141 return; 11721 return;
12142 11722
12143 LSL_List remaining = SetPrimParams(obj, rules); 11723 uint rulesParsed = 0;
11724 LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed);
12144 11725
12145 while ((object)remaining != null && remaining.Length > 2) 11726 while ((object)remaining != null && remaining.Length > 2)
12146 { 11727 {
12147 LSL_Integer newLink = remaining.GetLSLIntegerItem(0); 11728 LSL_Integer newLink = remaining.GetLSLIntegerItem(0);
12148 LSL_List newrules = remaining.GetSublist(1, -1); 11729 LSL_List newrules = remaining.GetSublist(1, -1);
12149 foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ 11730 foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){
12150 remaining = SetPrimParams(part, newrules); 11731 remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed);
12151 } 11732 }
12152 } 11733 }
12153 } 11734 }
12154 11735
12155 public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules) 11736 public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
12156 { 11737 {
12157 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); 11738 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
12158 if (obj == null)
12159 return new LSL_List();
12160 11739
12161 if (obj.OwnerID != m_host.OwnerID) 11740 LSL_List result = new LSL_List();
12162 return new LSL_List(); 11741
11742 if (obj != null && obj.OwnerID != m_host.OwnerID)
11743 {
11744 LSL_List remaining = GetPrimParams(obj, rules, ref result);
11745
11746 while (remaining != null && remaining.Length > 2)
11747 {
11748 int linknumber = remaining.GetLSLIntegerItem(0);
11749 rules = remaining.GetSublist(1, -1);
11750 List<SceneObjectPart> parts = GetLinkParts(linknumber);
11751
11752 foreach (SceneObjectPart part in parts)
11753 remaining = GetPrimParams(part, rules, ref result);
11754 }
11755 }
12163 11756
12164 return GetLinkPrimitiveParams(obj, rules); 11757 return result;
12165 } 11758 }
12166 11759
12167 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) 11760 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
@@ -12524,8 +12117,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12524 12117
12525 m_host.AddScriptLPS(1); 12118 m_host.AddScriptLPS(1);
12526 12119
12527 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z); 12120 Vector3 rayStart = start;
12528 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z); 12121 Vector3 rayEnd = end;
12529 Vector3 dir = rayEnd - rayStart; 12122 Vector3 dir = rayEnd - rayStart;
12530 12123
12531 float dist = Vector3.Mag(dir); 12124 float dist = Vector3.Mag(dir);
@@ -12936,7 +12529,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12936 } 12529 }
12937 12530
12938 bool result = money.ObjectGiveMoney( 12531 bool result = money.ObjectGiveMoney(
12939 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); 12532 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount, txn);
12940 12533
12941 if (result) 12534 if (result)
12942 { 12535 {
@@ -13099,6 +12692,455 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13099 } 12692 }
13100 } 12693 }
13101 } 12694 }
12695
12696 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed)
12697 {
12698 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
12699
12700 int idx = 0;
12701 int idxStart = 0;
12702
12703 bool positionChanged = false;
12704 Vector3 finalPos = Vector3.Zero;
12705
12706 try
12707 {
12708 while (idx < rules.Length)
12709 {
12710 ++rulesParsed;
12711 int code = rules.GetLSLIntegerItem(idx++);
12712
12713 int remain = rules.Length - idx;
12714 idxStart = idx;
12715
12716 switch (code)
12717 {
12718 case (int)ScriptBaseClass.PRIM_POSITION:
12719 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
12720 {
12721 if (remain < 1)
12722 return null;
12723
12724 LSL_Vector v;
12725 v = rules.GetVector3Item(idx++);
12726
12727 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12728 if (part == null)
12729 break;
12730
12731 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12732 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12733 if (part.LinkNum > 1)
12734 {
12735 localRot = GetPartLocalRot(part);
12736 localPos = GetPartLocalPos(part);
12737 }
12738
12739 v -= localPos;
12740 v /= localRot;
12741
12742 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
12743
12744 v = v + 2 * sitOffset;
12745
12746 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
12747 av.SendAvatarDataToAllAgents();
12748
12749 }
12750 break;
12751
12752 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
12753 case (int)ScriptBaseClass.PRIM_ROTATION:
12754 {
12755 if (remain < 1)
12756 return null;
12757
12758 LSL_Rotation r;
12759 r = rules.GetQuaternionItem(idx++);
12760
12761 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12762 if (part == null)
12763 break;
12764
12765 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12766 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12767
12768 if (part.LinkNum > 1)
12769 localRot = GetPartLocalRot(part);
12770
12771 r = r * llGetRootRotation() / localRot;
12772 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
12773 av.SendAvatarDataToAllAgents();
12774 }
12775 break;
12776
12777 // parse rest doing nothing but number of parameters error check
12778 case (int)ScriptBaseClass.PRIM_SIZE:
12779 case (int)ScriptBaseClass.PRIM_MATERIAL:
12780 case (int)ScriptBaseClass.PRIM_PHANTOM:
12781 case (int)ScriptBaseClass.PRIM_PHYSICS:
12782 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
12783 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
12784 case (int)ScriptBaseClass.PRIM_NAME:
12785 case (int)ScriptBaseClass.PRIM_DESC:
12786 if (remain < 1)
12787 return null;
12788 idx++;
12789 break;
12790
12791 case (int)ScriptBaseClass.PRIM_GLOW:
12792 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
12793 case (int)ScriptBaseClass.PRIM_TEXGEN:
12794 if (remain < 2)
12795 return null;
12796 idx += 2;
12797 break;
12798
12799 case (int)ScriptBaseClass.PRIM_TYPE:
12800 if (remain < 3)
12801 return null;
12802 code = (int)rules.GetLSLIntegerItem(idx++);
12803 remain = rules.Length - idx;
12804 switch (code)
12805 {
12806 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
12807 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
12808 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
12809 if (remain < 6)
12810 return null;
12811 idx += 6;
12812 break;
12813
12814 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
12815 if (remain < 5)
12816 return null;
12817 idx += 5;
12818 break;
12819
12820 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
12821 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
12822 case (int)ScriptBaseClass.PRIM_TYPE_RING:
12823 if (remain < 11)
12824 return null;
12825 idx += 11;
12826 break;
12827
12828 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
12829 if (remain < 2)
12830 return null;
12831 idx += 2;
12832 break;
12833 }
12834 break;
12835
12836 case (int)ScriptBaseClass.PRIM_COLOR:
12837 case (int)ScriptBaseClass.PRIM_TEXT:
12838 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
12839 case (int)ScriptBaseClass.PRIM_OMEGA:
12840 if (remain < 3)
12841 return null;
12842 idx += 3;
12843 break;
12844
12845 case (int)ScriptBaseClass.PRIM_TEXTURE:
12846 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
12847 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
12848 if (remain < 5)
12849 return null;
12850 idx += 5;
12851 break;
12852
12853 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
12854 if (remain < 7)
12855 return null;
12856
12857 idx += 7;
12858 break;
12859
12860 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
12861 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
12862 return null;
12863
12864 return rules.GetSublist(idx, -1);
12865 }
12866 }
12867 }
12868 catch (InvalidCastException e)
12869 {
12870 ShoutError(string.Format(
12871 "{0} error running rule #{1}: arg #{2} ",
12872 originFunc, rulesParsed, idx - idxStart) + e.Message);
12873 }
12874 finally
12875 {
12876 if (positionChanged)
12877 {
12878 av.OffsetPosition = finalPos;
12879// av.SendAvatarDataToAllAgents();
12880 av.SendTerseUpdateToAllClients();
12881 positionChanged = false;
12882 }
12883 }
12884 return null;
12885 }
12886
12887 public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res)
12888 {
12889 // avatars case
12890 // replies as SL wiki
12891
12892// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
12893 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
12894
12895 int idx = 0;
12896 while (idx < rules.Length)
12897 {
12898 int code = (int)rules.GetLSLIntegerItem(idx++);
12899 int remain = rules.Length - idx;
12900
12901 switch (code)
12902 {
12903 case (int)ScriptBaseClass.PRIM_MATERIAL:
12904 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh));
12905 break;
12906
12907 case (int)ScriptBaseClass.PRIM_PHYSICS:
12908 res.Add(new LSL_Integer(0));
12909 break;
12910
12911 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
12912 res.Add(new LSL_Integer(0));
12913 break;
12914
12915 case (int)ScriptBaseClass.PRIM_PHANTOM:
12916 res.Add(new LSL_Integer(0));
12917 break;
12918
12919 case (int)ScriptBaseClass.PRIM_POSITION:
12920
12921 Vector3 pos = avatar.OffsetPosition;
12922
12923 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
12924 pos -= sitOffset;
12925
12926 if( sitPart != null)
12927 pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation();
12928
12929 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
12930 break;
12931
12932 case (int)ScriptBaseClass.PRIM_SIZE:
12933 // as in llGetAgentSize above
12934 res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight));
12935 break;
12936
12937 case (int)ScriptBaseClass.PRIM_ROTATION:
12938 Quaternion rot = avatar.Rotation;
12939 if (sitPart != null)
12940 {
12941 rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation
12942 }
12943
12944 res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W));
12945 break;
12946
12947 case (int)ScriptBaseClass.PRIM_TYPE:
12948 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
12949 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
12950 res.Add(new LSL_Vector(0f,1.0f,0f));
12951 res.Add(new LSL_Float(0.0f));
12952 res.Add(new LSL_Vector(0, 0, 0));
12953 res.Add(new LSL_Vector(1.0f,1.0f,0f));
12954 res.Add(new LSL_Vector(0, 0, 0));
12955 break;
12956
12957 case (int)ScriptBaseClass.PRIM_TEXTURE:
12958 if (remain < 1)
12959 return null;
12960
12961 int face = (int)rules.GetLSLIntegerItem(idx++);
12962 if (face == ScriptBaseClass.ALL_SIDES)
12963 {
12964 for (face = 0; face < 21; face++)
12965 {
12966 res.Add(new LSL_String(""));
12967 res.Add(new LSL_Vector(0,0,0));
12968 res.Add(new LSL_Vector(0,0,0));
12969 res.Add(new LSL_Float(0.0));
12970 }
12971 }
12972 else
12973 {
12974 if (face >= 0 && face < 21)
12975 {
12976 res.Add(new LSL_String(""));
12977 res.Add(new LSL_Vector(0,0,0));
12978 res.Add(new LSL_Vector(0,0,0));
12979 res.Add(new LSL_Float(0.0));
12980 }
12981 }
12982 break;
12983
12984 case (int)ScriptBaseClass.PRIM_COLOR:
12985 if (remain < 1)
12986 return null;
12987
12988 face = (int)rules.GetLSLIntegerItem(idx++);
12989
12990 if (face == ScriptBaseClass.ALL_SIDES)
12991 {
12992 for (face = 0; face < 21; face++)
12993 {
12994 res.Add(new LSL_Vector(0,0,0));
12995 res.Add(new LSL_Float(0));
12996 }
12997 }
12998 else
12999 {
13000 res.Add(new LSL_Vector(0,0,0));
13001 res.Add(new LSL_Float(0));
13002 }
13003 break;
13004
13005 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
13006 if (remain < 1)
13007 return null;
13008 face = (int)rules.GetLSLIntegerItem(idx++);
13009
13010 if (face == ScriptBaseClass.ALL_SIDES)
13011 {
13012 for (face = 0; face < 21; face++)
13013 {
13014 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
13015 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
13016 }
13017 }
13018 else
13019 {
13020 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
13021 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
13022 }
13023 break;
13024
13025 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
13026 if (remain < 1)
13027 return null;
13028 face = (int)rules.GetLSLIntegerItem(idx++);
13029
13030 if (face == ScriptBaseClass.ALL_SIDES)
13031 {
13032 for (face = 0; face < 21; face++)
13033 {
13034 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
13035 }
13036 }
13037 else
13038 {
13039 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
13040 }
13041 break;
13042
13043 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
13044 res.Add(new LSL_Integer(0));
13045 res.Add(new LSL_Integer(0));// softness
13046 res.Add(new LSL_Float(0.0f)); // gravity
13047 res.Add(new LSL_Float(0.0f)); // friction
13048 res.Add(new LSL_Float(0.0f)); // wind
13049 res.Add(new LSL_Float(0.0f)); // tension
13050 res.Add(new LSL_Vector(0f,0f,0f));
13051 break;
13052
13053 case (int)ScriptBaseClass.PRIM_TEXGEN:
13054 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
13055 if (remain < 1)
13056 return null;
13057 face = (int)rules.GetLSLIntegerItem(idx++);
13058
13059 if (face == ScriptBaseClass.ALL_SIDES)
13060 {
13061 for (face = 0; face < 21; face++)
13062 {
13063 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13064 }
13065 }
13066 else
13067 {
13068 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13069 }
13070 break;
13071
13072 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
13073 res.Add(new LSL_Integer(0));
13074 res.Add(new LSL_Vector(0f,0f,0f));
13075 res.Add(new LSL_Float(0f)); // intensity
13076 res.Add(new LSL_Float(0f)); // radius
13077 res.Add(new LSL_Float(0f)); // falloff
13078 break;
13079
13080 case (int)ScriptBaseClass.PRIM_GLOW:
13081 if (remain < 1)
13082 return null;
13083 face = (int)rules.GetLSLIntegerItem(idx++);
13084
13085 if (face == ScriptBaseClass.ALL_SIDES)
13086 {
13087 for (face = 0; face < 21; face++)
13088 {
13089 res.Add(new LSL_Float(0f));
13090 }
13091 }
13092 else
13093 {
13094 res.Add(new LSL_Float(0f));
13095 }
13096 break;
13097
13098 case (int)ScriptBaseClass.PRIM_TEXT:
13099 res.Add(new LSL_String(""));
13100 res.Add(new LSL_Vector(0f,0f,0f));
13101 res.Add(new LSL_Float(1.0f));
13102 break;
13103
13104 case (int)ScriptBaseClass.PRIM_NAME:
13105 res.Add(new LSL_String(avatar.Name));
13106 break;
13107
13108 case (int)ScriptBaseClass.PRIM_DESC:
13109 res.Add(new LSL_String(""));
13110 break;
13111
13112 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
13113 Quaternion lrot = avatar.Rotation;
13114
13115 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13116 {
13117 lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset
13118 }
13119 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
13120 break;
13121
13122 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
13123 Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part
13124 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
13125 lpos -= lsitOffset;
13126
13127 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13128 {
13129 lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim
13130 }
13131 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
13132 break;
13133
13134 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
13135 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
13136 return null;
13137
13138 return rules.GetSublist(idx, -1);
13139 }
13140 }
13141
13142 return null;
13143 }
13102 } 13144 }
13103 13145
13104 public class NotecardCache 13146 public class NotecardCache
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
index 795de80..ceb4660 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
@@ -304,7 +304,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
304 case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: 304 case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY:
305 idx++; 305 idx++;
306 iV = rules.GetVector3Item(idx); 306 iV = rules.GetVector3Item(idx);
307 wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); 307 wl.cloudDetailXYDensity = iV;
308 break; 308 break;
309 case (int)ScriptBaseClass.WL_CLOUD_SCALE: 309 case (int)ScriptBaseClass.WL_CLOUD_SCALE:
310 idx++; 310 idx++;
@@ -329,7 +329,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
329 case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: 329 case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY:
330 idx++; 330 idx++;
331 iV = rules.GetVector3Item(idx); 331 iV = rules.GetVector3Item(idx);
332 wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); 332 wl.cloudXYDensity = iV;
333 break; 333 break;
334 case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: 334 case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER:
335 idx++; 335 idx++;
@@ -384,7 +384,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
384 case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: 384 case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE:
385 idx++; 385 idx++;
386 iV = rules.GetVector3Item(idx); 386 iV = rules.GetVector3Item(idx);
387 wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); 387 wl.reflectionWaveletScale = iV;
388 break; 388 break;
389 case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: 389 case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE:
390 idx++; 390 idx++;
@@ -422,7 +422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
422 case (int)ScriptBaseClass.WL_WATER_COLOR: 422 case (int)ScriptBaseClass.WL_WATER_COLOR:
423 idx++; 423 idx++;
424 iV = rules.GetVector3Item(idx); 424 iV = rules.GetVector3Item(idx);
425 wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); 425 wl.waterColor = iV;
426 break; 426 break;
427 case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: 427 case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT:
428 idx++; 428 idx++;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index 7844c75..8f34833 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -95,13 +95,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
95 95
96 internal void MODError(string msg) 96 internal void MODError(string msg)
97 { 97 {
98 throw new Exception("MOD Runtime Error: " + msg); 98 throw new ScriptException("MOD Runtime Error: " + msg);
99 } 99 }
100 100
101 // 101 /// <summary>
102 //Dumps an error message on the debug console. 102 /// Dumps an error message on the debug console.
103 // 103 /// </summary>
104 104 /// <param name='message'></param>
105 internal void MODShoutError(string message) 105 internal void MODShoutError(string message)
106 { 106 {
107 if (message.Length > 1023) 107 if (message.Length > 1023)
@@ -254,7 +254,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
254 254
255 object[] convertedParms = new object[parms.Length]; 255 object[] convertedParms = new object[parms.Length];
256 for (int i = 0; i < parms.Length; i++) 256 for (int i = 0; i < parms.Length; i++)
257 convertedParms[i] = ConvertFromLSL(parms[i],signature[i]); 257 convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname);
258 258
259 // now call the function, the contract with the function is that it will always return 259 // now call the function, the contract with the function is that it will always return
260 // non-null but don't trust it completely 260 // non-null but don't trust it completely
@@ -294,7 +294,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
294 294
295 /// <summary> 295 /// <summary>
296 /// </summary> 296 /// </summary>
297 protected object ConvertFromLSL(object lslparm, Type type) 297 protected object ConvertFromLSL(object lslparm, Type type, string fname)
298 { 298 {
299 // ---------- String ---------- 299 // ---------- String ----------
300 if (lslparm is LSL_String) 300 if (lslparm is LSL_String)
@@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
310 // ---------- Integer ---------- 310 // ---------- Integer ----------
311 else if (lslparm is LSL_Integer) 311 else if (lslparm is LSL_Integer)
312 { 312 {
313 if (type == typeof(int)) 313 if (type == typeof(int) || type == typeof(float))
314 return (int)(LSL_Integer)lslparm; 314 return (int)(LSL_Integer)lslparm;
315 } 315 }
316 316
@@ -333,8 +333,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
333 { 333 {
334 if (type == typeof(OpenMetaverse.Quaternion)) 334 if (type == typeof(OpenMetaverse.Quaternion))
335 { 335 {
336 LSL_Rotation rot = (LSL_Rotation)lslparm; 336 return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm);
337 return new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s);
338 } 337 }
339 } 338 }
340 339
@@ -343,8 +342,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
343 { 342 {
344 if (type == typeof(OpenMetaverse.Vector3)) 343 if (type == typeof(OpenMetaverse.Vector3))
345 { 344 {
346 LSL_Vector vect = (LSL_Vector)lslparm; 345 return (OpenMetaverse.Vector3)((LSL_Vector)lslparm);
347 return new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z);
348 } 346 }
349 } 347 }
350 348
@@ -361,29 +359,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
361 result[i] = (string)(LSL_String)plist[i]; 359 result[i] = (string)(LSL_String)plist[i];
362 else if (plist[i] is LSL_Integer) 360 else if (plist[i] is LSL_Integer)
363 result[i] = (int)(LSL_Integer)plist[i]; 361 result[i] = (int)(LSL_Integer)plist[i];
362 // The int check exists because of the many plain old int script constants in ScriptBase which
363 // are not LSL_Integers.
364 else if (plist[i] is int)
365 result[i] = plist[i];
364 else if (plist[i] is LSL_Float) 366 else if (plist[i] is LSL_Float)
365 result[i] = (float)(LSL_Float)plist[i]; 367 result[i] = (float)(LSL_Float)plist[i];
366 else if (plist[i] is LSL_Key) 368 else if (plist[i] is LSL_Key)
367 result[i] = new UUID((LSL_Key)plist[i]); 369 result[i] = new UUID((LSL_Key)plist[i]);
368 else if (plist[i] is LSL_Rotation) 370 else if (plist[i] is LSL_Rotation)
369 { 371 result[i] = (Quaternion)((LSL_Rotation)plist[i]);
370 LSL_Rotation rot = (LSL_Rotation)plist[i];
371 result[i] = new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s);
372 }
373 else if (plist[i] is LSL_Vector) 372 else if (plist[i] is LSL_Vector)
374 { 373 result[i] = (Vector3)((LSL_Vector)plist[i]);
375 LSL_Vector vect = (LSL_Vector)plist[i];
376 result[i] = new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z);
377 }
378 else 374 else
379 MODError("unknown LSL list element type"); 375 MODError(String.Format("{0}: unknown LSL list element type", fname));
380 } 376 }
381 377
382 return result; 378 return result;
383 } 379 }
384 } 380 }
385 381
386 MODError(String.Format("parameter type mismatch; expecting {0}",type.Name)); 382 MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname));
387 return null; 383 return null;
388 } 384 }
389 385
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 80111f9..51c8c7e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -141,6 +141,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
141 internal bool m_debuggerSafe = false; 141 internal bool m_debuggerSafe = false;
142 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); 142 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
143 143
144 protected IUrlModule m_UrlModule = null;
145
144 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 146 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
145 { 147 {
146 m_ScriptEngine = ScriptEngine; 148 m_ScriptEngine = ScriptEngine;
@@ -148,6 +150,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
148 m_item = item; 150 m_item = item;
149 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); 151 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
150 152
153 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
154
151 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) 155 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
152 m_OSFunctionsEnabled = true; 156 m_OSFunctionsEnabled = true;
153 157
@@ -214,7 +218,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
214 } 218 }
215 else 219 else
216 { 220 {
217 throw new Exception("OSSL Runtime Error: " + msg); 221 throw new ScriptException("OSSL Runtime Error: " + msg);
218 } 222 }
219 } 223 }
220 224
@@ -782,10 +786,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
782 786
783 // We will launch the teleport on a new thread so that when the script threads are terminated 787 // We will launch the teleport on a new thread so that when the script threads are terminated
784 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. 788 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
785 Util.FireAndForget( 789 Util.FireAndForget(o => World.RequestTeleportLocation(
786 o => World.RequestTeleportLocation(presence.ControllingClient, regionName, 790 presence.ControllingClient, regionName, position,
787 new Vector3((float)position.x, (float)position.y, (float)position.z), 791 lookat, (uint)TPFlags.ViaLocation));
788 new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
789 792
790 ScriptSleep(5000); 793 ScriptSleep(5000);
791 794
@@ -828,10 +831,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
828 831
829 // We will launch the teleport on a new thread so that when the script threads are terminated 832 // We will launch the teleport on a new thread so that when the script threads are terminated
830 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. 833 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
831 Util.FireAndForget( 834 Util.FireAndForget(o => World.RequestTeleportLocation(
832 o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle, 835 presence.ControllingClient, regionHandle,
833 new Vector3((float)position.x, (float)position.y, (float)position.z), 836 position, lookat, (uint)TPFlags.ViaLocation));
834 new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
835 837
836 ScriptSleep(5000); 838 ScriptSleep(5000);
837 839
@@ -1680,6 +1682,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1680 return; 1682 return;
1681 } 1683 }
1682 1684
1685 MessageObject(objUUID, message);
1686 }
1687
1688 private void MessageObject(UUID objUUID, string message)
1689 {
1683 object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) }; 1690 object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) };
1684 1691
1685 SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID); 1692 SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID);
@@ -1782,18 +1789,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1782 protected string LoadNotecard(string notecardNameOrUuid) 1789 protected string LoadNotecard(string notecardNameOrUuid)
1783 { 1790 {
1784 UUID assetID = CacheNotecard(notecardNameOrUuid); 1791 UUID assetID = CacheNotecard(notecardNameOrUuid);
1785 StringBuilder notecardData = new StringBuilder();
1786 1792
1787 for (int count = 0; count < NotecardCache.GetLines(assetID); count++) 1793 if (assetID != UUID.Zero)
1788 { 1794 {
1789 string line = NotecardCache.GetLine(assetID, count) + "\n"; 1795 StringBuilder notecardData = new StringBuilder();
1790 1796
1791// m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line); 1797 for (int count = 0; count < NotecardCache.GetLines(assetID); count++)
1792 1798 {
1793 notecardData.Append(line); 1799 string line = NotecardCache.GetLine(assetID, count) + "\n";
1800
1801 // m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line);
1802
1803 notecardData.Append(line);
1804 }
1805
1806 return notecardData.ToString();
1794 } 1807 }
1795 1808
1796 return notecardData.ToString(); 1809 return null;
1797 } 1810 }
1798 1811
1799 /// <summary> 1812 /// <summary>
@@ -2259,11 +2272,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2259 CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams"); 2272 CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams");
2260 m_host.AddScriptLPS(1); 2273 m_host.AddScriptLPS(1);
2261 InitLSL(); 2274 InitLSL();
2275 // One needs to cast m_LSL_Api because we're using functions not
2276 // on the ILSL_Api interface.
2277 LSL_Api LSL_Api = (LSL_Api)m_LSL_Api;
2262 LSL_List retVal = new LSL_List(); 2278 LSL_List retVal = new LSL_List();
2263 List<SceneObjectPart> parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber); 2279 LSL_List remaining = null;
2280 List<SceneObjectPart> parts = LSL_Api.GetLinkParts(linknumber);
2264 foreach (SceneObjectPart part in parts) 2281 foreach (SceneObjectPart part in parts)
2265 { 2282 {
2266 retVal += ((LSL_Api)m_LSL_Api).GetLinkPrimitiveParams(part, rules); 2283 remaining = LSL_Api.GetPrimParams(part, rules, ref retVal);
2284 }
2285
2286 while (remaining != null && remaining.Length > 2)
2287 {
2288 linknumber = remaining.GetLSLIntegerItem(0);
2289 rules = remaining.GetSublist(1, -1);
2290 parts = LSL_Api.GetLinkParts(linknumber);
2291
2292 foreach (SceneObjectPart part in parts)
2293 remaining = LSL_Api.GetPrimParams(part, rules, ref retVal);
2267 } 2294 }
2268 return retVal; 2295 return retVal;
2269 } 2296 }
@@ -2352,17 +2379,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2352 return UUID.Zero.ToString(); 2379 return UUID.Zero.ToString();
2353 } 2380 }
2354 } 2381 }
2382 else
2383 {
2384 OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard));
2385 }
2355 } 2386 }
2356 2387
2357 if (appearance == null)
2358 return new LSL_Key(UUID.Zero.ToString());
2359
2360 UUID ownerID = UUID.Zero; 2388 UUID ownerID = UUID.Zero;
2361 if (owned) 2389 if (owned)
2362 ownerID = m_host.OwnerID; 2390 ownerID = m_host.OwnerID;
2363 UUID x = module.CreateNPC(firstname, 2391 UUID x = module.CreateNPC(firstname,
2364 lastname, 2392 lastname,
2365 new Vector3((float) position.x, (float) position.y, (float) position.z), 2393 position,
2366 ownerID, 2394 ownerID,
2367 senseAsAgent, 2395 senseAsAgent,
2368 World, 2396 World,
@@ -2425,6 +2453,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2425 return; 2453 return;
2426 2454
2427 string appearanceSerialized = LoadNotecard(notecard); 2455 string appearanceSerialized = LoadNotecard(notecard);
2456
2457 if (appearanceSerialized == null)
2458 OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard));
2459
2428 OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); 2460 OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized);
2429// OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized); 2461// OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized);
2430// Console.WriteLine("appearanceSerialized {0}", appearanceSerialized); 2462// Console.WriteLine("appearanceSerialized {0}", appearanceSerialized);
@@ -2485,7 +2517,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2485 return new LSL_Vector(0, 0, 0); 2517 return new LSL_Vector(0, 0, 0);
2486 } 2518 }
2487 2519
2488 public void osNpcMoveTo(LSL_Key npc, LSL_Vector position) 2520 public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos)
2489 { 2521 {
2490 CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo"); 2522 CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo");
2491 m_host.AddScriptLPS(1); 2523 m_host.AddScriptLPS(1);
@@ -2500,7 +2532,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2500 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2532 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2501 return; 2533 return;
2502 2534
2503 Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z);
2504 module.MoveToTarget(npcId, World, pos, false, true, false); 2535 module.MoveToTarget(npcId, World, pos, false, true, false);
2505 } 2536 }
2506 } 2537 }
@@ -2520,11 +2551,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2520 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2551 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2521 return; 2552 return;
2522 2553
2523 Vector3 pos = new Vector3((float)target.x, (float)target.y, (float)target.z);
2524 module.MoveToTarget( 2554 module.MoveToTarget(
2525 new UUID(npc.m_string), 2555 new UUID(npc.m_string),
2526 World, 2556 World,
2527 pos, 2557 target,
2528 (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0, 2558 (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0,
2529 (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0, 2559 (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0,
2530 (options & ScriptBaseClass.OS_NPC_RUNNING) != 0); 2560 (options & ScriptBaseClass.OS_NPC_RUNNING) != 0);
@@ -2576,7 +2606,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2576 ScenePresence sp = World.GetScenePresence(npcId); 2606 ScenePresence sp = World.GetScenePresence(npcId);
2577 2607
2578 if (sp != null) 2608 if (sp != null)
2579 sp.Rotation = LSL_Api.Rot2Quaternion(rotation); 2609 sp.Rotation = rotation;
2580 } 2610 }
2581 } 2611 }
2582 2612
@@ -2936,7 +2966,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2936 avatar.SpeedModifier = (float)SpeedModifier; 2966 avatar.SpeedModifier = (float)SpeedModifier;
2937 } 2967 }
2938 2968
2939 public void osKickAvatar(string FirstName,string SurName,string alert) 2969 public void osKickAvatar(string FirstName, string SurName, string alert)
2940 { 2970 {
2941 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); 2971 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar");
2942 m_host.AddScriptLPS(1); 2972 m_host.AddScriptLPS(1);
@@ -2950,10 +2980,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2950 sp.ControllingClient.Kick(alert); 2980 sp.ControllingClient.Kick(alert);
2951 2981
2952 // ...and close on our side 2982 // ...and close on our side
2953 sp.Scene.IncomingCloseAgent(sp.UUID); 2983 sp.Scene.IncomingCloseAgent(sp.UUID, false);
2954 } 2984 }
2955 }); 2985 });
2956 } 2986 }
2987
2988 public LSL_Float osGetHealth(string avatar)
2989 {
2990 CheckThreatLevel(ThreatLevel.None, "osGetHealth");
2991 m_host.AddScriptLPS(1);
2992
2993 LSL_Float health = new LSL_Float(-1);
2994 ScenePresence presence = World.GetScenePresence(new UUID(avatar));
2995 if (presence != null) health = presence.Health;
2996 return health;
2997 }
2957 2998
2958 public void osCauseDamage(string avatar, double damage) 2999 public void osCauseDamage(string avatar, double damage)
2959 { 3000 {
@@ -2966,7 +3007,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2966 ScenePresence presence = World.GetScenePresence(avatarId); 3007 ScenePresence presence = World.GetScenePresence(avatarId);
2967 if (presence != null) 3008 if (presence != null)
2968 { 3009 {
2969 LandData land = World.GetLandData((float)pos.X, (float)pos.Y); 3010 LandData land = World.GetLandData(pos);
2970 if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage) 3011 if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage)
2971 { 3012 {
2972 float health = presence.Health; 3013 float health = presence.Health;
@@ -3013,7 +3054,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3013 m_host.AddScriptLPS(1); 3054 m_host.AddScriptLPS(1);
3014 InitLSL(); 3055 InitLSL();
3015 3056
3016 return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules); 3057 return m_LSL_Api.GetPrimitiveParamsEx(prim, rules);
3017 } 3058 }
3018 3059
3019 public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) 3060 public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules)
@@ -3022,7 +3063,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3022 m_host.AddScriptLPS(1); 3063 m_host.AddScriptLPS(1);
3023 InitLSL(); 3064 InitLSL();
3024 3065
3025 m_LSL_Api.SetPrimitiveParamsEx(prim, rules); 3066 m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams");
3026 } 3067 }
3027 3068
3028 /// <summary> 3069 /// <summary>
@@ -3254,6 +3295,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3254 } 3295 }
3255 } 3296 }
3256 3297
3298 #region Attachment commands
3299
3257 public void osForceAttachToAvatar(int attachmentPoint) 3300 public void osForceAttachToAvatar(int attachmentPoint)
3258 { 3301 {
3259 CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar"); 3302 CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar");
@@ -3343,6 +3386,175 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3343 ((LSL_Api)m_LSL_Api).DetachFromAvatar(); 3386 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3344 } 3387 }
3345 3388
3389 public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
3390 {
3391 CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments");
3392
3393 m_host.AddScriptLPS(1);
3394
3395 UUID targetUUID;
3396 ScenePresence target;
3397 LSL_List resp = new LSL_List();
3398
3399 if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
3400 {
3401 foreach (object point in attachmentPoints.Data)
3402 {
3403 LSL_Integer ipoint = new LSL_Integer(
3404 (point is LSL_Integer || point is int || point is uint) ?
3405 (int)point :
3406 0
3407 );
3408 resp.Add(ipoint);
3409 if (ipoint == 0)
3410 {
3411 // indicates zero attachments
3412 resp.Add(new LSL_Integer(0));
3413 }
3414 else
3415 {
3416 // gets the number of attachments on the attachment point
3417 resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count));
3418 }
3419 }
3420 }
3421
3422 return resp;
3423 }
3424
3425 public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options)
3426 {
3427 CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments");
3428 m_host.AddScriptLPS(1);
3429
3430 UUID targetUUID;
3431 ScenePresence target;
3432
3433 if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
3434 {
3435 List<int> aps = new List<int>();
3436 foreach (object point in attachmentPoints.Data)
3437 {
3438 int ipoint;
3439 if (int.TryParse(point.ToString(), out ipoint))
3440 {
3441 aps.Add(ipoint);
3442 }
3443 }
3444
3445 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
3446
3447 bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL);
3448 bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0;
3449
3450 if (msgAll && invertPoints)
3451 {
3452 return;
3453 }
3454 else if (msgAll || invertPoints)
3455 {
3456 attachments = target.GetAttachments();
3457 }
3458 else
3459 {
3460 foreach (int point in aps)
3461 {
3462 if (point > 0)
3463 {
3464 attachments.AddRange(target.GetAttachments((uint)point));
3465 }
3466 }
3467 }
3468
3469 // if we have no attachments at this point, exit now
3470 if (attachments.Count == 0)
3471 {
3472 return;
3473 }
3474
3475 List<SceneObjectGroup> ignoreThese = new List<SceneObjectGroup>();
3476
3477 if (invertPoints)
3478 {
3479 foreach (SceneObjectGroup attachment in attachments)
3480 {
3481 if (aps.Contains((int)attachment.AttachmentPoint))
3482 {
3483 ignoreThese.Add(attachment);
3484 }
3485 }
3486 }
3487
3488 foreach (SceneObjectGroup attachment in ignoreThese)
3489 {
3490 attachments.Remove(attachment);
3491 }
3492 ignoreThese.Clear();
3493
3494 // if inverting removed all attachments to check, exit now
3495 if (attachments.Count < 1)
3496 {
3497 return;
3498 }
3499
3500 if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0)
3501 {
3502 foreach (SceneObjectGroup attachment in attachments)
3503 {
3504 if (attachment.RootPart.CreatorID != m_host.CreatorID)
3505 {
3506 ignoreThese.Add(attachment);
3507 }
3508 }
3509
3510 foreach (SceneObjectGroup attachment in ignoreThese)
3511 {
3512 attachments.Remove(attachment);
3513 }
3514 ignoreThese.Clear();
3515
3516 // if filtering by same object creator removed all
3517 // attachments to check, exit now
3518 if (attachments.Count == 0)
3519 {
3520 return;
3521 }
3522 }
3523
3524 if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0)
3525 {
3526 foreach (SceneObjectGroup attachment in attachments)
3527 {
3528 if (attachment.RootPart.CreatorID != m_item.CreatorID)
3529 {
3530 ignoreThese.Add(attachment);
3531 }
3532 }
3533
3534 foreach (SceneObjectGroup attachment in ignoreThese)
3535 {
3536 attachments.Remove(attachment);
3537 }
3538 ignoreThese.Clear();
3539
3540 // if filtering by object creator must match originating
3541 // script creator removed all attachments to check,
3542 // exit now
3543 if (attachments.Count == 0)
3544 {
3545 return;
3546 }
3547 }
3548
3549 foreach (SceneObjectGroup attachment in attachments)
3550 {
3551 MessageObject(attachment.RootPart.UUID, message);
3552 }
3553 }
3554 }
3555
3556 #endregion
3557
3346 /// <summary> 3558 /// <summary>
3347 /// Checks if thing is a UUID. 3559 /// Checks if thing is a UUID.
3348 /// </summary> 3560 /// </summary>
@@ -3392,5 +3604,166 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3392 3604
3393 return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); 3605 return new LSL_Key(m_host.ParentGroup.FromPartID.ToString());
3394 } 3606 }
3607
3608 /// <summary>
3609 /// Sets the response type for an HTTP request/response
3610 /// </summary>
3611 /// <returns></returns>
3612 public void osSetContentType(LSL_Key id, string type)
3613 {
3614 CheckThreatLevel(ThreatLevel.High, "osSetContentType");
3615
3616 if (m_UrlModule != null)
3617 m_UrlModule.HttpContentType(new UUID(id),type);
3618 }
3619
3620 /// Shout an error if the object owner did not grant the script the specified permissions.
3621 /// </summary>
3622 /// <param name="perms"></param>
3623 /// <returns>boolean indicating whether an error was shouted.</returns>
3624 protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix)
3625 {
3626 m_host.AddScriptLPS(1);
3627 bool fail = false;
3628 if (m_item.PermsGranter != m_host.OwnerID)
3629 {
3630 fail = true;
3631 OSSLShoutError(string.Format("{0}. Permissions not granted to owner.", errorPrefix));
3632 }
3633 else if ((m_item.PermsMask & perms) == 0)
3634 {
3635 fail = true;
3636 OSSLShoutError(string.Format("{0}. Permissions not granted.", errorPrefix));
3637 }
3638
3639 return fail;
3640 }
3641
3642 protected void DropAttachment(bool checkPerms)
3643 {
3644 if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment"))
3645 {
3646 return;
3647 }
3648
3649 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3650 ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID);
3651
3652 if (attachmentsModule != null && sp != null)
3653 {
3654 attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId);
3655 }
3656 }
3657
3658 protected void DropAttachmentAt(bool checkPerms, LSL_Vector pos, LSL_Rotation rot)
3659 {
3660 if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment"))
3661 {
3662 return;
3663 }
3664
3665 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3666 ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID);
3667
3668 if (attachmentsModule != null && sp != null)
3669 {
3670 attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, pos, rot);
3671 }
3672 }
3673
3674 public void osDropAttachment()
3675 {
3676 CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment");
3677 m_host.AddScriptLPS(1);
3678
3679 DropAttachment(true);
3680 }
3681
3682 public void osForceDropAttachment()
3683 {
3684 CheckThreatLevel(ThreatLevel.High, "osForceDropAttachment");
3685 m_host.AddScriptLPS(1);
3686
3687 DropAttachment(false);
3688 }
3689
3690 public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot)
3691 {
3692 CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt");
3693 m_host.AddScriptLPS(1);
3694
3695 DropAttachmentAt(true, pos, rot);
3696 }
3697
3698 public void osForceDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot)
3699 {
3700 CheckThreatLevel(ThreatLevel.High, "osForceDropAttachmentAt");
3701 m_host.AddScriptLPS(1);
3702
3703 DropAttachmentAt(false, pos, rot);
3704 }
3705
3706 public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield)
3707 {
3708 CheckThreatLevel(ThreatLevel.Low, "osListenRegex");
3709 m_host.AddScriptLPS(1);
3710 UUID keyID;
3711 UUID.TryParse(ID, out keyID);
3712
3713 // if we want the name to be used as a regular expression, ensure it is valid first.
3714 if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_NAME) == ScriptBaseClass.OS_LISTEN_REGEX_NAME)
3715 {
3716 try
3717 {
3718 Regex.IsMatch("", name);
3719 }
3720 catch (Exception)
3721 {
3722 OSSLShoutError("Name regex is invalid.");
3723 return -1;
3724 }
3725 }
3726
3727 // if we want the msg to be used as a regular expression, ensure it is valid first.
3728 if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) == ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE)
3729 {
3730 try
3731 {
3732 Regex.IsMatch("", msg);
3733 }
3734 catch (Exception)
3735 {
3736 OSSLShoutError("Message regex is invalid.");
3737 return -1;
3738 }
3739 }
3740
3741 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
3742 return (wComm == null) ? -1 : wComm.Listen(
3743 m_host.LocalId,
3744 m_item.ItemID,
3745 m_host.UUID,
3746 channelID,
3747 name,
3748 keyID,
3749 msg,
3750 regexBitfield
3751 );
3752 }
3753
3754 public LSL_Integer osRegexIsMatch(string input, string pattern)
3755 {
3756 CheckThreatLevel(ThreatLevel.Low, "osRegexIsMatch");
3757 m_host.AddScriptLPS(1);
3758 try
3759 {
3760 return Regex.IsMatch(input, pattern) ? 1 : 0;
3761 }
3762 catch (Exception)
3763 {
3764 OSSLShoutError("Possible invalid regular expression detected.");
3765 return 0;
3766 }
3767 }
3395 } 3768 }
3396} 3769}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 678f9d5..4dd795d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -352,7 +352,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
352 q = avatar.Rotation; 352 q = avatar.Rotation;
353 } 353 }
354 354
355 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 355 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q);
356 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); 356 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
357 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); 357 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
358 358
@@ -429,9 +429,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
429 try 429 try
430 { 430 {
431 Vector3 diff = toRegionPos - fromRegionPos; 431 Vector3 diff = toRegionPos - fromRegionPos;
432 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); 432 double dot = LSL_Types.Vector3.Dot(forward_dir, diff);
433 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); 433 double mag_obj = LSL_Types.Vector3.Mag(diff);
434 double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
435 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); 434 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
436 } 435 }
437 catch 436 catch
@@ -483,7 +482,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
483 q = avatar.Rotation; 482 q = avatar.Rotation;
484 } 483 }
485 484
486 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 485 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q);
487 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); 486 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
488 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); 487 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
489 bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); 488 bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0);
@@ -564,8 +563,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
564 double ang_obj = 0; 563 double ang_obj = 0;
565 try 564 try
566 { 565 {
567 Vector3 diff = toRegionPos - fromRegionPos; 566 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(
568 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); 567 toRegionPos - fromRegionPos);
569 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); 568 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir);
570 double mag_obj = LSL_Types.Vector3.Mag(obj_dir); 569 double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
571 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); 570 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..d173db0
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.ScriptEngine.Shared.Api")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("369ed06e-a3ca-40f0-98e3-3cd3ec1443c3")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index af35258..9bf6f9b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -336,6 +336,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
336 void llSetBuoyancy(double buoyancy); 336 void llSetBuoyancy(double buoyancy);
337 void llSetCameraAtOffset(LSL_Vector offset); 337 void llSetCameraAtOffset(LSL_Vector offset);
338 void llSetCameraEyeOffset(LSL_Vector offset); 338 void llSetCameraEyeOffset(LSL_Vector offset);
339 void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at);
339 void llSetCameraParams(LSL_List rules); 340 void llSetCameraParams(LSL_List rules);
340 void llSetClickAction(int action); 341 void llSetClickAction(int action);
341 void llSetColor(LSL_Vector color, int face); 342 void llSetColor(LSL_Vector color, int face);
@@ -429,8 +430,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
429 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link); 430 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link);
430 void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density); 431 void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density);
431 432
432 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 433 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc);
433 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
434 void llSetKeyframedMotion(LSL_List frames, LSL_List options); 434 void llSetKeyframedMotion(LSL_List frames, LSL_List options);
435 LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
435 } 436 }
436} 437}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 8c34ed3..c447d1f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -40,16 +40,75 @@ using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
40 40
41namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces 41namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
42{ 42{
43 /// <summary>
44 /// To permit region owners to enable the extended scripting functionality
45 /// of OSSL, without allowing malicious scripts to access potentially
46 /// troublesome functions, each OSSL function is assigned a threat level,
47 /// and access to the functions is granted or denied based on a default
48 /// threshold set in OpenSim.ini (which can be overridden for individual
49 /// functions on a case-by-case basis)
50 /// </summary>
43 public enum ThreatLevel 51 public enum ThreatLevel
44 { 52 {
53 // Not documented, presumably means permanently disabled ?
45 NoAccess = -1, 54 NoAccess = -1,
55
56 /// <summary>
57 /// Function is no threat at all. It doesn't constitute a threat to
58 /// either users or the system and has no known side effects.
59 /// </summary>
46 None = 0, 60 None = 0,
61
62 /// <summary>
63 /// Abuse of this command can cause a nuisance to the region operator,
64 /// such as log message spew.
65 /// </summary>
47 Nuisance = 1, 66 Nuisance = 1,
67
68 /// <summary>
69 /// Extreme levels of abuse of this function can cause impaired
70 /// functioning of the region, or very gullible users can be tricked
71 /// into experiencing harmless effects.
72 /// </summary>
48 VeryLow = 2, 73 VeryLow = 2,
74
75 /// <summary>
76 /// Intentional abuse can cause crashes or malfunction under certain
77 /// circumstances, which can be easily rectified; or certain users can
78 /// be tricked into certain situations in an avoidable manner.
79 /// </summary>
49 Low = 3, 80 Low = 3,
81
82 /// <summary>
83 /// Intentional abuse can cause denial of service and crashes with
84 /// potential of data or state loss; or trusting users can be tricked
85 /// into embarrassing or uncomfortable situations.
86 /// </summary>
50 Moderate = 4, 87 Moderate = 4,
88
89 /// <summary>
90 /// Casual abuse can cause impaired functionality or temporary denial
91 /// of service conditions. Intentional abuse can easily cause crashes
92 /// with potential data loss, or can be used to trick experienced and
93 /// cautious users into unwanted situations, or changes global data
94 /// permanently and without undo ability.
95 /// </summary>
51 High = 5, 96 High = 5,
97
98 /// <summary>
99 /// Even normal use may, depending on the number of instances, or
100 /// frequency of use, result in severe service impairment or crash
101 /// with loss of data, or can be used to cause unwanted or harmful
102 /// effects on users without giving the user a means to avoid it.
103 /// </summary>
52 VeryHigh = 6, 104 VeryHigh = 6,
105
106 /// <summary>
107 /// Even casual use is a danger to region stability, or function allows
108 /// console or OS command execution, or function allows taking money
109 /// without consent, or allows deletion or modification of user data,
110 /// or allows the compromise of sensitive data by design.
111 /// </summary>
53 Severe = 7 112 Severe = 7
54 }; 113 };
55 114
@@ -98,7 +157,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
98 void osAvatarPlayAnimation(string avatar, string animation); 157 void osAvatarPlayAnimation(string avatar, string animation);
99 void osAvatarStopAnimation(string avatar, string animation); 158 void osAvatarStopAnimation(string avatar, string animation);
100 159
101 // Attachment commands 160 #region Attachment commands
102 161
103 /// <summary> 162 /// <summary>
104 /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH 163 /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
@@ -133,6 +192,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
133 /// <remarks>Nothing happens if the object is not attached.</remarks> 192 /// <remarks>Nothing happens if the object is not attached.</remarks>
134 void osForceDetachFromAvatar(); 193 void osForceDetachFromAvatar();
135 194
195 /// <summary>
196 /// Returns a strided list of the specified attachment points and the number of attachments on those points.
197 /// </summary>
198 /// <param name="avatar">avatar UUID</param>
199 /// <param name="attachmentPoints">list of ATTACH_* constants</param>
200 /// <returns></returns>
201 LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints);
202
203 /// <summary>
204 /// Sends a specified message to the specified avatar's attachments on
205 /// the specified attachment points.
206 /// </summary>
207 /// <remarks>
208 /// Behaves as osMessageObject(), without the sending script needing to know the attachment keys in advance.
209 /// </remarks>
210 /// <param name="avatar">avatar UUID</param>
211 /// <param name="message">message string</param>
212 /// <param name="attachmentPoints">list of ATTACH_* constants, or -1 for all attachments. If -1 is specified and OS_ATTACH_MSG_INVERT_POINTS is present in flags, no action is taken.</param>
213 /// <param name="flags">flags further constraining the attachments to deliver the message to.</param>
214 void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags);
215
216 #endregion
217
136 //texture draw functions 218 //texture draw functions
137 string osMovePen(string drawList, int x, int y); 219 string osMovePen(string drawList, int x, int y);
138 string osDrawLine(string drawList, int startX, int startY, int endX, int endY); 220 string osDrawLine(string drawList, int startX, int startY, int endX, int endY);
@@ -258,6 +340,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
258 int osGetSimulatorMemory(); 340 int osGetSimulatorMemory();
259 void osKickAvatar(string FirstName,string SurName,string alert); 341 void osKickAvatar(string FirstName,string SurName,string alert);
260 void osSetSpeed(string UUID, LSL_Float SpeedModifier); 342 void osSetSpeed(string UUID, LSL_Float SpeedModifier);
343 LSL_Float osGetHealth(string avatar);
261 void osCauseHealing(string avatar, double healing); 344 void osCauseHealing(string avatar, double healing);
262 void osCauseDamage(string avatar, double damage); 345 void osCauseDamage(string avatar, double damage);
263 LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); 346 LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules);
@@ -305,5 +388,59 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
305 /// </summary> 388 /// </summary>
306 /// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns> 389 /// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns>
307 LSL_Key osGetRezzingObject(); 390 LSL_Key osGetRezzingObject();
391
392 /// <summary>
393 /// Sets the response type for an HTTP request/response
394 /// </summary>
395 /// <returns></returns>
396 void osSetContentType(LSL_Key id, string type);
397
398 /// <summary>
399 /// Attempts to drop an attachment to the ground
400 /// </summary>
401 void osDropAttachment();
402
403 /// <summary>
404 /// Attempts to drop an attachment to the ground while bypassing the script permissions
405 /// </summary>
406 void osForceDropAttachment();
407
408 /// <summary>
409 /// Attempts to drop an attachment at the specified coordinates.
410 /// </summary>
411 /// <param name="pos"></param>
412 /// <param name="rot"></param>
413 void osDropAttachmentAt(vector pos, rotation rot);
414
415 /// <summary>
416 /// Attempts to drop an attachment at the specified coordinates while bypassing the script permissions
417 /// </summary>
418 /// <param name="pos"></param>
419 /// <param name="rot"></param>
420 void osForceDropAttachmentAt(vector pos, rotation rot);
421
422 /// <summary>
423 /// Identical to llListen except for a bitfield which indicates which
424 /// string parameters should be parsed as regex patterns.
425 /// </summary>
426 /// <param name="channelID"></param>
427 /// <param name="name"></param>
428 /// <param name="ID"></param>
429 /// <param name="msg"></param>
430 /// <param name="regexBitfield">
431 /// OS_LISTEN_REGEX_NAME
432 /// OS_LISTEN_REGEX_MESSAGE
433 /// </param>
434 /// <returns></returns>
435 LSL_Integer osListenRegex(int channelID, string name, string ID,
436 string msg, int regexBitfield);
437
438 /// <summary>
439 /// Wraps to bool Regex.IsMatch(string input, string pattern)
440 /// </summary>
441 /// <param name="input">string to test for match</param>
442 /// <param name="regex">string to use as pattern</param>
443 /// <returns>boolean</returns>
444 LSL_Integer osRegexIsMatch(string input, string pattern);
308 } 445 }
309} 446}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index f989cc6..0dd5a57 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -237,6 +237,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
237 public const int ATTACH_HUD_BOTTOM = 37; 237 public const int ATTACH_HUD_BOTTOM = 37;
238 public const int ATTACH_HUD_BOTTOM_RIGHT = 38; 238 public const int ATTACH_HUD_BOTTOM_RIGHT = 38;
239 239
240 #region osMessageAttachments constants
241
242 /// <summary>
243 /// Instructs osMessageAttachements to send the message to attachments
244 /// on every point.
245 /// </summary>
246 /// <remarks>
247 /// One might expect this to be named OS_ATTACH_ALL, but then one might
248 /// also expect functions designed to attach or detach or get
249 /// attachments to work with it too. Attaching a no-copy item to
250 /// many attachments could be dangerous.
251 /// when combined with OS_ATTACH_MSG_INVERT_POINTS, will prevent the
252 /// message from being sent.
253 /// if combined with OS_ATTACH_MSG_OBJECT_CREATOR or
254 /// OS_ATTACH_MSG_SCRIPT_CREATOR, could result in no message being
255 /// sent- this is expected behaviour.
256 /// </remarks>
257 public const int OS_ATTACH_MSG_ALL = -65535;
258
259 /// <summary>
260 /// Instructs osMessageAttachements to invert how the attachment points
261 /// list should be treated (e.g. go from inclusive operation to
262 /// exclusive operation).
263 /// </summary>
264 /// <remarks>
265 /// This might be used if you want to deliver a message to one set of
266 /// attachments and a different message to everything else. With
267 /// this flag, you only need to build one explicit list for both calls.
268 /// </remarks>
269 public const int OS_ATTACH_MSG_INVERT_POINTS = 1;
270
271 /// <summary>
272 /// Instructs osMessageAttachments to only send the message to
273 /// attachments with a CreatorID that matches the host object CreatorID
274 /// </summary>
275 /// <remarks>
276 /// This would be used if distributed in an object vendor/updater server.
277 /// </remarks>
278 public const int OS_ATTACH_MSG_OBJECT_CREATOR = 2;
279
280 /// <summary>
281 /// Instructs osMessageAttachments to only send the message to
282 /// attachments with a CreatorID that matches the sending script CreatorID
283 /// </summary>
284 /// <remarks>
285 /// This might be used if the script is distributed independently of a
286 /// containing object.
287 /// </remarks>
288 public const int OS_ATTACH_MSG_SCRIPT_CREATOR = 4;
289
290 #endregion
291
240 public const int LAND_LEVEL = 0; 292 public const int LAND_LEVEL = 0;
241 public const int LAND_RAISE = 1; 293 public const int LAND_RAISE = 1;
242 public const int LAND_LOWER = 2; 294 public const int LAND_LOWER = 2;
@@ -329,6 +381,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
329 public const int PRIM_OMEGA = 32; 381 public const int PRIM_OMEGA = 32;
330 public const int PRIM_POS_LOCAL = 33; 382 public const int PRIM_POS_LOCAL = 33;
331 public const int PRIM_LINK_TARGET = 34; 383 public const int PRIM_LINK_TARGET = 34;
384 public const int PRIM_SLICE = 35;
332 public const int PRIM_TEXGEN_DEFAULT = 0; 385 public const int PRIM_TEXGEN_DEFAULT = 0;
333 public const int PRIM_TEXGEN_PLANAR = 1; 386 public const int PRIM_TEXGEN_PLANAR = 1;
334 387
@@ -560,6 +613,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
560 public const int CLICK_ACTION_OPEN = 4; 613 public const int CLICK_ACTION_OPEN = 4;
561 public const int CLICK_ACTION_PLAY = 5; 614 public const int CLICK_ACTION_PLAY = 5;
562 public const int CLICK_ACTION_OPEN_MEDIA = 6; 615 public const int CLICK_ACTION_OPEN_MEDIA = 6;
616 public const int CLICK_ACTION_ZOOM = 7;
563 617
564 // constants for the llDetectedTouch* functions 618 // constants for the llDetectedTouch* functions
565 public const int TOUCH_INVALID_FACE = -1; 619 public const int TOUCH_INVALID_FACE = -1;
@@ -687,5 +741,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
687 public const int KFM_CMD_PLAY = 0; 741 public const int KFM_CMD_PLAY = 0;
688 public const int KFM_CMD_STOP = 1; 742 public const int KFM_CMD_STOP = 1;
689 public const int KFM_CMD_PAUSE = 2; 743 public const int KFM_CMD_PAUSE = 2;
744
745 /// <summary>
746 /// process name parameter as regex
747 /// </summary>
748 public const int OS_LISTEN_REGEX_NAME = 0x1;
749
750 /// <summary>
751 /// process message parameter as regex
752 /// </summary>
753 public const int OS_LISTEN_REGEX_MESSAGE = 0x2;
690 } 754 }
691} 755}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index 89b6eff..8ecc4f8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -1515,6 +1515,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1515 m_LSL_Functions.llSetCameraEyeOffset(offset); 1515 m_LSL_Functions.llSetCameraEyeOffset(offset);
1516 } 1516 }
1517 1517
1518 public void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at)
1519 {
1520 m_LSL_Functions.llSetLinkCamera(link, eye, at);
1521 }
1522
1518 public void llSetCameraParams(LSL_List rules) 1523 public void llSetCameraParams(LSL_List rules)
1519 { 1524 {
1520 m_LSL_Functions.llSetCameraParams(rules); 1525 m_LSL_Functions.llSetCameraParams(rules);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 94405d2..afa9ae0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -289,7 +289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
289 m_OSSL_Functions.osAvatarStopAnimation(avatar, animation); 289 m_OSSL_Functions.osAvatarStopAnimation(avatar, animation);
290 } 290 }
291 291
292 // Avatar functions 292 #region Attachment commands
293 293
294 public void osForceAttachToAvatar(int attachmentPoint) 294 public void osForceAttachToAvatar(int attachmentPoint)
295 { 295 {
@@ -311,6 +311,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
311 m_OSSL_Functions.osForceDetachFromAvatar(); 311 m_OSSL_Functions.osForceDetachFromAvatar();
312 } 312 }
313 313
314 public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
315 {
316 return m_OSSL_Functions.osGetNumberOfAttachments(avatar, attachmentPoints);
317 }
318
319 public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags)
320 {
321 m_OSSL_Functions.osMessageAttachments(avatar, message, attachmentPoints, flags);
322 }
323
324 #endregion
325
314 // Texture Draw functions 326 // Texture Draw functions
315 327
316 public string osMovePen(string drawList, int x, int y) 328 public string osMovePen(string drawList, int x, int y)
@@ -865,7 +877,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
865 { 877 {
866 m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier); 878 m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier);
867 } 879 }
868 880
881 public LSL_Float osGetHealth(string avatar)
882 {
883 return m_OSSL_Functions.osGetHealth(avatar);
884 }
885
869 public void osCauseDamage(string avatar, double damage) 886 public void osCauseDamage(string avatar, double damage)
870 { 887 {
871 m_OSSL_Functions.osCauseDamage(avatar, damage); 888 m_OSSL_Functions.osCauseDamage(avatar, damage);
@@ -950,5 +967,40 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
950 { 967 {
951 return m_OSSL_Functions.osGetRezzingObject(); 968 return m_OSSL_Functions.osGetRezzingObject();
952 } 969 }
970
971 public void osSetContentType(LSL_Key id, string type)
972 {
973 m_OSSL_Functions.osSetContentType(id,type);
974 }
975
976 public void osDropAttachment()
977 {
978 m_OSSL_Functions.osDropAttachment();
979 }
980
981 public void osForceDropAttachment()
982 {
983 m_OSSL_Functions.osForceDropAttachment();
984 }
985
986 public void osDropAttachmentAt(vector pos, rotation rot)
987 {
988 m_OSSL_Functions.osDropAttachmentAt(pos, rot);
989 }
990
991 public void osForceDropAttachmentAt(vector pos, rotation rot)
992 {
993 m_OSSL_Functions.osForceDropAttachmentAt(pos, rot);
994 }
995
996 public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield)
997 {
998 return m_OSSL_Functions.osListenRegex(channelID, name, ID, msg, regexBitfield);
999 }
1000
1001 public LSL_Integer osRegexIsMatch(string input, string pattern)
1002 {
1003 return m_OSSL_Functions.osRegexIsMatch(input, pattern);
1004 }
953 } 1005 }
954} 1006}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..573a803
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.ScriptEngine.Shared.Api.Runtime")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("ac60ce7e-7c35-4431-b294-fe6ca26b5b50")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f6d5d41
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/YieldProlog/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.ScriptEngine.Shared.YieldProlog")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("8df98e6b-0425-44d6-8d91-2b3b4c56acdf")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index 17a0d69..03be2ab 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -546,6 +546,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
546 "OpenSim.Region.ScriptEngine.Shared.dll")); 546 "OpenSim.Region.ScriptEngine.Shared.dll"));
547 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, 547 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
548 "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll")); 548 "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll"));
549 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
550 "OpenMetaverseTypes.dll"));
549 551
550 if (lang == enumCompileType.yp) 552 if (lang == enumCompileType.yp)
551 { 553 {
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c65caa8
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.ScriptEngine.Shared.CodeTools")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("fd446fb3-3a21-471b-951c-68b9eb6ef8e5")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 9e5fb24..22804f5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -164,11 +164,11 @@ namespace OpenSim.Region.ScriptEngine.Shared
164 else 164 else
165 { 165 {
166 // Set the values from the touch data provided by the client 166 // Set the values from the touch data provided by the client
167 touchST = new LSL_Types.Vector3(value.STCoord.X, value.STCoord.Y, value.STCoord.Z); 167 touchST = new LSL_Types.Vector3(value.STCoord);
168 touchUV = new LSL_Types.Vector3(value.UVCoord.X, value.UVCoord.Y, value.UVCoord.Z); 168 touchUV = new LSL_Types.Vector3(value.UVCoord);
169 touchNormal = new LSL_Types.Vector3(value.Normal.X, value.Normal.Y, value.Normal.Z); 169 touchNormal = new LSL_Types.Vector3(value.Normal);
170 touchBinormal = new LSL_Types.Vector3(value.Binormal.X, value.Binormal.Y, value.Binormal.Z); 170 touchBinormal = new LSL_Types.Vector3(value.Binormal);
171 touchPos = new LSL_Types.Vector3(value.Position.X, value.Position.Y, value.Position.Z); 171 touchPos = new LSL_Types.Vector3(value.Position);
172 touchFace = value.FaceIndex; 172 touchFace = value.FaceIndex;
173 } 173 }
174 } 174 }
@@ -189,19 +189,13 @@ namespace OpenSim.Region.ScriptEngine.Shared
189 Country = account.UserCountry; 189 Country = account.UserCountry;
190 190
191 Owner = Key; 191 Owner = Key;
192 Position = new LSL_Types.Vector3( 192 Position = new LSL_Types.Vector3(presence.AbsolutePosition);
193 presence.AbsolutePosition.X,
194 presence.AbsolutePosition.Y,
195 presence.AbsolutePosition.Z);
196 Rotation = new LSL_Types.Quaternion( 193 Rotation = new LSL_Types.Quaternion(
197 presence.Rotation.X, 194 presence.Rotation.X,
198 presence.Rotation.Y, 195 presence.Rotation.Y,
199 presence.Rotation.Z, 196 presence.Rotation.Z,
200 presence.Rotation.W); 197 presence.Rotation.W);
201 Velocity = new LSL_Types.Vector3( 198 Velocity = new LSL_Types.Vector3(presence.Velocity);
202 presence.Velocity.X,
203 presence.Velocity.Y,
204 presence.Velocity.Z);
205 199
206 Type = 0x01; // Avatar 200 Type = 0x01; // Avatar
207 if (presence.PresenceType == PresenceType.Npc) 201 if (presence.PresenceType == PresenceType.Npc)
@@ -254,16 +248,12 @@ namespace OpenSim.Region.ScriptEngine.Shared
254 } 248 }
255 } 249 }
256 250
257 Position = new LSL_Types.Vector3(part.AbsolutePosition.X, 251 Position = new LSL_Types.Vector3(part.AbsolutePosition);
258 part.AbsolutePosition.Y,
259 part.AbsolutePosition.Z);
260 252
261 Quaternion wr = part.ParentGroup.GroupRotation; 253 Quaternion wr = part.ParentGroup.GroupRotation;
262 Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W); 254 Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W);
263 255
264 Velocity = new LSL_Types.Vector3(part.Velocity.X, 256 Velocity = new LSL_Types.Vector3(part.Velocity);
265 part.Velocity.Y,
266 part.Velocity.Z);
267 } 257 }
268 } 258 }
269 259
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..470e1a1
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.ScriptEngine.Shared.Instance")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("b776d846-68c1-43a2-9e72-9bd1fe20fd41")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index 8adf4c5..c9c4753 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -31,6 +31,11 @@ using System.Globalization;
31using System.Text.RegularExpressions; 31using System.Text.RegularExpressions;
32using OpenSim.Framework; 32using OpenSim.Framework;
33 33
34using OpenMetaverse;
35using OMV_Vector3 = OpenMetaverse.Vector3;
36using OMV_Vector3d = OpenMetaverse.Vector3d;
37using OMV_Quaternion = OpenMetaverse.Quaternion;
38
34namespace OpenSim.Region.ScriptEngine.Shared 39namespace OpenSim.Region.ScriptEngine.Shared
35{ 40{
36 [Serializable] 41 [Serializable]
@@ -54,6 +59,20 @@ namespace OpenSim.Region.ScriptEngine.Shared
54 z = (float)vector.z; 59 z = (float)vector.z;
55 } 60 }
56 61
62 public Vector3(OMV_Vector3 vector)
63 {
64 x = vector.X;
65 y = vector.Y;
66 z = vector.Z;
67 }
68
69 public Vector3(OMV_Vector3d vector)
70 {
71 x = vector.X;
72 y = vector.Y;
73 z = vector.Z;
74 }
75
57 public Vector3(double X, double Y, double Z) 76 public Vector3(double X, double Y, double Z)
58 { 77 {
59 x = X; 78 x = X;
@@ -109,6 +128,26 @@ namespace OpenSim.Region.ScriptEngine.Shared
109 return new list(new object[] { vec }); 128 return new list(new object[] { vec });
110 } 129 }
111 130
131 public static implicit operator OMV_Vector3(Vector3 vec)
132 {
133 return new OMV_Vector3((float)vec.x, (float)vec.y, (float)vec.z);
134 }
135
136 public static implicit operator Vector3(OMV_Vector3 vec)
137 {
138 return new Vector3(vec);
139 }
140
141 public static implicit operator OMV_Vector3d(Vector3 vec)
142 {
143 return new OMV_Vector3d(vec.x, vec.y, vec.z);
144 }
145
146 public static implicit operator Vector3(OMV_Vector3d vec)
147 {
148 return new Vector3(vec);
149 }
150
112 public static bool operator ==(Vector3 lhs, Vector3 rhs) 151 public static bool operator ==(Vector3 lhs, Vector3 rhs)
113 { 152 {
114 return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); 153 return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z);
@@ -322,6 +361,14 @@ namespace OpenSim.Region.ScriptEngine.Shared
322 s = 1; 361 s = 1;
323 } 362 }
324 363
364 public Quaternion(OMV_Quaternion rot)
365 {
366 x = rot.X;
367 y = rot.Y;
368 z = rot.Z;
369 s = rot.W;
370 }
371
325 #endregion 372 #endregion
326 373
327 #region Overriders 374 #region Overriders
@@ -368,6 +415,21 @@ namespace OpenSim.Region.ScriptEngine.Shared
368 return new list(new object[] { r }); 415 return new list(new object[] { r });
369 } 416 }
370 417
418 public static implicit operator OMV_Quaternion(Quaternion rot)
419 {
420 // LSL quaternions can normalize to 0, normal Quaternions can't.
421 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
422 rot.z = 1; // ZERO_ROTATION = 0,0,0,1
423 OMV_Quaternion omvrot = new OMV_Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
424 omvrot.Normalize();
425 return omvrot;
426 }
427
428 public static implicit operator Quaternion(OMV_Quaternion rot)
429 {
430 return new Quaternion(rot);
431 }
432
371 public static bool operator ==(Quaternion lhs, Quaternion rhs) 433 public static bool operator ==(Quaternion lhs, Quaternion rhs)
372 { 434 {
373 // Return true if the fields match: 435 // Return true if the fields match:
@@ -562,12 +624,23 @@ namespace OpenSim.Region.ScriptEngine.Shared
562 else if (m_data[itemIndex] is LSL_Types.LSLString) 624 else if (m_data[itemIndex] is LSL_Types.LSLString)
563 return new LSLInteger(m_data[itemIndex].ToString()); 625 return new LSLInteger(m_data[itemIndex].ToString());
564 else 626 else
565 throw new InvalidCastException(); 627 throw new InvalidCastException(string.Format(
628 "{0} expected but {1} given",
629 typeof(LSL_Types.LSLInteger).Name,
630 m_data[itemIndex] != null ?
631 m_data[itemIndex].GetType().Name : "null"));
566 } 632 }
567 633
568 public LSL_Types.Vector3 GetVector3Item(int itemIndex) 634 public LSL_Types.Vector3 GetVector3Item(int itemIndex)
569 { 635 {
570 return (LSL_Types.Vector3)m_data[itemIndex]; 636 if(m_data[itemIndex] is LSL_Types.Vector3)
637 return (LSL_Types.Vector3)m_data[itemIndex];
638 else
639 throw new InvalidCastException(string.Format(
640 "{0} expected but {1} given",
641 typeof(LSL_Types.Vector3).Name,
642 m_data[itemIndex] != null ?
643 m_data[itemIndex].GetType().Name : "null"));
571 } 644 }
572 645
573 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex) 646 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e6e8777
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.ScriptEngine.Shared")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("5fe331de-bc53-4ca7-b080-2a5a5ce2d380")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs b/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs
new file mode 100644
index 0000000..f55ba7e
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs
@@ -0,0 +1,44 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Runtime.Serialization;
30
31namespace OpenSim.Region.ScriptEngine.Shared
32{
33 [Serializable]
34 public class ScriptException : Exception
35 {
36 public ScriptException() : base() {}
37
38 public ScriptException(string message) : base(message) {}
39
40 public ScriptException(string message, Exception innerException) : base(message, innerException) {}
41
42 public ScriptException(SerializationInfo info, StreamingContext context) :base(info, context) {}
43 }
44} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
new file mode 100644
index 0000000..dd23be8
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
@@ -0,0 +1,134 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using NUnit.Framework;
31using OpenSim.Framework;
32using OpenSim.Tests.Common;
33using OpenSim.Region.ScriptEngine.Shared;
34using OpenSim.Region.Framework.Scenes;
35using Nini.Config;
36using OpenSim.Region.ScriptEngine.Shared.Api;
37using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
38using OpenMetaverse;
39using OpenSim.Tests.Common.Mock;
40
41using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
42using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
43using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
44using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
45
46namespace OpenSim.Region.ScriptEngine.Shared.Tests
47{
48 [TestFixture]
49 public class LSL_ApiListTests
50 {
51 private LSL_Api m_lslApi;
52
53 [SetUp]
54 public void SetUp()
55 {
56 IConfigSource initConfigSource = new IniConfigSource();
57 IConfig config = initConfigSource.AddConfig("XEngine");
58 config.Set("Enabled", "true");
59
60 Scene scene = new SceneHelpers().SetupScene();
61 SceneObjectPart part = SceneHelpers.AddSceneObject(scene).RootPart;
62
63 XEngine.XEngine engine = new XEngine.XEngine();
64 engine.Initialise(initConfigSource);
65 engine.AddRegion(scene);
66
67 m_lslApi = new LSL_Api();
68 m_lslApi.Initialize(engine, part, null);
69 }
70
71 [Test]
72 public void TestllListFindList()
73 {
74 TestHelpers.InMethod();
75
76 LSL_List src = new LSL_List(new LSL_Integer(1), new LSL_Integer(2), new LSL_Integer(3));
77
78 {
79 // Test for a single item that should be found
80 int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4)));
81 Assert.That(result, Is.EqualTo(-1));
82 }
83
84 {
85 // Test for a single item that should be found
86 int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2)));
87 Assert.That(result, Is.EqualTo(1));
88 }
89
90 {
91 // Test for a constant that should be found
92 int result = m_lslApi.llListFindList(src, new LSL_List(ScriptBaseClass.AGENT));
93 Assert.That(result, Is.EqualTo(0));
94 }
95
96 {
97 // Test for a list that should be found
98 int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3)));
99 Assert.That(result, Is.EqualTo(1));
100 }
101
102 {
103 // Test for a single item not in the list
104 int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4)));
105 Assert.That(result, Is.EqualTo(-1));
106 }
107
108 {
109 // Test for something that should not be cast
110 int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_String("4")));
111 Assert.That(result, Is.EqualTo(-1));
112 }
113
114 {
115 // Test for a list not in the list
116 int result
117 = m_lslApi.llListFindList(
118 src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3), new LSL_Integer(4)));
119 Assert.That(result, Is.EqualTo(-1));
120 }
121
122 {
123 LSL_List srcWithConstants
124 = new LSL_List(new LSL_Integer(3), ScriptBaseClass.AGENT, ScriptBaseClass.OS_NPC_LAND_AT_TARGET);
125
126 // Test for constants that appears in the source list that should be found
127 int result
128 = m_lslApi.llListFindList(srcWithConstants, new LSL_List(new LSL_Integer(1), new LSL_Integer(2)));
129
130 Assert.That(result, Is.EqualTo(1));
131 }
132 }
133 }
134 } \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
index c8718d9..c401794 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
@@ -75,76 +75,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
75 m_engine.AddRegion(m_scene); 75 m_engine.AddRegion(m_scene);
76 } 76 }
77 77
78 /// <summary>
79 /// Test creation of an NPC where the appearance data comes from a notecard
80 /// </summary>
81 [Test]
82 public void TestOsNpcCreateUsingAppearanceFromNotecard()
83 {
84 TestHelpers.InMethod();
85// log4net.Config.XmlConfigurator.Configure();
86
87 // Store an avatar with a different height from default in a notecard.
88 UUID userId = TestHelpers.ParseTail(0x1);
89 float newHeight = 1.9f;
90
91 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
92 sp.Appearance.AvatarHeight = newHeight;
93 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
94 SceneObjectPart part = so.RootPart;
95 m_scene.AddSceneObject(so);
96
97 OSSL_Api osslApi = new OSSL_Api();
98 osslApi.Initialize(m_engine, part, null);
99
100 string notecardName = "appearanceNc";
101 osslApi.osOwnerSaveAppearance(notecardName);
102
103 // Try creating a bot using the appearance in the notecard.
104 string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName);
105 Assert.That(npcRaw, Is.Not.Null);
106
107 UUID npcId = new UUID(npcRaw);
108 ScenePresence npc = m_scene.GetScenePresence(npcId);
109 Assert.That(npc, Is.Not.Null);
110 Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight));
111 }
112
113 /// <summary>
114 /// Test creation of an NPC where the appearance data comes from an avatar already in the region.
115 /// </summary>
116 [Test]
117 public void TestOsNpcCreateUsingAppearanceFromAvatar()
118 {
119 TestHelpers.InMethod();
120// TestHelpers.EnableLogging();
121
122 // Store an avatar with a different height from default in a notecard.
123 UUID userId = TestHelpers.ParseTail(0x1);
124 float newHeight = 1.9f;
125
126 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
127 sp.Appearance.AvatarHeight = newHeight;
128 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
129 SceneObjectPart part = so.RootPart;
130 m_scene.AddSceneObject(so);
131
132 OSSL_Api osslApi = new OSSL_Api();
133 osslApi.Initialize(m_engine, part, null);
134
135 string notecardName = "appearanceNc";
136 osslApi.osOwnerSaveAppearance(notecardName);
137
138 // Try creating a bot using the existing avatar's appearance
139 string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString());
140 Assert.That(npcRaw, Is.Not.Null);
141
142 UUID npcId = new UUID(npcRaw);
143 ScenePresence npc = m_scene.GetScenePresence(npcId);
144 Assert.That(npc, Is.Not.Null);
145 Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight));
146 }
147
148 [Test] 78 [Test]
149 public void TestOsOwnerSaveAppearance() 79 public void TestOsOwnerSaveAppearance()
150 { 80 {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
index 25679a6..b49bcc2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
@@ -36,6 +36,7 @@ using OpenMetaverse;
36using OpenMetaverse.Assets; 36using OpenMetaverse.Assets;
37using OpenMetaverse.StructuredData; 37using OpenMetaverse.StructuredData;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Region.CoreModules.Avatar.Attachments;
39using OpenSim.Region.CoreModules.Avatar.AvatarFactory; 40using OpenSim.Region.CoreModules.Avatar.AvatarFactory;
40using OpenSim.Region.OptionalModules.World.NPC; 41using OpenSim.Region.OptionalModules.World.NPC;
41using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
@@ -71,7 +72,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
71 config.Set("Enabled", "true"); 72 config.Set("Enabled", "true");
72 73
73 m_scene = new SceneHelpers().SetupScene(); 74 m_scene = new SceneHelpers().SetupScene();
74 SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule()); 75 SceneHelpers.SetupSceneModules(
76 m_scene, initConfigSource, new AvatarFactoryModule(), new AttachmentsModule(), new NPCModule());
75 77
76 m_engine = new XEngine.XEngine(); 78 m_engine = new XEngine.XEngine();
77 m_engine.Initialise(initConfigSource); 79 m_engine.Initialise(initConfigSource);
@@ -79,13 +81,191 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
79 } 81 }
80 82
81 /// <summary> 83 /// <summary>
84 /// Test creation of an NPC where the appearance data comes from a notecard
85 /// </summary>
86 [Test]
87 public void TestOsNpcCreateUsingAppearanceFromNotecard()
88 {
89 TestHelpers.InMethod();
90
91 // Store an avatar with a different height from default in a notecard.
92 UUID userId = TestHelpers.ParseTail(0x1);
93 float newHeight = 1.9f;
94
95 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
96 sp.Appearance.AvatarHeight = newHeight;
97 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
98 SceneObjectPart part = so.RootPart;
99 m_scene.AddSceneObject(so);
100
101 OSSL_Api osslApi = new OSSL_Api();
102 osslApi.Initialize(m_engine, part, null);
103
104 string notecardName = "appearanceNc";
105 osslApi.osOwnerSaveAppearance(notecardName);
106
107 // Try creating a bot using the appearance in the notecard.
108 string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName);
109 Assert.That(npcRaw, Is.Not.Null);
110
111 UUID npcId = new UUID(npcRaw);
112 ScenePresence npc = m_scene.GetScenePresence(npcId);
113 Assert.That(npc, Is.Not.Null);
114 Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight));
115 }
116
117 [Test]
118 public void TestOsNpcCreateNotExistingNotecard()
119 {
120 TestHelpers.InMethod();
121
122 UUID userId = TestHelpers.ParseTail(0x1);
123
124 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
125 m_scene.AddSceneObject(so);
126
127 OSSL_Api osslApi = new OSSL_Api();
128 osslApi.Initialize(m_engine, so.RootPart, null);
129
130 string npcRaw;
131 bool gotExpectedException = false;
132 try
133 {
134 npcRaw
135 = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name");
136 }
137 catch (ScriptException)
138 {
139 gotExpectedException = true;
140 }
141
142 Assert.That(gotExpectedException, Is.True);
143 }
144
145 /// <summary>
146 /// Test creation of an NPC where the appearance data comes from an avatar already in the region.
147 /// </summary>
148 [Test]
149 public void TestOsNpcCreateUsingAppearanceFromAvatar()
150 {
151 TestHelpers.InMethod();
152// TestHelpers.EnableLogging();
153
154 // Store an avatar with a different height from default in a notecard.
155 UUID userId = TestHelpers.ParseTail(0x1);
156 float newHeight = 1.9f;
157
158 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
159 sp.Appearance.AvatarHeight = newHeight;
160 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
161 SceneObjectPart part = so.RootPart;
162 m_scene.AddSceneObject(so);
163
164 OSSL_Api osslApi = new OSSL_Api();
165 osslApi.Initialize(m_engine, part, null);
166
167 string notecardName = "appearanceNc";
168 osslApi.osOwnerSaveAppearance(notecardName);
169
170 // Try creating a bot using the existing avatar's appearance
171 string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString());
172 Assert.That(npcRaw, Is.Not.Null);
173
174 UUID npcId = new UUID(npcRaw);
175 ScenePresence npc = m_scene.GetScenePresence(npcId);
176 Assert.That(npc, Is.Not.Null);
177 Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight));
178 }
179
180 [Test]
181 public void TestOsNpcLoadAppearance()
182 {
183 TestHelpers.InMethod();
184
185 // Store an avatar with a different height from default in a notecard.
186 UUID userId = TestHelpers.ParseTail(0x1);
187 float firstHeight = 1.9f;
188 float secondHeight = 2.1f;
189 string firstAppearanceNcName = "appearanceNc1";
190 string secondAppearanceNcName = "appearanceNc2";
191
192 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
193 sp.Appearance.AvatarHeight = firstHeight;
194 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
195 SceneObjectPart part = so.RootPart;
196 m_scene.AddSceneObject(so);
197
198 OSSL_Api osslApi = new OSSL_Api();
199 osslApi.Initialize(m_engine, part, null);
200
201 osslApi.osOwnerSaveAppearance(firstAppearanceNcName);
202
203 string npcRaw
204 = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName);
205
206 // Create a second appearance notecard with a different height
207 sp.Appearance.AvatarHeight = secondHeight;
208 osslApi.osOwnerSaveAppearance(secondAppearanceNcName);
209
210 osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName);
211
212 UUID npcId = new UUID(npcRaw);
213 ScenePresence npc = m_scene.GetScenePresence(npcId);
214 Assert.That(npc, Is.Not.Null);
215 Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(secondHeight));
216 }
217
218 [Test]
219 public void TestOsNpcLoadAppearanceNotExistingNotecard()
220 {
221 TestHelpers.InMethod();
222
223 // Store an avatar with a different height from default in a notecard.
224 UUID userId = TestHelpers.ParseTail(0x1);
225 float firstHeight = 1.9f;
226 float secondHeight = 2.1f;
227 string firstAppearanceNcName = "appearanceNc1";
228 string secondAppearanceNcName = "appearanceNc2";
229
230 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
231 sp.Appearance.AvatarHeight = firstHeight;
232 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
233 SceneObjectPart part = so.RootPart;
234 m_scene.AddSceneObject(so);
235
236 OSSL_Api osslApi = new OSSL_Api();
237 osslApi.Initialize(m_engine, part, null);
238
239 osslApi.osOwnerSaveAppearance(firstAppearanceNcName);
240
241 string npcRaw
242 = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName);
243
244 bool gotExpectedException = false;
245 try
246 {
247 osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName);
248 }
249 catch (ScriptException)
250 {
251 gotExpectedException = true;
252 }
253
254 Assert.That(gotExpectedException, Is.True);
255
256 UUID npcId = new UUID(npcRaw);
257 ScenePresence npc = m_scene.GetScenePresence(npcId);
258 Assert.That(npc, Is.Not.Null);
259 Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(firstHeight));
260 }
261
262 /// <summary>
82 /// Test removal of an owned NPC. 263 /// Test removal of an owned NPC.
83 /// </summary> 264 /// </summary>
84 [Test] 265 [Test]
85 public void TestOsNpcRemoveOwned() 266 public void TestOsNpcRemoveOwned()
86 { 267 {
87 TestHelpers.InMethod(); 268 TestHelpers.InMethod();
88// log4net.Config.XmlConfigurator.Configure();
89 269
90 // Store an avatar with a different height from default in a notecard. 270 // Store an avatar with a different height from default in a notecard.
91 UUID userId = TestHelpers.ParseTail(0x1); 271 UUID userId = TestHelpers.ParseTail(0x1);
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
index 5c4174e..9405075 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
@@ -96,9 +96,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
96 if (part == null) 96 if (part == null)
97 return; 97 return;
98 98
99 if ((part.ScriptEvents & scriptEvents.money) == 0)
100 part = part.ParentGroup.RootPart;
101
99 m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount); 102 m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount);
100 103
101 part = part.ParentGroup.RootPart; 104// part = part.ParentGroup.RootPart;
102 money(part.LocalId, agentID, amount); 105 money(part.LocalId, agentID, amount);
103 } 106 }
104 107
@@ -152,9 +155,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
152 det[0] = new DetectParams(); 155 det[0] = new DetectParams();
153 det[0].Key = remoteClient.AgentId; 156 det[0].Key = remoteClient.AgentId;
154 det[0].Populate(myScriptEngine.World); 157 det[0].Populate(myScriptEngine.World);
155 det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X, 158 det[0].OffsetPos = offsetPos;
156 offsetPos.Y,
157 offsetPos.Z);
158 159
159 if (originalID == 0) 160 if (originalID == 0)
160 { 161 {
@@ -298,9 +299,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
298 foreach (DetectedObject detobj in col.Colliders) 299 foreach (DetectedObject detobj in col.Colliders)
299 { 300 {
300 DetectParams d = new DetectParams(); 301 DetectParams d = new DetectParams();
301 d.Position = new LSL_Types.Vector3(detobj.posVector.X, 302 d.Position = detobj.posVector;
302 detobj.posVector.Y,
303 detobj.posVector.Z);
304 d.Populate(myScriptEngine.World); 303 d.Populate(myScriptEngine.World);
305 det.Add(d); 304 det.Add(d);
306 myScriptEngine.PostObjectEvent(localID, new EventParams( 305 myScriptEngine.PostObjectEvent(localID, new EventParams(
@@ -318,9 +317,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
318 foreach (DetectedObject detobj in col.Colliders) 317 foreach (DetectedObject detobj in col.Colliders)
319 { 318 {
320 DetectParams d = new DetectParams(); 319 DetectParams d = new DetectParams();
321 d.Position = new LSL_Types.Vector3(detobj.posVector.X, 320 d.Position = detobj.posVector;
322 detobj.posVector.Y,
323 detobj.posVector.Z);
324 d.Populate(myScriptEngine.World); 321 d.Populate(myScriptEngine.World);
325 det.Add(d); 322 det.Add(d);
326 myScriptEngine.PostObjectEvent(localID, new EventParams( 323 myScriptEngine.PostObjectEvent(localID, new EventParams(
@@ -337,9 +334,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
337 foreach (DetectedObject detobj in col.Colliders) 334 foreach (DetectedObject detobj in col.Colliders)
338 { 335 {
339 DetectParams d = new DetectParams(); 336 DetectParams d = new DetectParams();
340 d.Position = new LSL_Types.Vector3(detobj.posVector.X, 337 d.Position = detobj.posVector;
341 detobj.posVector.Y,
342 detobj.posVector.Z);
343 d.Populate(myScriptEngine.World); 338 d.Populate(myScriptEngine.World);
344 det.Add(d); 339 det.Add(d);
345 myScriptEngine.PostObjectEvent(localID, new EventParams( 340 myScriptEngine.PostObjectEvent(localID, new EventParams(
@@ -381,8 +376,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
381 myScriptEngine.PostObjectEvent(localID, new EventParams( 376 myScriptEngine.PostObjectEvent(localID, new EventParams(
382 "at_target", new object[] { 377 "at_target", new object[] {
383 new LSL_Types.LSLInteger(handle), 378 new LSL_Types.LSLInteger(handle),
384 new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z), 379 new LSL_Types.Vector3(targetpos),
385 new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) }, 380 new LSL_Types.Vector3(atpos) },
386 new DetectParams[0])); 381 new DetectParams[0]));
387 } 382 }
388 383
@@ -399,8 +394,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
399 myScriptEngine.PostObjectEvent(localID, new EventParams( 394 myScriptEngine.PostObjectEvent(localID, new EventParams(
400 "at_rot_target", new object[] { 395 "at_rot_target", new object[] {
401 new LSL_Types.LSLInteger(handle), 396 new LSL_Types.LSLInteger(handle),
402 new LSL_Types.Quaternion(targetrot.X,targetrot.Y,targetrot.Z,targetrot.W), 397 new LSL_Types.Quaternion(targetrot),
403 new LSL_Types.Quaternion(atrot.X,atrot.Y,atrot.Z,atrot.W) }, 398 new LSL_Types.Quaternion(atrot) },
404 new DetectParams[0])); 399 new DetectParams[0]));
405 } 400 }
406 401
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bd26a8b
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.ScriptEngine.XEngine")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("1feed7de-3d45-4d3d-80e2-b57566284df5")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
index f247a0b..f331658 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
@@ -90,7 +90,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
90// log4net.Config.XmlConfigurator.Configure(); 90// log4net.Config.XmlConfigurator.Configure();
91 91
92 UUID userId = TestHelpers.ParseTail(0x1); 92 UUID userId = TestHelpers.ParseTail(0x1);
93// UUID objectId = TestHelpers.ParseTail(0x2); 93// UUID objectId = TestHelpers.ParseTail(0x100);
94// UUID itemId = TestHelpers.ParseTail(0x3); 94// UUID itemId = TestHelpers.ParseTail(0x3);
95 string itemName = "TestStartScript() Item"; 95 string itemName = "TestStartScript() Item";
96 96
@@ -105,12 +105,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
105 105
106 m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; 106 m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
107 107
108 m_scene.RezNewScript(userId, itemTemplate); 108 SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate);
109 109
110 m_chatEvent.WaitOne(60000); 110 m_chatEvent.WaitOne(60000);
111 111
112 Assert.That(m_osChatMessageReceived, Is.Not.Null, "No chat message received in TestStartScript()"); 112 Assert.That(m_osChatMessageReceived, Is.Not.Null, "No chat message received in TestStartScript()");
113 Assert.That(m_osChatMessageReceived.Message, Is.EqualTo("Script running")); 113 Assert.That(m_osChatMessageReceived.Message, Is.EqualTo("Script running"));
114
115 bool running;
116 TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
117 Assert.That(
118 SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True);
119 Assert.That(running, Is.True);
114 } 120 }
115 121
116 private void OnChatFromWorld(object sender, OSChatMessage oscm) 122 private void OnChatFromWorld(object sender, OSChatMessage oscm)
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index f6cb7df..9f05666 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -656,7 +656,19 @@ namespace OpenSim.Region.ScriptEngine.XEngine
656 if (m_Assemblies.ContainsKey(instance.AssetID)) 656 if (m_Assemblies.ContainsKey(instance.AssetID))
657 { 657 {
658 string assembly = m_Assemblies[instance.AssetID]; 658 string assembly = m_Assemblies[instance.AssetID];
659 instance.SaveState(assembly); 659
660 try
661 {
662 instance.SaveState(assembly);
663 }
664 catch (Exception e)
665 {
666 m_log.Error(
667 string.Format(
668 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
669 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
670 , e);
671 }
660 } 672 }
661 673
662 // Clear the event queue and abort the instance thread 674 // Clear the event queue and abort the instance thread
@@ -778,7 +790,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine
778 assembly = m_Assemblies[i.AssetID]; 790 assembly = m_Assemblies[i.AssetID];
779 791
780 792
781 i.SaveState(assembly); 793 try
794 {
795 i.SaveState(assembly);
796 }
797 catch (Exception e)
798 {
799 m_log.Error(
800 string.Format(
801 "[XEngine]: Failed to save state of script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
802 i.PrimName, i.ScriptName, i.ItemID, i.ObjectID, World.Name)
803 , e);
804 }
782 } 805 }
783 806
784 instances.Clear(); 807 instances.Clear();
@@ -971,6 +994,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
971 // This delay exists to stop mono problems where script compilation and startup would stop the sim 994 // This delay exists to stop mono problems where script compilation and startup would stop the sim
972 // working properly for the session. 995 // working properly for the session.
973 System.Threading.Thread.Sleep(m_StartDelay); 996 System.Threading.Thread.Sleep(m_StartDelay);
997
998 m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name);
974 } 999 }
975 1000
976 object[] o; 1001 object[] o;
@@ -986,13 +1011,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
986 if (m_InitialStartup) 1011 if (m_InitialStartup)
987 if (scriptsStarted % 50 == 0) 1012 if (scriptsStarted % 50 == 0)
988 m_log.InfoFormat( 1013 m_log.InfoFormat(
989 "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); 1014 "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name);
990 } 1015 }
991 } 1016 }
992 1017
993 if (m_InitialStartup) 1018 if (m_InitialStartup)
994 m_log.InfoFormat( 1019 m_log.InfoFormat(
995 "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); 1020 "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name);
996 1021
997 // NOTE: Despite having a lockless queue, this lock is required 1022 // NOTE: Despite having a lockless queue, this lock is required
998 // to make sure there is never no compile thread while there 1023 // to make sure there is never no compile thread while there
@@ -1053,10 +1078,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1053 return false; 1078 return false;
1054 } 1079 }
1055 1080
1056 UUID assetID = item.AssetID; 1081 m_log.DebugFormat(
1082 "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1083 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1084 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1057 1085
1058 //m_log.DebugFormat("[XEngine] Compiling script {0} ({1} on object {2})", 1086 UUID assetID = item.AssetID;
1059 // item.Name, itemID.ToString(), part.ParentGroup.RootPart.Name);
1060 1087
1061 ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); 1088 ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID);
1062 1089
@@ -1235,10 +1262,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1235 item.Name, startParam, postOnRez, 1262 item.Name, startParam, postOnRez,
1236 stateSource, m_MaxScriptQueue); 1263 stateSource, m_MaxScriptQueue);
1237 1264
1238 m_log.DebugFormat( 1265// m_log.DebugFormat(
1239 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", 1266// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1240 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 1267// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1241 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1268// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1242 1269
1243 if (presence != null) 1270 if (presence != null)
1244 { 1271 {
@@ -1554,9 +1581,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1554 else if (p[i] is string) 1581 else if (p[i] is string)
1555 lsl_p[i] = new LSL_Types.LSLString((string)p[i]); 1582 lsl_p[i] = new LSL_Types.LSLString((string)p[i]);
1556 else if (p[i] is Vector3) 1583 else if (p[i] is Vector3)
1557 lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); 1584 lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]);
1558 else if (p[i] is Quaternion) 1585 else if (p[i] is Quaternion)
1559 lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); 1586 lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]);
1560 else if (p[i] is float) 1587 else if (p[i] is float)
1561 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); 1588 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]);
1562 else 1589 else
@@ -1580,9 +1607,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1580 else if (p[i] is string) 1607 else if (p[i] is string)
1581 lsl_p[i] = new LSL_Types.LSLString((string)p[i]); 1608 lsl_p[i] = new LSL_Types.LSLString((string)p[i]);
1582 else if (p[i] is Vector3) 1609 else if (p[i] is Vector3)
1583 lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); 1610 lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]);
1584 else if (p[i] is Quaternion) 1611 else if (p[i] is Quaternion)
1585 lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); 1612 lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]);
1586 else if (p[i] is float) 1613 else if (p[i] is float)
1587 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); 1614 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]);
1588 else 1615 else
diff --git a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..100cf99
--- /dev/null
+++ b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Region.UserStatistics")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("42b28288-5fdd-478f-8903-8dccbbb2d5f9")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs
index c11ea02..b08233c 100644
--- a/OpenSim/Region/UserStatistics/WebStatsModule.cs
+++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs
@@ -43,15 +43,20 @@ using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.Framework.Interfaces; 43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes; 44using OpenSim.Region.Framework.Scenes;
45using Mono.Data.SqliteClient; 45using Mono.Data.SqliteClient;
46using Mono.Addins;
46 47
47using Caps = OpenSim.Framework.Capabilities.Caps; 48using Caps = OpenSim.Framework.Capabilities.Caps;
48 49
49using OSD = OpenMetaverse.StructuredData.OSD; 50using OSD = OpenMetaverse.StructuredData.OSD;
50using OSDMap = OpenMetaverse.StructuredData.OSDMap; 51using OSDMap = OpenMetaverse.StructuredData.OSDMap;
51 52
53[assembly: Addin("WebStats", "1.0")]
54[assembly: AddinDependency("OpenSim", "0.5")]
55
52namespace OpenSim.Region.UserStatistics 56namespace OpenSim.Region.UserStatistics
53{ 57{
54 public class WebStatsModule : IRegionModule 58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WebStatsModule")]
59 public class WebStatsModule : ISharedRegionModule
55 { 60 {
56 private static readonly ILog m_log = 61 private static readonly ILog m_log =
57 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 62 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -61,7 +66,7 @@ namespace OpenSim.Region.UserStatistics
61 /// <summary> 66 /// <summary>
62 /// User statistics sessions keyed by agent ID 67 /// User statistics sessions keyed by agent ID
63 /// </summary> 68 /// </summary>
64 private Dictionary<UUID, UserSessionID> m_sessions = new Dictionary<UUID, UserSessionID>(); 69 private Dictionary<UUID, UserSession> m_sessions = new Dictionary<UUID, UserSession>();
65 70
66 private List<Scene> m_scenes = new List<Scene>(); 71 private List<Scene> m_scenes = new List<Scene>();
67 private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>(); 72 private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>();
@@ -74,59 +79,69 @@ namespace OpenSim.Region.UserStatistics
74 private string m_loglines = String.Empty; 79 private string m_loglines = String.Empty;
75 private volatile int lastHit = 12000; 80 private volatile int lastHit = 12000;
76 81
77 public virtual void Initialise(Scene scene, IConfigSource config) 82 #region ISharedRegionModule
83
84 public virtual void Initialise(IConfigSource config)
78 { 85 {
79 IConfig cnfg = config.Configs["WebStats"]; 86 IConfig cnfg = config.Configs["WebStats"];
80 87
81 if (cnfg != null) 88 if (cnfg != null)
82 enabled = cnfg.GetBoolean("enabled", false); 89 enabled = cnfg.GetBoolean("enabled", false);
83 90 }
91
92 public virtual void PostInitialise()
93 {
94 if (!enabled)
95 return;
96
97 AddEventHandlers();
98
99 if (Util.IsWindows())
100 Util.LoadArchSpecificWindowsDll("sqlite3.dll");
101
102 //IConfig startupConfig = config.Configs["Startup"];
103
104 dbConn = new SqliteConnection("URI=file:LocalUserStatistics.db,version=3");
105 dbConn.Open();
106 CreateTables(dbConn);
107
108 Prototype_distributor protodep = new Prototype_distributor();
109 Updater_distributor updatedep = new Updater_distributor();
110 ActiveConnectionsAJAX ajConnections = new ActiveConnectionsAJAX();
111 SimStatsAJAX ajSimStats = new SimStatsAJAX();
112 LogLinesAJAX ajLogLines = new LogLinesAJAX();
113 Default_Report defaultReport = new Default_Report();
114 Clients_report clientReport = new Clients_report();
115 Sessions_Report sessionsReport = new Sessions_Report();
116
117 reports.Add("prototype.js", protodep);
118 reports.Add("updater.js", updatedep);
119 reports.Add("activeconnectionsajax.html", ajConnections);
120 reports.Add("simstatsajax.html", ajSimStats);
121 reports.Add("activelogajax.html", ajLogLines);
122 reports.Add("default.report", defaultReport);
123 reports.Add("clients.report", clientReport);
124 reports.Add("sessions.report", sessionsReport);
125
126 ////
127 // Add Your own Reports here (Do Not Modify Lines here Devs!)
128 ////
129
130 ////
131 // End Own reports section
132 ////
133
134 MainServer.Instance.AddHTTPHandler("/SStats/", HandleStatsRequest);
135 MainServer.Instance.AddHTTPHandler("/CAPS/VS/", HandleUnknownCAPSRequest);
136 }
137
138 public virtual void AddRegion(Scene scene)
139 {
84 if (!enabled) 140 if (!enabled)
85 return; 141 return;
86 142
87 lock (m_scenes) 143 lock (m_scenes)
88 { 144 {
89 if (m_scenes.Count == 0)
90 {
91 if (Util.IsWindows())
92 Util.LoadArchSpecificWindowsDll("sqlite3.dll");
93
94 //IConfig startupConfig = config.Configs["Startup"];
95
96 dbConn = new SqliteConnection("URI=file:LocalUserStatistics.db,version=3");
97 dbConn.Open();
98 CreateTables(dbConn);
99
100 Prototype_distributor protodep = new Prototype_distributor();
101 Updater_distributor updatedep = new Updater_distributor();
102 ActiveConnectionsAJAX ajConnections = new ActiveConnectionsAJAX();
103 SimStatsAJAX ajSimStats = new SimStatsAJAX();
104 LogLinesAJAX ajLogLines = new LogLinesAJAX();
105 Default_Report defaultReport = new Default_Report();
106 Clients_report clientReport = new Clients_report();
107 Sessions_Report sessionsReport = new Sessions_Report();
108
109 reports.Add("prototype.js", protodep);
110 reports.Add("updater.js", updatedep);
111 reports.Add("activeconnectionsajax.html", ajConnections);
112 reports.Add("simstatsajax.html", ajSimStats);
113 reports.Add("activelogajax.html", ajLogLines);
114 reports.Add("default.report", defaultReport);
115 reports.Add("clients.report", clientReport);
116 reports.Add("sessions.report", sessionsReport);
117
118 ////
119 // Add Your own Reports here (Do Not Modify Lines here Devs!)
120 ////
121
122 ////
123 // End Own reports section
124 ////
125
126 MainServer.Instance.AddHTTPHandler("/SStats/", HandleStatsRequest);
127 MainServer.Instance.AddHTTPHandler("/CAPS/VS/", HandleUnknownCAPSRequest);
128 }
129
130 m_scenes.Add(scene); 145 m_scenes.Add(scene);
131 if (m_simstatsCounters.ContainsKey(scene.RegionInfo.RegionID)) 146 if (m_simstatsCounters.ContainsKey(scene.RegionInfo.RegionID))
132 m_simstatsCounters.Remove(scene.RegionInfo.RegionID); 147 m_simstatsCounters.Remove(scene.RegionInfo.RegionID);
@@ -136,6 +151,39 @@ namespace OpenSim.Region.UserStatistics
136 } 151 }
137 } 152 }
138 153
154 public void RegionLoaded(Scene scene)
155 {
156 }
157
158 public void RemoveRegion(Scene scene)
159 {
160 }
161
162 public virtual void Close()
163 {
164 if (!enabled)
165 return;
166
167 dbConn.Close();
168 dbConn.Dispose();
169 m_sessions.Clear();
170 m_scenes.Clear();
171 reports.Clear();
172 m_simstatsCounters.Clear();
173 }
174
175 public virtual string Name
176 {
177 get { return "ViewerStatsModule"; }
178 }
179
180 public Type ReplaceableInterface
181 {
182 get { return null; }
183 }
184
185 #endregion
186
139 private void ReceiveClassicSimStatsPacket(SimStats stats) 187 private void ReceiveClassicSimStatsPacket(SimStats stats)
140 { 188 {
141 if (!enabled) 189 if (!enabled)
@@ -251,37 +299,6 @@ namespace OpenSim.Region.UserStatistics
251 } 299 }
252 } 300 }
253 301
254 public virtual void PostInitialise()
255 {
256 if (!enabled)
257 return;
258
259 AddHandlers();
260 }
261
262 public virtual void Close()
263 {
264 if (!enabled)
265 return;
266
267 dbConn.Close();
268 dbConn.Dispose();
269 m_sessions.Clear();
270 m_scenes.Clear();
271 reports.Clear();
272 m_simstatsCounters.Clear();
273 }
274
275 public virtual string Name
276 {
277 get { return "ViewerStatsModule"; }
278 }
279
280 public bool IsSharedModule
281 {
282 get { return true; }
283 }
284
285 private void OnRegisterCaps(UUID agentID, Caps caps) 302 private void OnRegisterCaps(UUID agentID, Caps caps)
286 { 303 {
287// m_log.DebugFormat("[WEB STATS MODULE]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps); 304// m_log.DebugFormat("[WEB STATS MODULE]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps);
@@ -302,7 +319,7 @@ namespace OpenSim.Region.UserStatistics
302 { 319 {
303 } 320 }
304 321
305 protected virtual void AddHandlers() 322 protected virtual void AddEventHandlers()
306 { 323 {
307 lock (m_scenes) 324 lock (m_scenes)
308 { 325 {
@@ -319,14 +336,18 @@ namespace OpenSim.Region.UserStatistics
319 336
320 private void OnMakeRootAgent(ScenePresence agent) 337 private void OnMakeRootAgent(ScenePresence agent)
321 { 338 {
339// m_log.DebugFormat(
340// "[WEB STATS MODULE]: Looking for session {0} for {1} in {2}",
341// agent.ControllingClient.SessionId, agent.Name, agent.Scene.Name);
342
322 lock (m_sessions) 343 lock (m_sessions)
323 { 344 {
324 UserSessionID uid; 345 UserSession uid;
325 346
326 if (!m_sessions.ContainsKey(agent.UUID)) 347 if (!m_sessions.ContainsKey(agent.UUID))
327 { 348 {
328 UserSessionData usd = UserSessionUtil.newUserSessionData(); 349 UserSessionData usd = UserSessionUtil.newUserSessionData();
329 uid = new UserSessionID(); 350 uid = new UserSession();
330 uid.name_f = agent.Firstname; 351 uid.name_f = agent.Firstname;
331 uid.name_l = agent.Lastname; 352 uid.name_l = agent.Lastname;
332 uid.session_data = usd; 353 uid.session_data = usd;
@@ -411,9 +432,9 @@ namespace OpenSim.Region.UserStatistics
411 return String.Empty; 432 return String.Empty;
412 } 433 }
413 434
414 private UserSessionID ParseViewerStats(string request, UUID agentID) 435 private UserSession ParseViewerStats(string request, UUID agentID)
415 { 436 {
416 UserSessionID uid = new UserSessionID(); 437 UserSession uid = new UserSession();
417 UserSessionData usd; 438 UserSessionData usd;
418 OSD message = OSDParser.DeserializeLLSDXml(request); 439 OSD message = OSDParser.DeserializeLLSDXml(request);
419 OSDMap mmap; 440 OSDMap mmap;
@@ -425,22 +446,25 @@ namespace OpenSim.Region.UserStatistics
425 if (!m_sessions.ContainsKey(agentID)) 446 if (!m_sessions.ContainsKey(agentID))
426 { 447 {
427 m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID); 448 m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID);
428 return new UserSessionID(); 449 return new UserSession();
429 } 450 }
451
430 uid = m_sessions[agentID]; 452 uid = m_sessions[agentID];
453
454// m_log.DebugFormat("[WEB STATS MODULE]: Got session {0} for {1}", uid.session_id, agentID);
431 } 455 }
432 else 456 else
433 { 457 {
434 // parse through the beginning to locate the session 458 // parse through the beginning to locate the session
435 if (message.Type != OSDType.Map) 459 if (message.Type != OSDType.Map)
436 return new UserSessionID(); 460 return new UserSession();
437 461
438 mmap = (OSDMap)message; 462 mmap = (OSDMap)message;
439 { 463 {
440 UUID sessionID = mmap["session_id"].AsUUID(); 464 UUID sessionID = mmap["session_id"].AsUUID();
441 465
442 if (sessionID == UUID.Zero) 466 if (sessionID == UUID.Zero)
443 return new UserSessionID(); 467 return new UserSession();
444 468
445 469
446 // search through each session looking for the owner 470 // search through each session looking for the owner
@@ -459,7 +483,7 @@ namespace OpenSim.Region.UserStatistics
459 // can't find a session 483 // can't find a session
460 if (agentID == UUID.Zero) 484 if (agentID == UUID.Zero)
461 { 485 {
462 return new UserSessionID(); 486 return new UserSession();
463 } 487 }
464 } 488 }
465 } 489 }
@@ -468,12 +492,12 @@ namespace OpenSim.Region.UserStatistics
468 usd = uid.session_data; 492 usd = uid.session_data;
469 493
470 if (message.Type != OSDType.Map) 494 if (message.Type != OSDType.Map)
471 return new UserSessionID(); 495 return new UserSession();
472 496
473 mmap = (OSDMap)message; 497 mmap = (OSDMap)message;
474 { 498 {
475 if (mmap["agent"].Type != OSDType.Map) 499 if (mmap["agent"].Type != OSDType.Map)
476 return new UserSessionID(); 500 return new UserSession();
477 OSDMap agent_map = (OSDMap)mmap["agent"]; 501 OSDMap agent_map = (OSDMap)mmap["agent"];
478 usd.agent_id = agentID; 502 usd.agent_id = agentID;
479 usd.name_f = uid.name_f; 503 usd.name_f = uid.name_f;
@@ -493,17 +517,18 @@ namespace OpenSim.Region.UserStatistics
493 (float)agent_map["fps"].AsReal()); 517 (float)agent_map["fps"].AsReal());
494 518
495 if (mmap["downloads"].Type != OSDType.Map) 519 if (mmap["downloads"].Type != OSDType.Map)
496 return new UserSessionID(); 520 return new UserSession();
497 OSDMap downloads_map = (OSDMap)mmap["downloads"]; 521 OSDMap downloads_map = (OSDMap)mmap["downloads"];
498 usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal(); 522 usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal();
499 usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal(); 523 usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal();
500 usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal(); 524 usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal();
501 525
526// m_log.DebugFormat("[WEB STATS MODULE]: mmap[\"session_id\"] = [{0}]", mmap["session_id"].AsUUID());
502 527
503 usd.session_id = mmap["session_id"].AsUUID(); 528 usd.session_id = mmap["session_id"].AsUUID();
504 529
505 if (mmap["system"].Type != OSDType.Map) 530 if (mmap["system"].Type != OSDType.Map)
506 return new UserSessionID(); 531 return new UserSession();
507 OSDMap system_map = (OSDMap)mmap["system"]; 532 OSDMap system_map = (OSDMap)mmap["system"];
508 533
509 usd.s_cpu = system_map["cpu"].AsString(); 534 usd.s_cpu = system_map["cpu"].AsString();
@@ -512,13 +537,13 @@ namespace OpenSim.Region.UserStatistics
512 usd.s_ram = system_map["ram"].AsInteger(); 537 usd.s_ram = system_map["ram"].AsInteger();
513 538
514 if (mmap["stats"].Type != OSDType.Map) 539 if (mmap["stats"].Type != OSDType.Map)
515 return new UserSessionID(); 540 return new UserSession();
516 541
517 OSDMap stats_map = (OSDMap)mmap["stats"]; 542 OSDMap stats_map = (OSDMap)mmap["stats"];
518 { 543 {
519 544
520 if (stats_map["failures"].Type != OSDType.Map) 545 if (stats_map["failures"].Type != OSDType.Map)
521 return new UserSessionID(); 546 return new UserSession();
522 OSDMap stats_failures = (OSDMap)stats_map["failures"]; 547 OSDMap stats_failures = (OSDMap)stats_map["failures"];
523 usd.f_dropped = stats_failures["dropped"].AsInteger(); 548 usd.f_dropped = stats_failures["dropped"].AsInteger();
524 usd.f_failed_resends = stats_failures["failed_resends"].AsInteger(); 549 usd.f_failed_resends = stats_failures["failed_resends"].AsInteger();
@@ -527,18 +552,18 @@ namespace OpenSim.Region.UserStatistics
527 usd.f_send_packet = stats_failures["send_packet"].AsInteger(); 552 usd.f_send_packet = stats_failures["send_packet"].AsInteger();
528 553
529 if (stats_map["net"].Type != OSDType.Map) 554 if (stats_map["net"].Type != OSDType.Map)
530 return new UserSessionID(); 555 return new UserSession();
531 OSDMap stats_net = (OSDMap)stats_map["net"]; 556 OSDMap stats_net = (OSDMap)stats_map["net"];
532 { 557 {
533 if (stats_net["in"].Type != OSDType.Map) 558 if (stats_net["in"].Type != OSDType.Map)
534 return new UserSessionID(); 559 return new UserSession();
535 560
536 OSDMap net_in = (OSDMap)stats_net["in"]; 561 OSDMap net_in = (OSDMap)stats_net["in"];
537 usd.n_in_kb = (float)net_in["kbytes"].AsReal(); 562 usd.n_in_kb = (float)net_in["kbytes"].AsReal();
538 usd.n_in_pk = net_in["packets"].AsInteger(); 563 usd.n_in_pk = net_in["packets"].AsInteger();
539 564
540 if (stats_net["out"].Type != OSDType.Map) 565 if (stats_net["out"].Type != OSDType.Map)
541 return new UserSessionID(); 566 return new UserSession();
542 OSDMap net_out = (OSDMap)stats_net["out"]; 567 OSDMap net_out = (OSDMap)stats_net["out"];
543 568
544 usd.n_out_kb = (float)net_out["kbytes"].AsReal(); 569 usd.n_out_kb = (float)net_out["kbytes"].AsReal();
@@ -549,11 +574,18 @@ namespace OpenSim.Region.UserStatistics
549 574
550 uid.session_data = usd; 575 uid.session_data = usd;
551 m_sessions[agentID] = uid; 576 m_sessions[agentID] = uid;
577
578// m_log.DebugFormat(
579// "[WEB STATS MODULE]: Parse data for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id);
580
552 return uid; 581 return uid;
553 } 582 }
554 583
555 private void UpdateUserStats(UserSessionID uid, SqliteConnection db) 584 private void UpdateUserStats(UserSession uid, SqliteConnection db)
556 { 585 {
586// m_log.DebugFormat(
587// "[WEB STATS MODULE]: Updating user stats for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id);
588
557 if (uid.session_id == UUID.Zero) 589 if (uid.session_id == UUID.Zero)
558 return; 590 return;
559 591
@@ -740,7 +772,6 @@ VALUES
740 s.min_ping = ArrayMin_f(__ping); 772 s.min_ping = ArrayMin_f(__ping);
741 s.max_ping = ArrayMax_f(__ping); 773 s.max_ping = ArrayMax_f(__ping);
742 s.mode_ping = ArrayMode_f(__ping); 774 s.mode_ping = ArrayMode_f(__ping);
743
744 } 775 }
745 776
746 #region Statistics 777 #region Statistics
@@ -985,7 +1016,7 @@ VALUES
985 } 1016 }
986 #region structs 1017 #region structs
987 1018
988 public struct UserSessionID 1019 public class UserSession
989 { 1020 {
990 public UUID session_id; 1021 public UUID session_id;
991 public UUID region_id; 1022 public UUID region_id;
diff --git a/OpenSim/Server/Base/HttpServerBase.cs b/OpenSim/Server/Base/HttpServerBase.cs
index 29b1c00..954783c 100644
--- a/OpenSim/Server/Base/HttpServerBase.cs
+++ b/OpenSim/Server/Base/HttpServerBase.cs
@@ -52,7 +52,7 @@ namespace OpenSim.Server.Base
52 52
53 protected override void ReadConfig() 53 protected override void ReadConfig()
54 { 54 {
55 IConfig networkConfig = m_Config.Configs["Network"]; 55 IConfig networkConfig = Config.Configs["Network"];
56 56
57 if (networkConfig == null) 57 if (networkConfig == null)
58 { 58 {
diff --git a/OpenSim/Server/Base/Properties/AssemblyInfo.cs b/OpenSim/Server/Base/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4bbe358
--- /dev/null
+++ b/OpenSim/Server/Base/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Server.Base")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("8fbd5035-0dbc-4b9a-ad1a-a7567f254ea9")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs
index b137c05..5b23149 100644
--- a/OpenSim/Server/Base/ServicesServerBase.cs
+++ b/OpenSim/Server/Base/ServicesServerBase.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using System.IO; 30using System.IO;
30using System.Reflection; 31using System.Reflection;
31using System.Threading; 32using System.Threading;
@@ -33,6 +34,7 @@ using System.Text;
33using System.Xml; 34using System.Xml;
34using OpenSim.Framework; 35using OpenSim.Framework;
35using OpenSim.Framework.Console; 36using OpenSim.Framework.Console;
37using OpenSim.Framework.Servers;
36using log4net; 38using log4net;
37using log4net.Config; 39using log4net.Config;
38using log4net.Appender; 40using log4net.Appender;
@@ -42,7 +44,7 @@ using Nini.Config;
42 44
43namespace OpenSim.Server.Base 45namespace OpenSim.Server.Base
44{ 46{
45 public class ServicesServerBase 47 public class ServicesServerBase : ServerBase
46 { 48 {
47 // Logger 49 // Logger
48 // 50 //
@@ -54,26 +56,13 @@ namespace OpenSim.Server.Base
54 // 56 //
55 protected string[] m_Arguments; 57 protected string[] m_Arguments;
56 58
57 // Configuration
58 //
59 protected IConfigSource m_Config = null;
60
61 public IConfigSource Config
62 {
63 get { return m_Config; }
64 }
65
66 // Run flag 59 // Run flag
67 // 60 //
68 private bool m_Running = true; 61 private bool m_Running = true;
69 62
70 // PID file
71 //
72 private string m_pidFile = String.Empty;
73
74 // Handle all the automagical stuff 63 // Handle all the automagical stuff
75 // 64 //
76 public ServicesServerBase(string prompt, string[] args) 65 public ServicesServerBase(string prompt, string[] args) : base()
77 { 66 {
78 // Save raw arguments 67 // Save raw arguments
79 // 68 //
@@ -120,11 +109,11 @@ namespace OpenSim.Server.Base
120 configUri.Scheme == Uri.UriSchemeHttp) 109 configUri.Scheme == Uri.UriSchemeHttp)
121 { 110 {
122 XmlReader r = XmlReader.Create(iniFile); 111 XmlReader r = XmlReader.Create(iniFile);
123 m_Config = new XmlConfigSource(r); 112 Config = new XmlConfigSource(r);
124 } 113 }
125 else 114 else
126 { 115 {
127 m_Config = new IniConfigSource(iniFile); 116 Config = new IniConfigSource(iniFile);
128 } 117 }
129 } 118 }
130 catch (Exception e) 119 catch (Exception e)
@@ -136,13 +125,13 @@ namespace OpenSim.Server.Base
136 // Merge the configuration from the command line into the 125 // Merge the configuration from the command line into the
137 // loaded file 126 // loaded file
138 // 127 //
139 m_Config.Merge(argvConfig); 128 Config.Merge(argvConfig);
140 129
141 // Refresh the startupConfig post merge 130 // Refresh the startupConfig post merge
142 // 131 //
143 if (m_Config.Configs["Startup"] != null) 132 if (Config.Configs["Startup"] != null)
144 { 133 {
145 startupConfig = m_Config.Configs["Startup"]; 134 startupConfig = Config.Configs["Startup"];
146 } 135 }
147 136
148 prompt = startupConfig.GetString("Prompt", prompt); 137 prompt = startupConfig.GetString("Prompt", prompt);
@@ -172,6 +161,8 @@ namespace OpenSim.Server.Base
172 MainConsole.Instance = new LocalConsole(prompt); 161 MainConsole.Instance = new LocalConsole(prompt);
173 } 162 }
174 163
164 m_console = MainConsole.Instance;
165
175 // Configure the appenders for log4net 166 // Configure the appenders for log4net
176 // 167 //
177 OpenSimAppender consoleAppender = null; 168 OpenSimAppender consoleAppender = null;
@@ -187,54 +178,15 @@ namespace OpenSim.Server.Base
187 XmlConfigurator.Configure(); 178 XmlConfigurator.Configure();
188 } 179 }
189 180
190 ILoggerRepository repository = LogManager.GetRepository(); 181 RegisterCommonAppenders(startupConfig);
191 IAppender[] appenders = repository.GetAppenders();
192
193 foreach (IAppender appender in appenders)
194 {
195 if (appender.Name == "Console")
196 {
197 consoleAppender = (OpenSimAppender)appender;
198 }
199 if (appender.Name == "LogFileAppender")
200 {
201 fileAppender = (FileAppender)appender;
202 }
203 }
204
205 if (consoleAppender == null)
206 {
207 System.Console.WriteLine("No console appender found. Server can't start");
208 Thread.CurrentThread.Abort();
209 }
210 else
211 {
212 consoleAppender.Console = (ConsoleBase)MainConsole.Instance;
213
214 if (null == consoleAppender.Threshold)
215 consoleAppender.Threshold = Level.All;
216 }
217
218 // Set log file
219 //
220 if (fileAppender != null)
221 {
222 if (startupConfig != null)
223 {
224 string cfgFileName = startupConfig.GetString("logfile", null);
225 if (cfgFileName != null)
226 {
227 fileAppender.File = cfgFileName;
228 fileAppender.ActivateOptions();
229 }
230 }
231 }
232 182
233 if (startupConfig.GetString("PIDFile", String.Empty) != String.Empty) 183 if (startupConfig.GetString("PIDFile", String.Empty) != String.Empty)
234 { 184 {
235 CreatePIDFile(startupConfig.GetString("PIDFile")); 185 CreatePIDFile(startupConfig.GetString("PIDFile"));
236 } 186 }
237 187
188 RegisterCommonCommands();
189
238 // Register the quit command 190 // Register the quit command
239 // 191 //
240 MainConsole.Instance.Commands.AddCommand("General", false, "quit", 192 MainConsole.Instance.Commands.AddCommand("General", false, "quit",
@@ -244,12 +196,6 @@ namespace OpenSim.Server.Base
244 MainConsole.Instance.Commands.AddCommand("General", false, "shutdown", 196 MainConsole.Instance.Commands.AddCommand("General", false, "shutdown",
245 "shutdown", 197 "shutdown",
246 "Quit the application", HandleQuit); 198 "Quit the application", HandleQuit);
247
248 // Register a command to read other commands from a file
249 MainConsole.Instance.Commands.AddCommand("General", false, "command-script",
250 "command-script <script>",
251 "Run a command script from file", HandleScript);
252
253 199
254 // Allow derived classes to perform initialization that 200 // Allow derived classes to perform initialization that
255 // needs to be done after the console has opened 201 // needs to be done after the console has opened
@@ -276,8 +222,8 @@ namespace OpenSim.Server.Base
276 } 222 }
277 } 223 }
278 224
279 if (m_pidFile != String.Empty) 225 RemovePIDFile();
280 File.Delete(m_pidFile); 226
281 return 0; 227 return 0;
282 } 228 }
283 229
@@ -285,43 +231,9 @@ namespace OpenSim.Server.Base
285 { 231 {
286 m_Running = false; 232 m_Running = false;
287 m_log.Info("[CONSOLE] Quitting"); 233 m_log.Info("[CONSOLE] Quitting");
288 }
289
290 protected virtual void HandleScript(string module, string[] parms)
291 {
292 if (parms.Length != 2)
293 {
294 return;
295 }
296 RunCommandScript(parms[1]);
297 }
298
299 /// <summary>
300 /// Run an optional startup list of commands
301 /// </summary>
302 /// <param name="fileName"></param>
303 private void RunCommandScript(string fileName)
304 {
305 if (File.Exists(fileName))
306 {
307 m_log.Info("[COMMANDFILE]: Running " + fileName);
308 234
309 using (StreamReader readFile = File.OpenText(fileName))
310 {
311 string currentCommand;
312 while ((currentCommand = readFile.ReadLine()) != null)
313 {
314 if (currentCommand != String.Empty)
315 {
316 m_log.Info("[COMMANDFILE]: Running '" + currentCommand + "'");
317 MainConsole.Instance.RunCommand(currentCommand);
318 }
319 }
320 }
321 }
322 } 235 }
323 236
324
325 protected virtual void ReadConfig() 237 protected virtual void ReadConfig()
326 { 238 {
327 } 239 }
@@ -329,21 +241,5 @@ namespace OpenSim.Server.Base
329 protected virtual void Initialise() 241 protected virtual void Initialise()
330 { 242 {
331 } 243 }
332
333 protected void CreatePIDFile(string path)
334 {
335 try
336 {
337 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
338 FileStream fs = File.Create(path);
339 Byte[] buf = Encoding.ASCII.GetBytes(pidstring);
340 fs.Write(buf, 0, buf.Length);
341 fs.Close();
342 m_pidFile = path;
343 }
344 catch (Exception)
345 {
346 }
347 }
348 } 244 }
349} 245} \ No newline at end of file
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs
index 46b0c67..ff45d94 100644
--- a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs
+++ b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs
@@ -67,10 +67,25 @@ namespace OpenSim.Server.Handlers.Asset
67 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName)); 67 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
68 68
69 bool allowDelete = serverConfig.GetBoolean("AllowRemoteDelete", false); 69 bool allowDelete = serverConfig.GetBoolean("AllowRemoteDelete", false);
70 bool allowDeleteAllTypes = serverConfig.GetBoolean("AllowRemoteDeleteAllTypes", false);
71
72 AllowedRemoteDeleteTypes allowedRemoteDeleteTypes;
73
74 if (!allowDelete)
75 {
76 allowedRemoteDeleteTypes = AllowedRemoteDeleteTypes.None;
77 }
78 else
79 {
80 if (allowDeleteAllTypes)
81 allowedRemoteDeleteTypes = AllowedRemoteDeleteTypes.All;
82 else
83 allowedRemoteDeleteTypes = AllowedRemoteDeleteTypes.MapTile;
84 }
70 85
71 server.AddStreamHandler(new AssetServerGetHandler(m_AssetService)); 86 server.AddStreamHandler(new AssetServerGetHandler(m_AssetService));
72 server.AddStreamHandler(new AssetServerPostHandler(m_AssetService)); 87 server.AddStreamHandler(new AssetServerPostHandler(m_AssetService));
73 server.AddStreamHandler(new AssetServerDeleteHandler(m_AssetService, allowDelete)); 88 server.AddStreamHandler(new AssetServerDeleteHandler(m_AssetService, allowedRemoteDeleteTypes));
74 89
75 MainConsole.Instance.Commands.AddCommand("Assets", false, 90 MainConsole.Instance.Commands.AddCommand("Assets", false,
76 "show asset", 91 "show asset",
@@ -141,6 +156,9 @@ namespace OpenSim.Server.Handlers.Asset
141 } 156 }
142 157
143 string fileName = rawAssetId; 158 string fileName = rawAssetId;
159
160 if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName))
161 return;
144 162
145 using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) 163 using (FileStream fs = new FileStream(fileName, FileMode.CreateNew))
146 { 164 {
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs b/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs
index 0cfe5b1..986394b 100644
--- a/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs
+++ b/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs
@@ -42,18 +42,32 @@ using OpenSim.Framework.Servers.HttpServer;
42 42
43namespace OpenSim.Server.Handlers.Asset 43namespace OpenSim.Server.Handlers.Asset
44{ 44{
45 /// <summary>
46 /// Remote deletes allowed.
47 /// </summary>
48 public enum AllowedRemoteDeleteTypes
49 {
50 None,
51 MapTile,
52 All
53 }
54
45 public class AssetServerDeleteHandler : BaseStreamHandler 55 public class AssetServerDeleteHandler : BaseStreamHandler
46 { 56 {
47 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 57 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 58
49 private IAssetService m_AssetService; 59 private IAssetService m_AssetService;
50 protected bool m_allowDelete;
51 60
52 public AssetServerDeleteHandler(IAssetService service, bool allowDelete) : 61 /// <summary>
62 /// Asset types that can be deleted remotely.
63 /// </summary>
64 private AllowedRemoteDeleteTypes m_allowedTypes;
65
66 public AssetServerDeleteHandler(IAssetService service, AllowedRemoteDeleteTypes allowedTypes) :
53 base("DELETE", "/assets") 67 base("DELETE", "/assets")
54 { 68 {
55 m_AssetService = service; 69 m_AssetService = service;
56 m_allowDelete = allowDelete; 70 m_allowedTypes = allowedTypes;
57 } 71 }
58 72
59 public override byte[] Handle(string path, Stream request, 73 public override byte[] Handle(string path, Stream request,
@@ -63,13 +77,32 @@ namespace OpenSim.Server.Handlers.Asset
63 77
64 string[] p = SplitParams(path); 78 string[] p = SplitParams(path);
65 79
66 if (p.Length > 0 && m_allowDelete) 80 if (p.Length > 0)
67 { 81 {
68 result = m_AssetService.Delete(p[0]); 82 if (m_allowedTypes != AllowedRemoteDeleteTypes.None)
83 {
84 string assetID = p[0];
85
86 AssetBase asset = m_AssetService.Get(assetID);
87 if (asset != null)
88 {
89 if (m_allowedTypes == AllowedRemoteDeleteTypes.All
90 || (int)(asset.Flags & AssetFlags.Maptile) != 0)
91 {
92 result = m_AssetService.Delete(assetID);
93 }
94 else
95 {
96 m_log.DebugFormat(
97 "[ASSET SERVER DELETE HANDLER]: Request to delete asset {0}, but type is {1} and allowed remote delete types are {2}",
98 assetID, (AssetFlags)asset.Flags, m_allowedTypes);
99 }
100 }
101 }
69 } 102 }
70 103
71 XmlSerializer xs = new XmlSerializer(typeof(bool)); 104 XmlSerializer xs = new XmlSerializer(typeof(bool));
72 return ServerUtils.SerializeResult(xs, result); 105 return ServerUtils.SerializeResult(xs, result);
73 } 106 }
74 } 107 }
75} 108} \ No newline at end of file
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs b/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs
index 87b3d2d..a006fa8 100644
--- a/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs
@@ -57,14 +57,23 @@ namespace OpenSim.Server.Handlers.Asset
57 public override byte[] Handle(string path, Stream request, 57 public override byte[] Handle(string path, Stream request,
58 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 58 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 { 59 {
60 AssetBase asset;
60 XmlSerializer xs = new XmlSerializer(typeof (AssetBase)); 61 XmlSerializer xs = new XmlSerializer(typeof (AssetBase));
61 AssetBase asset = (AssetBase) xs.Deserialize(request); 62
63 try
64 {
65 asset = (AssetBase)xs.Deserialize(request);
66 }
67 catch (XmlException)
68 {
69 httpResponse.StatusCode = (int)HttpStatusCode.BadRequest;
70 return null;
71 }
62 72
63 string[] p = SplitParams(path); 73 string[] p = SplitParams(path);
64 if (p.Length > 1) 74 if (p.Length > 1)
65 { 75 {
66 bool result = 76 bool result = m_AssetService.UpdateContent(p[1], asset.Data);
67 m_AssetService.UpdateContent(p[1], asset.Data);
68 77
69 xs = new XmlSerializer(typeof(bool)); 78 xs = new XmlSerializer(typeof(bool));
70 return ServerUtils.SerializeResult(xs, result); 79 return ServerUtils.SerializeResult(xs, result);
diff --git a/OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs b/OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs
new file mode 100644
index 0000000..427fa16
--- /dev/null
+++ b/OpenSim/Server/Handlers/Asset/Tests/AssetServerPostHandlerTests.cs
@@ -0,0 +1,110 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Net;
31using System.Text;
32using System.Xml;
33using System.Xml.Serialization;
34using Nini.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Server.Handlers.Asset;
39using OpenSim.Services.AssetService;
40using OpenSim.Services.Interfaces;
41using OpenSim.Tests.Common;
42using OpenSim.Tests.Common.Mock;
43
44namespace OpenSim.Server.Handlers.Asset.Test
45{
46 [TestFixture]
47 public class AssetServerPostHandlerTests : OpenSimTestCase
48 {
49 [Test]
50 public void TestGoodAssetStoreRequest()
51 {
52 TestHelpers.InMethod();
53
54 UUID assetId = TestHelpers.ParseTail(0x1);
55
56 IConfigSource config = new IniConfigSource();
57 config.AddConfig("AssetService");
58 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
59
60 AssetService assetService = new AssetService(config);
61
62 AssetServerPostHandler asph = new AssetServerPostHandler(assetService);
63
64 AssetBase asset = AssetHelpers.CreateNotecardAsset(assetId, "Hello World");
65
66 MemoryStream buffer = new MemoryStream();
67
68 XmlWriterSettings settings = new XmlWriterSettings();
69 settings.Encoding = Encoding.UTF8;
70
71 using (XmlWriter writer = XmlWriter.Create(buffer, settings))
72 {
73 XmlSerializer serializer = new XmlSerializer(typeof(AssetBase));
74 serializer.Serialize(writer, asset);
75 writer.Flush();
76 }
77
78 buffer.Position = 0;
79 asph.Handle(null, buffer, null, null);
80
81 AssetBase retrievedAsset = assetService.Get(assetId.ToString());
82
83 Assert.That(retrievedAsset, Is.Not.Null);
84 }
85
86 [Test]
87 public void TestBadXmlAssetStoreRequest()
88 {
89 TestHelpers.InMethod();
90
91 IConfigSource config = new IniConfigSource();
92 config.AddConfig("AssetService");
93 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
94
95 AssetService assetService = new AssetService(config);
96
97 AssetServerPostHandler asph = new AssetServerPostHandler(assetService);
98
99 MemoryStream buffer = new MemoryStream();
100 byte[] badData = new byte[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f };
101 buffer.Write(badData, 0, badData.Length);
102 buffer.Position = 0;
103
104 TestOSHttpResponse response = new TestOSHttpResponse();
105 asph.Handle(null, buffer, null, response);
106
107 Assert.That(response.StatusCode, Is.EqualTo((int)HttpStatusCode.BadRequest));
108 }
109 }
110} \ No newline at end of file
diff --git a/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs b/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs
index 393584e..8cd747e 100644
--- a/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs
@@ -137,6 +137,8 @@ namespace OpenSim.Server.Handlers.Avatar
137 if (!UUID.TryParse(request["UserID"].ToString(), out user)) 137 if (!UUID.TryParse(request["UserID"].ToString(), out user))
138 return FailureResult(); 138 return FailureResult();
139 139
140 RemoveRequestParamsNotForStorage(request);
141
140 AvatarData avatar = new AvatarData(request); 142 AvatarData avatar = new AvatarData(request);
141 if (m_AvatarService.SetAvatar(user, avatar)) 143 if (m_AvatarService.SetAvatar(user, avatar))
142 return SuccessResult(); 144 return SuccessResult();
@@ -153,11 +155,25 @@ namespace OpenSim.Server.Handlers.Avatar
153 if (!UUID.TryParse(request["UserID"].ToString(), out user)) 155 if (!UUID.TryParse(request["UserID"].ToString(), out user))
154 return FailureResult(); 156 return FailureResult();
155 157
158 RemoveRequestParamsNotForStorage(request);
159
156 if (m_AvatarService.ResetAvatar(user)) 160 if (m_AvatarService.ResetAvatar(user))
157 return SuccessResult(); 161 return SuccessResult();
158 162
159 return FailureResult(); 163 return FailureResult();
160 } 164 }
165
166 /// <summary>
167 /// Remove parameters that were used to invoke the method and should not in themselves be persisted.
168 /// </summary>
169 /// <param name='request'></param>
170 private void RemoveRequestParamsNotForStorage(Dictionary<string, object> request)
171 {
172 request.Remove("VERSIONMAX");
173 request.Remove("VERSIONMIN");
174 request.Remove("METHOD");
175 request.Remove("UserID");
176 }
161 177
162 byte[] SetItems(Dictionary<string, object> request) 178 byte[] SetItems(Dictionary<string, object> request)
163 { 179 {
@@ -173,6 +189,8 @@ namespace OpenSim.Server.Handlers.Avatar
173 if (!(request["Names"] is List<string> || request["Values"] is List<string>)) 189 if (!(request["Names"] is List<string> || request["Values"] is List<string>))
174 return FailureResult(); 190 return FailureResult();
175 191
192 RemoveRequestParamsNotForStorage(request);
193
176 List<string> _names = (List<string>)request["Names"]; 194 List<string> _names = (List<string>)request["Names"];
177 names = _names.ToArray(); 195 names = _names.ToArray();
178 List<string> _values = (List<string>)request["Values"]; 196 List<string> _values = (List<string>)request["Values"];
diff --git a/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..53e9737
--- /dev/null
+++ b/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Server.Handlers")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("6319afca-d740-4468-a95d-d7f87a081cb3")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Server/Properties/AssemblyInfo.cs b/OpenSim/Server/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ebc10fb
--- /dev/null
+++ b/OpenSim/Server/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("Robust")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("d347c5cb-baf8-4566-a221-35d948e1776f")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Server/ServerMain.cs b/OpenSim/Server/ServerMain.cs
index 21fb678..45c13fb 100644
--- a/OpenSim/Server/ServerMain.cs
+++ b/OpenSim/Server/ServerMain.cs
@@ -60,7 +60,25 @@ namespace OpenSim.Server
60 } 60 }
61 61
62 string connList = serverConfig.GetString("ServiceConnectors", String.Empty); 62 string connList = serverConfig.GetString("ServiceConnectors", String.Empty);
63 string[] conns = connList.Split(new char[] {',', ' '}); 63
64 IConfig servicesConfig = m_Server.Config.Configs["ServiceList"];
65 if (servicesConfig != null)
66 {
67 List<string> servicesList = new List<string>();
68 if (connList != String.Empty)
69 servicesList.Add(connList);
70
71 foreach (string k in servicesConfig.GetKeys())
72 {
73 string v = servicesConfig.GetString(k);
74 if (v != String.Empty)
75 servicesList.Add(v);
76 }
77
78 connList = String.Join(",", servicesList.ToArray());
79 }
80
81 string[] conns = connList.Split(new char[] {',', ' ', '\n', '\r', '\t'});
64 82
65// int i = 0; 83// int i = 0;
66 foreach (string c in conns) 84 foreach (string c in conns)
@@ -130,4 +148,4 @@ namespace OpenSim.Server
130 return 0; 148 return 0;
131 } 149 }
132 } 150 }
133} \ No newline at end of file 151}
diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs
index 96b430d..f1bffa4 100644
--- a/OpenSim/Services/AssetService/AssetService.cs
+++ b/OpenSim/Services/AssetService/AssetService.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Services.AssetService
70 70
71 if (assetLoaderEnabled) 71 if (assetLoaderEnabled)
72 { 72 {
73 m_log.DebugFormat("[ASSET]: Loading default asset set from {0}", loaderArgs); 73 m_log.DebugFormat("[ASSET SERVICE]: Loading default asset set from {0}", loaderArgs);
74 74
75 m_AssetLoader.ForEachDefaultXmlAsset( 75 m_AssetLoader.ForEachDefaultXmlAsset(
76 loaderArgs, 76 loaderArgs,
@@ -200,20 +200,7 @@ namespace OpenSim.Services.AssetService
200 if (!UUID.TryParse(id, out assetID)) 200 if (!UUID.TryParse(id, out assetID))
201 return false; 201 return false;
202 202
203 AssetBase asset = m_Database.GetAsset(assetID); 203 return m_Database.Delete(id);
204 if (asset == null)
205 return false;
206
207 if ((int)(asset.Flags & AssetFlags.Maptile) != 0)
208 {
209 return m_Database.Delete(id);
210 }
211 else
212 {
213 m_log.DebugFormat("[ASSET SERVICE]: Request to delete asset {0}, but flags are not Maptile", id);
214 }
215
216 return false;
217 } 204 }
218 } 205 }
219} \ No newline at end of file 206} \ No newline at end of file
diff --git a/OpenSim/Services/AssetService/AssetServiceBase.cs b/OpenSim/Services/AssetService/AssetServiceBase.cs
index 177c565..58ab052 100644
--- a/OpenSim/Services/AssetService/AssetServiceBase.cs
+++ b/OpenSim/Services/AssetService/AssetServiceBase.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Services.AssetService
84 84
85 m_Database = LoadPlugin<IAssetDataPlugin>(dllName); 85 m_Database = LoadPlugin<IAssetDataPlugin>(dllName);
86 if (m_Database == null) 86 if (m_Database == null)
87 throw new Exception("Could not find a storage interface in the given module"); 87 throw new Exception(string.Format("Could not find a storage interface in the module {0}", dllName));
88 88
89 m_Database.Initialise(connString); 89 m_Database.Initialise(connString);
90 90
@@ -96,7 +96,7 @@ namespace OpenSim.Services.AssetService
96 m_AssetLoader = LoadPlugin<IAssetLoader>(loaderName); 96 m_AssetLoader = LoadPlugin<IAssetLoader>(loaderName);
97 97
98 if (m_AssetLoader == null) 98 if (m_AssetLoader == null)
99 throw new Exception("Asset loader could not be loaded"); 99 throw new Exception(string.Format("Asset loader could not be loaded from {0}", loaderName));
100 } 100 }
101 } 101 }
102 } 102 }
diff --git a/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs b/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1509400
--- /dev/null
+++ b/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.AssetService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("fe57c0df-6101-4c23-ae1a-7b3e937843f9")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/AssetService/XAssetService.cs b/OpenSim/Services/AssetService/XAssetService.cs
index e62bcb5..a1d10ed 100644
--- a/OpenSim/Services/AssetService/XAssetService.cs
+++ b/OpenSim/Services/AssetService/XAssetService.cs
@@ -194,21 +194,7 @@ namespace OpenSim.Services.AssetService
194 if (!UUID.TryParse(id, out assetID)) 194 if (!UUID.TryParse(id, out assetID))
195 return false; 195 return false;
196 196
197 AssetBase asset = m_Database.GetAsset(assetID); 197 return m_Database.Delete(id);
198 if (asset == null)
199 return false;
200
201 if ((int)(asset.Flags & AssetFlags.Maptile) != 0)
202 {
203 return m_Database.Delete(id);
204 }
205 else
206 {
207 m_log.DebugFormat("[XASSET SERVICE]: Request to delete asset {0}, but flags are not Maptile", id);
208 }
209
210 return false;
211 } 198 }
212 } 199 }
213} 200} \ No newline at end of file
214
diff --git a/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..0eb2ba7
--- /dev/null
+++ b/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.AuthenticationService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("Copyright © 2012")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("74497b6f-8844-4ed4-8f0d-2caf7f42b760")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..6d6b11e
--- /dev/null
+++ b/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.AuthorizationService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("822586bb-cf25-4a2a-ac3e-59edaf147be3")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs b/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..0944149
--- /dev/null
+++ b/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.AvatarService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("0c9462ad-a5f3-46d1-ae9e-d6901fa33aa4")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/Base/Properties/AssemblyInfo.cs b/OpenSim/Services/Base/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..306b699
--- /dev/null
+++ b/OpenSim/Services/Base/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.Base")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("db9f6f73-3a56-497f-a465-4bea9cb86062")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
index 7f32ad3..4b502b7 100644
--- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
@@ -52,6 +52,8 @@ namespace OpenSim.Services.Connectors
52 private int m_retryCounter; 52 private int m_retryCounter;
53 private Dictionary<int, List<AssetBase>> m_retryQueue = new Dictionary<int, List<AssetBase>>(); 53 private Dictionary<int, List<AssetBase>> m_retryQueue = new Dictionary<int, List<AssetBase>>();
54 private System.Timers.Timer m_retryTimer; 54 private System.Timers.Timer m_retryTimer;
55 private int m_maxAssetRequestConcurrency = 30;
56
55 private delegate void AssetRetrievedEx(AssetBase asset); 57 private delegate void AssetRetrievedEx(AssetBase asset);
56 58
57 // Keeps track of concurrent requests for the same asset, so that it's only loaded once. 59 // Keeps track of concurrent requests for the same asset, so that it's only loaded once.
@@ -80,6 +82,10 @@ namespace OpenSim.Services.Connectors
80 82
81 public virtual void Initialise(IConfigSource source) 83 public virtual void Initialise(IConfigSource source)
82 { 84 {
85 IConfig netconfig = source.Configs["Network"];
86 if (netconfig != null)
87 m_maxAssetRequestConcurrency = netconfig.GetInt("MaxRequestConcurrency",m_maxAssetRequestConcurrency);
88
83 IConfig assetConfig = source.Configs["AssetService"]; 89 IConfig assetConfig = source.Configs["AssetService"];
84 if (assetConfig == null) 90 if (assetConfig == null)
85 { 91 {
@@ -204,7 +210,7 @@ namespace OpenSim.Services.Connectors
204 if (asset == null || asset.Data == null || asset.Data.Length == 0) 210 if (asset == null || asset.Data == null || asset.Data.Length == 0)
205 { 211 {
206 asset = SynchronousRestObjectRequester. 212 asset = SynchronousRestObjectRequester.
207 MakeRequest<int, AssetBase>("GET", uri, 0, 30); 213 MakeRequest<int, AssetBase>("GET", uri, 0, m_maxAssetRequestConcurrency);
208 214
209 if (m_Cache != null) 215 if (m_Cache != null)
210 m_Cache.Cache(asset); 216 m_Cache.Cache(asset);
diff --git a/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
index 6cd21d1..45f4514 100644
--- a/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
+++ b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
@@ -128,7 +128,7 @@ namespace OpenSim.Services.Connectors.Friends
128 return Call(region, sendData); 128 return Call(region, sendData);
129 } 129 }
130 130
131 public bool StatusNotify(GridRegion region, UUID userID, UUID friendID, bool online) 131 public bool StatusNotify(GridRegion region, UUID userID, string friendID, bool online)
132 { 132 {
133 Dictionary<string, object> sendData = new Dictionary<string, object>(); 133 Dictionary<string, object> sendData = new Dictionary<string, object>();
134 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); 134 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
@@ -136,7 +136,7 @@ namespace OpenSim.Services.Connectors.Friends
136 sendData["METHOD"] = "status"; 136 sendData["METHOD"] = "status";
137 137
138 sendData["FromID"] = userID.ToString(); 138 sendData["FromID"] = userID.ToString();
139 sendData["ToID"] = friendID.ToString(); 139 sendData["ToID"] = friendID;
140 sendData["Online"] = online.ToString(); 140 sendData["Online"] = online.ToString();
141 141
142 return Call(region, sendData); 142 return Call(region, sendData);
@@ -154,7 +154,7 @@ namespace OpenSim.Services.Connectors.Friends
154 if (!region.ServerURI.EndsWith("/")) 154 if (!region.ServerURI.EndsWith("/"))
155 path = "/" + path; 155 path = "/" + path;
156 string uri = region.ServerURI + path; 156 string uri = region.ServerURI + path;
157 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: calling {0}", uri); 157 // m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: calling {0}", uri);
158 158
159 try 159 try
160 { 160 {
diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs
index 20d7eaf..94bda82 100644
--- a/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs
+++ b/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs
@@ -207,7 +207,7 @@ namespace OpenSim.Services.Connectors
207 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null)) 207 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
208 { 208 {
209 if (replyData["result"] is Dictionary<string, object>) 209 if (replyData["result"] is Dictionary<string, object>)
210 guinfo = new GridUserInfo((Dictionary<string, object>)replyData["result"]); 210 guinfo = Create((Dictionary<string, object>)replyData["result"]);
211 } 211 }
212 212
213 return guinfo; 213 return guinfo;
@@ -273,7 +273,7 @@ namespace OpenSim.Services.Connectors
273 { 273 {
274 if (griduser is Dictionary<string, object>) 274 if (griduser is Dictionary<string, object>)
275 { 275 {
276 GridUserInfo pinfo = new GridUserInfo((Dictionary<string, object>)griduser); 276 GridUserInfo pinfo = Create((Dictionary<string, object>)griduser);
277 rinfos.Add(pinfo); 277 rinfos.Add(pinfo);
278 } 278 }
279 else 279 else
@@ -286,5 +286,10 @@ namespace OpenSim.Services.Connectors
286 286
287 return rinfos.ToArray(); 287 return rinfos.ToArray();
288 } 288 }
289
290 protected virtual GridUserInfo Create(Dictionary<string, object> griduser)
291 {
292 return new GridUserInfo(griduser);
293 }
289 } 294 }
290} 295}
diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
index 4cd933c..d840527 100644
--- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
@@ -321,7 +321,7 @@ namespace OpenSim.Services.Connectors.Hypergrid
321 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString()); 321 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
322 args["teleport_flags"] = OSD.FromString(flags.ToString()); 322 args["teleport_flags"] = OSD.FromString(flags.ToString());
323 323
324 OSDMap result = WebUtil.PostToService(uri, args, 20000); 324 OSDMap result = WebUtil.PostToService(uri, args, 80000);
325 if (result["Success"].AsBoolean()) 325 if (result["Success"].AsBoolean())
326 { 326 {
327 OSDMap unpacked = (OSDMap)result["_Result"]; 327 OSDMap unpacked = (OSDMap)result["_Result"];
diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs
index 7429293..7688e0f 100644
--- a/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs
@@ -153,9 +153,9 @@ namespace OpenSim.Services.Connectors
153 } 153 }
154 catch (Exception e) 154 catch (Exception e)
155 { 155 {
156 m_log.WarnFormat( 156// m_log.WarnFormat(
157 "[NEIGHBOUR SERVICE CONNCTOR]: Unable to send HelloNeighbour from {0} to {1}. Exception {2}{3}", 157// "[NEIGHBOUR SERVICE CONNCTOR]: Unable to send HelloNeighbour from {0} to {1}. Exception {2}{3}",
158 thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace); 158// thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
159 159
160 return false; 160 return false;
161 } 161 }
@@ -202,4 +202,4 @@ namespace OpenSim.Services.Connectors
202 return true; 202 return true;
203 } 203 }
204 } 204 }
205} \ No newline at end of file 205}
diff --git a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..bfb681b
--- /dev/null
+++ b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.Connectors")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("3ab0a9a1-3f45-4c07-a892-3848df8c0173")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
index 6bfc5cc..63a32e7 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
45 /// <summary> 45 /// <summary>
46 /// Connects to the SimianGrid asset service 46 /// Connects to the SimianGrid asset service
47 /// </summary> 47 /// </summary>
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianAssetServiceConnector")]
49 public class SimianAssetServiceConnector : IAssetService, ISharedRegionModule 49 public class SimianAssetServiceConnector : IAssetService, ISharedRegionModule
50 { 50 {
51 private static readonly ILog m_log = 51 private static readonly ILog m_log =
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
index ffae0da..03b19ae 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
@@ -43,7 +43,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
43 /// <summary> 43 /// <summary>
44 /// Connects authentication/authorization to the SimianGrid backend 44 /// Connects authentication/authorization to the SimianGrid backend
45 /// </summary> 45 /// </summary>
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianAuthenticationServiceConnector")]
47 public class SimianAuthenticationServiceConnector : IAuthenticationService, ISharedRegionModule 47 public class SimianAuthenticationServiceConnector : IAuthenticationService, ISharedRegionModule
48 { 48 {
49 private static readonly ILog m_log = 49 private static readonly ILog m_log =
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
index 360f0dd..841bfa0 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
47 /// <summary> 47 /// <summary>
48 /// Connects avatar appearance data to the SimianGrid backend 48 /// Connects avatar appearance data to the SimianGrid backend
49 /// </summary> 49 /// </summary>
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianAvatarServiceConnector")]
51 public class SimianAvatarServiceConnector : IAvatarService, ISharedRegionModule 51 public class SimianAvatarServiceConnector : IAvatarService, ISharedRegionModule
52 { 52 {
53 private static readonly ILog m_log = 53 private static readonly ILog m_log =
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
index 0e4d794..20eaa3a 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
@@ -112,7 +112,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
112// m_log.Warn("Registering region " + regionInfo.RegionName + " (" + regionInfo.RegionID + ") that we are not tracking"); 112// m_log.Warn("Registering region " + regionInfo.RegionName + " (" + regionInfo.RegionID + ") that we are not tracking");
113 113
114 Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0); 114 Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0);
115 Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0); 115 Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
116 116
117 OSDMap extraData = new OSDMap 117 OSDMap extraData = new OSDMap
118 { 118 {
@@ -297,7 +297,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
297 List<GridRegion> foundRegions = new List<GridRegion>(); 297 List<GridRegion> foundRegions = new List<GridRegion>();
298 298
299 Vector3d minPosition = new Vector3d(xmin, ymin, 0.0); 299 Vector3d minPosition = new Vector3d(xmin, ymin, 0.0);
300 Vector3d maxPosition = new Vector3d(xmax, ymax, 4096.0); 300 Vector3d maxPosition = new Vector3d(xmax, ymax, Constants.RegionHeight);
301 301
302 NameValueCollection requestArgs = new NameValueCollection 302 NameValueCollection requestArgs = new NameValueCollection
303 { 303 {
@@ -395,8 +395,8 @@ namespace OpenSim.Services.Connectors.SimianGrid
395 if (response["Success"].AsBoolean()) 395 if (response["Success"].AsBoolean())
396 { 396 {
397 OSDMap extraData = response["ExtraData"] as OSDMap; 397 OSDMap extraData = response["ExtraData"] as OSDMap;
398 int enabled = response["Enabled"].AsBoolean() ? (int) OpenSim.Data.RegionFlags.RegionOnline : 0; 398 int enabled = response["Enabled"].AsBoolean() ? (int)OpenSim.Framework.RegionFlags.RegionOnline : 0;
399 int hypergrid = extraData["HyperGrid"].AsBoolean() ? (int) OpenSim.Data.RegionFlags.Hyperlink : 0; 399 int hypergrid = extraData["HyperGrid"].AsBoolean() ? (int)OpenSim.Framework.RegionFlags.Hyperlink : 0;
400 int flags = enabled | hypergrid; 400 int flags = enabled | hypergrid;
401 m_log.DebugFormat("[SGGC] enabled - {0} hg - {1} flags - {2}", enabled, hypergrid, flags); 401 m_log.DebugFormat("[SGGC] enabled - {0} hg - {1} flags - {2}", enabled, hypergrid, flags);
402 return flags; 402 return flags;
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
index f828abb..a391275 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
@@ -59,7 +59,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
59 /// <summary> 59 /// <summary>
60 /// Connects avatar inventories to the SimianGrid backend 60 /// Connects avatar inventories to the SimianGrid backend
61 /// </summary> 61 /// </summary>
62 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 62 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianInventoryServiceConnector")]
63 public class SimianInventoryServiceConnector : IInventoryService, ISharedRegionModule 63 public class SimianInventoryServiceConnector : IInventoryService, ISharedRegionModule
64 { 64 {
65 private static readonly ILog m_log = 65 private static readonly ILog m_log =
@@ -781,7 +781,6 @@ namespace OpenSim.Services.Connectors.SimianGrid
781 invItem.CreationDate = item["CreationDate"].AsInteger(); 781 invItem.CreationDate = item["CreationDate"].AsInteger();
782 invItem.CreatorId = item["CreatorID"].AsString(); 782 invItem.CreatorId = item["CreatorID"].AsString();
783 invItem.CreatorData = item["CreatorData"].AsString(); 783 invItem.CreatorData = item["CreatorData"].AsString();
784 invItem.CreatorIdAsUuid = item["CreatorID"].AsUUID();
785 invItem.Description = item["Description"].AsString(); 784 invItem.Description = item["Description"].AsString();
786 invItem.Folder = item["ParentID"].AsUUID(); 785 invItem.Folder = item["ParentID"].AsUUID();
787 invItem.ID = item["ID"].AsUUID(); 786 invItem.ID = item["ID"].AsUUID();
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
index ca1b64f..854bea4 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
47 /// Connects avatar presence information (for tracking current location and 47 /// Connects avatar presence information (for tracking current location and
48 /// message routing) to the SimianGrid backend 48 /// message routing) to the SimianGrid backend
49 /// </summary> 49 /// </summary>
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianPresenceServiceConnector")]
51 public class SimianPresenceServiceConnector : IPresenceService, IGridUserService, ISharedRegionModule 51 public class SimianPresenceServiceConnector : IPresenceService, IGridUserService, ISharedRegionModule
52 { 52 {
53 private static readonly ILog m_log = 53 private static readonly ILog m_log =
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs
index 6aefc38..bd8069f 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs
@@ -59,7 +59,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
59 /// Connects avatar profile and classified queries to the SimianGrid 59 /// Connects avatar profile and classified queries to the SimianGrid
60 /// backend 60 /// backend
61 /// </summary> 61 /// </summary>
62 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 62 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianProfiles")]
63 public class SimianProfiles : INonSharedRegionModule 63 public class SimianProfiles : INonSharedRegionModule
64 { 64 {
65 private static readonly ILog m_log = 65 private static readonly ILog m_log =
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
index f38ebe8..fcb5115 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
45 /// Connects user account data (creating new users, looking up existing 45 /// Connects user account data (creating new users, looking up existing
46 /// users) to the SimianGrid backend 46 /// users) to the SimianGrid backend
47 /// </summary> 47 /// </summary>
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianUserAccountServiceConnector")]
49 public class SimianUserAccountServiceConnector : IUserAccountService, ISharedRegionModule 49 public class SimianUserAccountServiceConnector : IUserAccountService, ISharedRegionModule
50 { 50 {
51 private const double CACHE_EXPIRATION_SECONDS = 120.0; 51 private const double CACHE_EXPIRATION_SECONDS = 120.0;
diff --git a/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs b/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..58c7283
--- /dev/null
+++ b/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.FreeswitchService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("af7d2401-cfd9-4ba5-8d6c-8af629984123")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/Friends/Properties/AssemblyInfo.cs b/OpenSim/Services/Friends/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..dddb091
--- /dev/null
+++ b/OpenSim/Services/Friends/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.FriendsService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("a265d071-e152-42cc-9674-3ddd053977f5")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs
index aab403a..ee3b858 100644
--- a/OpenSim/Services/GridService/GridService.cs
+++ b/OpenSim/Services/GridService/GridService.cs
@@ -137,20 +137,25 @@ namespace OpenSim.Services.GridService
137 if (regionInfos.RegionID == UUID.Zero) 137 if (regionInfos.RegionID == UUID.Zero)
138 return "Invalid RegionID - cannot be zero UUID"; 138 return "Invalid RegionID - cannot be zero UUID";
139 139
140 // This needs better sanity testing. What if regionInfo is registering in
141 // overlapping coords?
142 RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); 140 RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
141 if ((region != null) && (region.RegionID != regionInfos.RegionID))
142 {
143 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.",
144 regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
145 return "Region overlaps another region";
146 }
147
143 if (region != null) 148 if (region != null)
144 { 149 {
145 // There is a preexisting record 150 // There is a preexisting record
146 // 151 //
147 // Get it's flags 152 // Get it's flags
148 // 153 //
149 OpenSim.Data.RegionFlags rflags = (OpenSim.Data.RegionFlags)Convert.ToInt32(region.Data["flags"]); 154 OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(region.Data["flags"]);
150 155
151 // Is this a reservation? 156 // Is this a reservation?
152 // 157 //
153 if ((rflags & OpenSim.Data.RegionFlags.Reservation) != 0) 158 if ((rflags & OpenSim.Framework.RegionFlags.Reservation) != 0)
154 { 159 {
155 // Regions reserved for the null key cannot be taken. 160 // Regions reserved for the null key cannot be taken.
156 if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString()) 161 if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString())
@@ -161,10 +166,10 @@ namespace OpenSim.Services.GridService
161 // NOTE: Fudging the flags value here, so these flags 166 // NOTE: Fudging the flags value here, so these flags
162 // should not be used elsewhere. Don't optimize 167 // should not be used elsewhere. Don't optimize
163 // this with the later retrieval of the same flags! 168 // this with the later retrieval of the same flags!
164 rflags |= OpenSim.Data.RegionFlags.Authenticate; 169 rflags |= OpenSim.Framework.RegionFlags.Authenticate;
165 } 170 }
166 171
167 if ((rflags & OpenSim.Data.RegionFlags.Authenticate) != 0) 172 if ((rflags & OpenSim.Framework.RegionFlags.Authenticate) != 0)
168 { 173 {
169 // Can we authenticate at all? 174 // Can we authenticate at all?
170 // 175 //
@@ -176,19 +181,36 @@ namespace OpenSim.Services.GridService
176 } 181 }
177 } 182 }
178 183
179 if ((region != null) && (region.RegionID != regionInfos.RegionID)) 184 // If we get here, the destination is clear. Now for the real check.
185
186 if (!m_AllowDuplicateNames)
180 { 187 {
181 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.", 188 List<RegionData> dupe = m_Database.Get(regionInfos.RegionName, scopeID);
182 regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); 189 if (dupe != null && dupe.Count > 0)
183 return "Region overlaps another region"; 190 {
191 foreach (RegionData d in dupe)
192 {
193 if (d.RegionID != regionInfos.RegionID)
194 {
195 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register duplicate name with ID {1}.",
196 regionInfos.RegionName, regionInfos.RegionID);
197 return "Duplicate region name";
198 }
199 }
200 }
184 } 201 }
185 202
203 // If there is an old record for us, delete it if it is elsewhere.
204 region = m_Database.Get(regionInfos.RegionID, scopeID);
186 if ((region != null) && (region.RegionID == regionInfos.RegionID) && 205 if ((region != null) && (region.RegionID == regionInfos.RegionID) &&
187 ((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY))) 206 ((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY)))
188 { 207 {
189 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.NoMove) != 0) 208 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.NoMove) != 0)
190 return "Can't move this region"; 209 return "Can't move this region";
191 210
211 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.LockedOut) != 0)
212 return "Region locked out";
213
192 // Region reregistering in other coordinates. Delete the old entry 214 // Region reregistering in other coordinates. Delete the old entry
193 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.", 215 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.",
194 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY); 216 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY);
@@ -203,23 +225,6 @@ namespace OpenSim.Services.GridService
203 } 225 }
204 } 226 }
205 227
206 if (!m_AllowDuplicateNames)
207 {
208 List<RegionData> dupe = m_Database.Get(regionInfos.RegionName, scopeID);
209 if (dupe != null && dupe.Count > 0)
210 {
211 foreach (RegionData d in dupe)
212 {
213 if (d.RegionID != regionInfos.RegionID)
214 {
215 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register duplicate name with ID {1}.",
216 regionInfos.RegionName, regionInfos.RegionID);
217 return "Duplicate region name";
218 }
219 }
220 }
221 }
222
223 // Everything is ok, let's register 228 // Everything is ok, let's register
224 RegionData rdata = RegionInfo2RegionData(regionInfos); 229 RegionData rdata = RegionInfo2RegionData(regionInfos);
225 rdata.ScopeID = scopeID; 230 rdata.ScopeID = scopeID;
@@ -227,10 +232,8 @@ namespace OpenSim.Services.GridService
227 if (region != null) 232 if (region != null)
228 { 233 {
229 int oldFlags = Convert.ToInt32(region.Data["flags"]); 234 int oldFlags = Convert.ToInt32(region.Data["flags"]);
230 if ((oldFlags & (int)OpenSim.Data.RegionFlags.LockedOut) != 0)
231 return "Region locked out";
232 235
233 oldFlags &= ~(int)OpenSim.Data.RegionFlags.Reservation; 236 oldFlags &= ~(int)OpenSim.Framework.RegionFlags.Reservation;
234 237
235 rdata.Data["flags"] = oldFlags.ToString(); // Preserve flags 238 rdata.Data["flags"] = oldFlags.ToString(); // Preserve flags
236 } 239 }
@@ -249,7 +252,7 @@ namespace OpenSim.Services.GridService
249 } 252 }
250 253
251 int flags = Convert.ToInt32(rdata.Data["flags"]); 254 int flags = Convert.ToInt32(rdata.Data["flags"]);
252 flags |= (int)OpenSim.Data.RegionFlags.RegionOnline; 255 flags |= (int)OpenSim.Framework.RegionFlags.RegionOnline;
253 rdata.Data["flags"] = flags.ToString(); 256 rdata.Data["flags"] = flags.ToString();
254 257
255 try 258 try
@@ -280,9 +283,9 @@ namespace OpenSim.Services.GridService
280 283
281 int flags = Convert.ToInt32(region.Data["flags"]); 284 int flags = Convert.ToInt32(region.Data["flags"]);
282 285
283 if (!m_DeleteOnUnregister || (flags & (int)OpenSim.Data.RegionFlags.Persistent) != 0) 286 if (!m_DeleteOnUnregister || (flags & (int)OpenSim.Framework.RegionFlags.Persistent) != 0)
284 { 287 {
285 flags &= ~(int)OpenSim.Data.RegionFlags.RegionOnline; 288 flags &= ~(int)OpenSim.Framework.RegionFlags.RegionOnline;
286 region.Data["flags"] = flags.ToString(); 289 region.Data["flags"] = flags.ToString();
287 region.Data["last_seen"] = Util.UnixTimeSinceEpoch(); 290 region.Data["last_seen"] = Util.UnixTimeSinceEpoch();
288 try 291 try
@@ -317,7 +320,7 @@ namespace OpenSim.Services.GridService
317 if (rdata.RegionID != regionID) 320 if (rdata.RegionID != regionID)
318 { 321 {
319 int flags = Convert.ToInt32(rdata.Data["flags"]); 322 int flags = Convert.ToInt32(rdata.Data["flags"]);
320 if ((flags & (int)Data.RegionFlags.Hyperlink) == 0) // no hyperlinks as neighbours 323 if ((flags & (int)Framework.RegionFlags.Hyperlink) == 0) // no hyperlinks as neighbours
321 rinfos.Add(RegionData2RegionInfo(rdata)); 324 rinfos.Add(RegionData2RegionInfo(rdata));
322 } 325 }
323 } 326 }
@@ -467,7 +470,7 @@ namespace OpenSim.Services.GridService
467 470
468 foreach (RegionData r in regions) 471 foreach (RegionData r in regions)
469 { 472 {
470 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0) 473 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
471 ret.Add(RegionData2RegionInfo(r)); 474 ret.Add(RegionData2RegionInfo(r));
472 } 475 }
473 476
@@ -483,7 +486,7 @@ namespace OpenSim.Services.GridService
483 486
484 foreach (RegionData r in regions) 487 foreach (RegionData r in regions)
485 { 488 {
486 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0) 489 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
487 ret.Add(RegionData2RegionInfo(r)); 490 ret.Add(RegionData2RegionInfo(r));
488 } 491 }
489 492
@@ -499,7 +502,7 @@ namespace OpenSim.Services.GridService
499 502
500 foreach (RegionData r in regions) 503 foreach (RegionData r in regions)
501 { 504 {
502 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0) 505 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
503 ret.Add(RegionData2RegionInfo(r)); 506 ret.Add(RegionData2RegionInfo(r));
504 } 507 }
505 508
@@ -626,7 +629,7 @@ namespace OpenSim.Services.GridService
626 629
627 private void OutputRegionToConsole(RegionData r) 630 private void OutputRegionToConsole(RegionData r)
628 { 631 {
629 OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]); 632 OpenSim.Framework.RegionFlags flags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(r.Data["flags"]);
630 633
631 ConsoleDisplayList dispList = new ConsoleDisplayList(); 634 ConsoleDisplayList dispList = new ConsoleDisplayList();
632 dispList.AddRow("Region Name", r.RegionName); 635 dispList.AddRow("Region Name", r.RegionName);
@@ -656,7 +659,7 @@ namespace OpenSim.Services.GridService
656 659
657 foreach (RegionData r in regions) 660 foreach (RegionData r in regions)
658 { 661 {
659 OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]); 662 OpenSim.Framework.RegionFlags flags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(r.Data["flags"]);
660 dispTable.AddRow( 663 dispTable.AddRow(
661 r.RegionName, 664 r.RegionName,
662 r.RegionID.ToString(), 665 r.RegionID.ToString(),
@@ -670,7 +673,7 @@ namespace OpenSim.Services.GridService
670 673
671 private int ParseFlags(int prev, string flags) 674 private int ParseFlags(int prev, string flags)
672 { 675 {
673 OpenSim.Data.RegionFlags f = (OpenSim.Data.RegionFlags)prev; 676 OpenSim.Framework.RegionFlags f = (OpenSim.Framework.RegionFlags)prev;
674 677
675 string[] parts = flags.Split(new char[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries); 678 string[] parts = flags.Split(new char[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries);
676 679
@@ -682,18 +685,18 @@ namespace OpenSim.Services.GridService
682 { 685 {
683 if (p.StartsWith("+")) 686 if (p.StartsWith("+"))
684 { 687 {
685 val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p.Substring(1)); 688 val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p.Substring(1));
686 f |= (OpenSim.Data.RegionFlags)val; 689 f |= (OpenSim.Framework.RegionFlags)val;
687 } 690 }
688 else if (p.StartsWith("-")) 691 else if (p.StartsWith("-"))
689 { 692 {
690 val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p.Substring(1)); 693 val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p.Substring(1));
691 f &= ~(OpenSim.Data.RegionFlags)val; 694 f &= ~(OpenSim.Framework.RegionFlags)val;
692 } 695 }
693 else 696 else
694 { 697 {
695 val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p); 698 val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p);
696 f |= (OpenSim.Data.RegionFlags)val; 699 f |= (OpenSim.Framework.RegionFlags)val;
697 } 700 }
698 } 701 }
699 catch (Exception) 702 catch (Exception)
@@ -725,7 +728,7 @@ namespace OpenSim.Services.GridService
725 int flags = Convert.ToInt32(r.Data["flags"]); 728 int flags = Convert.ToInt32(r.Data["flags"]);
726 flags = ParseFlags(flags, cmd[4]); 729 flags = ParseFlags(flags, cmd[4]);
727 r.Data["flags"] = flags.ToString(); 730 r.Data["flags"] = flags.ToString();
728 OpenSim.Data.RegionFlags f = (OpenSim.Data.RegionFlags)flags; 731 OpenSim.Framework.RegionFlags f = (OpenSim.Framework.RegionFlags)flags;
729 732
730 MainConsole.Instance.Output(String.Format("Set region {0} to {1}", r.RegionName, f)); 733 MainConsole.Instance.Output(String.Format("Set region {0} to {1}", r.RegionName, f));
731 m_Database.Store(r); 734 m_Database.Store(r);
diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs
index 78eab3d..743d089 100644
--- a/OpenSim/Services/GridService/HypergridLinker.cs
+++ b/OpenSim/Services/GridService/HypergridLinker.cs
@@ -390,8 +390,8 @@ namespace OpenSim.Services.GridService
390 List<RegionData> regions = m_Database.Get(mapName, m_ScopeID); 390 List<RegionData> regions = m_Database.Get(mapName, m_ScopeID);
391 if (regions != null && regions.Count > 0) 391 if (regions != null && regions.Count > 0)
392 { 392 {
393 OpenSim.Data.RegionFlags rflags = (OpenSim.Data.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]); 393 OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]);
394 if ((rflags & OpenSim.Data.RegionFlags.Hyperlink) != 0) 394 if ((rflags & OpenSim.Framework.RegionFlags.Hyperlink) != 0)
395 { 395 {
396 regInfo = new GridRegion(); 396 regInfo = new GridRegion();
397 regInfo.RegionID = regions[0].RegionID; 397 regInfo.RegionID = regions[0].RegionID;
@@ -460,7 +460,7 @@ namespace OpenSim.Services.GridService
460 private void AddHyperlinkRegion(GridRegion regionInfo, ulong regionHandle) 460 private void AddHyperlinkRegion(GridRegion regionInfo, ulong regionHandle)
461 { 461 {
462 RegionData rdata = m_GridService.RegionInfo2RegionData(regionInfo); 462 RegionData rdata = m_GridService.RegionInfo2RegionData(regionInfo);
463 int flags = (int)OpenSim.Data.RegionFlags.Hyperlink + (int)OpenSim.Data.RegionFlags.NoDirectLogin + (int)OpenSim.Data.RegionFlags.RegionOnline; 463 int flags = (int)OpenSim.Framework.RegionFlags.Hyperlink + (int)OpenSim.Framework.RegionFlags.NoDirectLogin + (int)OpenSim.Framework.RegionFlags.RegionOnline;
464 rdata.Data["flags"] = flags.ToString(); 464 rdata.Data["flags"] = flags.ToString();
465 465
466 m_Database.Store(rdata); 466 m_Database.Store(rdata);
diff --git a/OpenSim/Services/GridService/Properties/AssemblyInfo.cs b/OpenSim/Services/GridService/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..5c0c8f4
--- /dev/null
+++ b/OpenSim/Services/GridService/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.GridService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("96526d7b-4943-4b8e-9f0f-5908af621090")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs
index 47d22b9..7b84d55 100644
--- a/OpenSim/Services/HypergridService/GatekeeperService.cs
+++ b/OpenSim/Services/HypergridService/GatekeeperService.cs
@@ -57,14 +57,18 @@ namespace OpenSim.Services.HypergridService
57 private static IUserAccountService m_UserAccountService; 57 private static IUserAccountService m_UserAccountService;
58 private static IUserAgentService m_UserAgentService; 58 private static IUserAgentService m_UserAgentService;
59 private static ISimulationService m_SimulationService; 59 private static ISimulationService m_SimulationService;
60 private static IGridUserService m_GridUserService;
60 61
61 protected string m_AllowedClients = string.Empty; 62 private static string m_AllowedClients = string.Empty;
62 protected string m_DeniedClients = string.Empty; 63 private static string m_DeniedClients = string.Empty;
63 private static bool m_ForeignAgentsAllowed = true; 64 private static bool m_ForeignAgentsAllowed = true;
65 private static List<string> m_ForeignsAllowedExceptions = new List<string>();
66 private static List<string> m_ForeignsDisallowedExceptions = new List<string>();
64 67
65 private static UUID m_ScopeID; 68 private static UUID m_ScopeID;
66 private static bool m_AllowTeleportsToAnyRegion; 69 private static bool m_AllowTeleportsToAnyRegion;
67 private static string m_ExternalName; 70 private static string m_ExternalName;
71 private static Uri m_Uri;
68 private static GridRegion m_DefaultGatewayRegion; 72 private static GridRegion m_DefaultGatewayRegion;
69 73
70 public GatekeeperService(IConfigSource config, ISimulationService simService) 74 public GatekeeperService(IConfigSource config, ISimulationService simService)
@@ -82,8 +86,9 @@ namespace OpenSim.Services.HypergridService
82 string gridService = serverConfig.GetString("GridService", String.Empty); 86 string gridService = serverConfig.GetString("GridService", String.Empty);
83 string presenceService = serverConfig.GetString("PresenceService", String.Empty); 87 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
84 string simulationService = serverConfig.GetString("SimulationService", String.Empty); 88 string simulationService = serverConfig.GetString("SimulationService", String.Empty);
89 string gridUserService = serverConfig.GetString("GridUserService", String.Empty);
85 90
86 // These 3 are mandatory, the others aren't 91 // These are mandatory, the others aren't
87 if (gridService == string.Empty || presenceService == string.Empty) 92 if (gridService == string.Empty || presenceService == string.Empty)
88 throw new Exception("Incomplete specifications, Gatekeeper Service cannot function."); 93 throw new Exception("Incomplete specifications, Gatekeeper Service cannot function.");
89 94
@@ -95,6 +100,15 @@ namespace OpenSim.Services.HypergridService
95 if (m_ExternalName != string.Empty && !m_ExternalName.EndsWith("/")) 100 if (m_ExternalName != string.Empty && !m_ExternalName.EndsWith("/"))
96 m_ExternalName = m_ExternalName + "/"; 101 m_ExternalName = m_ExternalName + "/";
97 102
103 try
104 {
105 m_Uri = new Uri(m_ExternalName);
106 }
107 catch
108 {
109 m_log.WarnFormat("[GATEKEEPER SERVICE]: Malformed gatekeeper address {0}", m_ExternalName);
110 }
111
98 Object[] args = new Object[] { config }; 112 Object[] args = new Object[] { config };
99 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args); 113 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
100 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args); 114 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
@@ -103,6 +117,8 @@ namespace OpenSim.Services.HypergridService
103 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args); 117 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args);
104 if (homeUsersService != string.Empty) 118 if (homeUsersService != string.Empty)
105 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(homeUsersService, args); 119 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(homeUsersService, args);
120 if (gridUserService != string.Empty)
121 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args);
106 122
107 if (simService != null) 123 if (simService != null)
108 m_SimulationService = simService; 124 m_SimulationService = simService;
@@ -113,6 +129,9 @@ namespace OpenSim.Services.HypergridService
113 m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty); 129 m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty);
114 m_ForeignAgentsAllowed = serverConfig.GetBoolean("ForeignAgentsAllowed", true); 130 m_ForeignAgentsAllowed = serverConfig.GetBoolean("ForeignAgentsAllowed", true);
115 131
132 LoadDomainExceptionsFromConfig(serverConfig, "AllowExcept", m_ForeignsAllowedExceptions);
133 LoadDomainExceptionsFromConfig(serverConfig, "DisallowExcept", m_ForeignsDisallowedExceptions);
134
116 if (m_GridService == null || m_PresenceService == null || m_SimulationService == null) 135 if (m_GridService == null || m_PresenceService == null || m_SimulationService == null)
117 throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function."); 136 throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function.");
118 137
@@ -125,6 +144,15 @@ namespace OpenSim.Services.HypergridService
125 { 144 {
126 } 145 }
127 146
147 protected void LoadDomainExceptionsFromConfig(IConfig config, string variable, List<string> exceptions)
148 {
149 string value = config.GetString(variable, string.Empty);
150 string[] parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
151
152 foreach (string s in parts)
153 exceptions.Add(s.Trim());
154 }
155
128 public bool LinkRegion(string regionName, out UUID regionID, out ulong regionHandle, out string externalName, out string imageURL, out string reason) 156 public bool LinkRegion(string regionName, out UUID regionID, out ulong regionHandle, out string externalName, out string imageURL, out string reason)
129 { 157 {
130 regionID = UUID.Zero; 158 regionID = UUID.Zero;
@@ -260,17 +288,26 @@ namespace OpenSim.Services.HypergridService
260 m_log.DebugFormat("[GATEKEEPER SERVICE]: User is ok"); 288 m_log.DebugFormat("[GATEKEEPER SERVICE]: User is ok");
261 289
262 // 290 //
263 // Foreign agents allowed 291 // Foreign agents allowed? Exceptions?
264 // 292 //
265 if (account == null && !m_ForeignAgentsAllowed) 293 if (account == null)
266 { 294 {
267 reason = "Unauthorized"; 295 bool allowed = m_ForeignAgentsAllowed;
268 m_log.InfoFormat("[GATEKEEPER SERVICE]: Foreign agents are not permitted {0} {1}. Refusing service.",
269 aCircuit.firstname, aCircuit.lastname);
270 return false;
271 }
272 296
273 // May want to authorize 297 if (m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsAllowedExceptions))
298 allowed = false;
299
300 if (!m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsDisallowedExceptions))
301 allowed = true;
302
303 if (!allowed)
304 {
305 reason = "Destination does not allow visitors from your world";
306 m_log.InfoFormat("[GATEKEEPER SERVICE]: Foreign agents are not permitted {0} {1} @ {2}. Refusing service.",
307 aCircuit.firstname, aCircuit.lastname, aCircuit.ServiceURLs["HomeURI"]);
308 return false;
309 }
310 }
274 311
275 bool isFirstLogin = false; 312 bool isFirstLogin = false;
276 // 313 //
@@ -280,7 +317,8 @@ namespace OpenSim.Services.HypergridService
280 if (presence != null) // it has been placed there by the login service 317 if (presence != null) // it has been placed there by the login service
281 isFirstLogin = true; 318 isFirstLogin = true;
282 319
283 else 320 else
321 {
284 if (!m_PresenceService.LoginAgent(aCircuit.AgentID.ToString(), aCircuit.SessionID, aCircuit.SecureSessionID)) 322 if (!m_PresenceService.LoginAgent(aCircuit.AgentID.ToString(), aCircuit.SessionID, aCircuit.SecureSessionID))
285 { 323 {
286 reason = "Unable to login presence"; 324 reason = "Unable to login presence";
@@ -290,6 +328,26 @@ namespace OpenSim.Services.HypergridService
290 } 328 }
291 m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence ok"); 329 m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence ok");
292 330
331 // Also login foreigners with GridUser service
332 if (m_GridUserService != null && account == null)
333 {
334 string userId = aCircuit.AgentID.ToString();
335 string first = aCircuit.firstname, last = aCircuit.lastname;
336 if (last.StartsWith("@"))
337 {
338 string[] parts = aCircuit.firstname.Split('.');
339 if (parts.Length >= 2)
340 {
341 first = parts[0];
342 last = parts[1];
343 }
344 }
345
346 userId += ";" + aCircuit.ServiceURLs["HomeURI"] + ";" + first + " " + last;
347 m_GridUserService.LoggedIn(userId);
348 }
349 }
350
293 // 351 //
294 // Get the region 352 // Get the region
295 // 353 //
@@ -385,7 +443,18 @@ namespace OpenSim.Services.HypergridService
385 string externalname = m_ExternalName.TrimEnd(trailing_slash); 443 string externalname = m_ExternalName.TrimEnd(trailing_slash);
386 m_log.DebugFormat("[GATEKEEPER SERVICE]: Verifying {0} against {1}", addressee, externalname); 444 m_log.DebugFormat("[GATEKEEPER SERVICE]: Verifying {0} against {1}", addressee, externalname);
387 445
388 return string.Equals(addressee, externalname, StringComparison.OrdinalIgnoreCase); 446 Uri uri;
447 try
448 {
449 uri = new Uri(addressee);
450 }
451 catch
452 {
453 m_log.DebugFormat("[GATEKEEPER SERVICE]: Visitor provided malformed service address {0}", addressee);
454 return false;
455 }
456
457 return string.Equals(uri.GetLeftPart(UriPartial.Authority), m_Uri.GetLeftPart(UriPartial.Authority), StringComparison.OrdinalIgnoreCase) ;
389 } 458 }
390 459
391 #endregion 460 #endregion
@@ -393,6 +462,27 @@ namespace OpenSim.Services.HypergridService
393 462
394 #region Misc 463 #region Misc
395 464
465 private bool IsException(AgentCircuitData aCircuit, List<string> exceptions)
466 {
467 bool exception = false;
468 if (exceptions.Count > 0) // we have exceptions
469 {
470 // Retrieve the visitor's origin
471 string userURL = aCircuit.ServiceURLs["HomeURI"].ToString();
472 if (!userURL.EndsWith("/"))
473 userURL += "/";
474
475 if (exceptions.Find(delegate(string s)
476 {
477 if (!s.EndsWith("/"))
478 s += "/";
479 return s == userURL;
480 }) != null)
481 exception = true;
482 }
483
484 return exception;
485 }
396 486
397 #endregion 487 #endregion
398 } 488 }
diff --git a/OpenSim/Services/HypergridService/HGAssetService.cs b/OpenSim/Services/HypergridService/HGAssetService.cs
index db98166..84dec8d 100644
--- a/OpenSim/Services/HypergridService/HGAssetService.cs
+++ b/OpenSim/Services/HypergridService/HGAssetService.cs
@@ -58,6 +58,8 @@ namespace OpenSim.Services.HypergridService
58 58
59 private UserAccountCache m_Cache; 59 private UserAccountCache m_Cache;
60 60
61 private AssetPermissions m_AssetPerms;
62
61 public HGAssetService(IConfigSource config, string configName) : base(config, configName) 63 public HGAssetService(IConfigSource config, string configName) : base(config, configName)
62 { 64 {
63 m_log.Debug("[HGAsset Service]: Starting"); 65 m_log.Debug("[HGAsset Service]: Starting");
@@ -80,6 +82,10 @@ namespace OpenSim.Services.HypergridService
80 m_HomeURL = assetConfig.GetString("HomeURI", m_HomeURL); 82 m_HomeURL = assetConfig.GetString("HomeURI", m_HomeURL);
81 83
82 m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); 84 m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService);
85
86 // Permissions
87 m_AssetPerms = new AssetPermissions(assetConfig);
88
83 } 89 }
84 90
85 #region IAssetService overrides 91 #region IAssetService overrides
@@ -90,6 +96,9 @@ namespace OpenSim.Services.HypergridService
90 if (asset == null) 96 if (asset == null)
91 return null; 97 return null;
92 98
99 if (!m_AssetPerms.AllowedExport(asset.Type))
100 return null;
101
93 if (asset.Metadata.Type == (sbyte)AssetType.Object) 102 if (asset.Metadata.Type == (sbyte)AssetType.Object)
94 asset.Data = AdjustIdentifiers(asset.Data); ; 103 asset.Data = AdjustIdentifiers(asset.Data); ;
95 104
@@ -112,16 +121,27 @@ namespace OpenSim.Services.HypergridService
112 121
113 public override byte[] GetData(string id) 122 public override byte[] GetData(string id)
114 { 123 {
115 byte[] data = base.GetData(id); 124 AssetBase asset = Get(id);
125
126 if (asset == null)
127 return null;
116 128
117 if (data == null) 129 if (!m_AssetPerms.AllowedExport(asset.Type))
118 return null; 130 return null;
119 131
120 return AdjustIdentifiers(data); 132 return asset.Data;
121 } 133 }
122 134
123 //public virtual bool Get(string id, Object sender, AssetRetrieved handler) 135 //public virtual bool Get(string id, Object sender, AssetRetrieved handler)
124 136
137 public override string Store(AssetBase asset)
138 {
139 if (!m_AssetPerms.AllowedImport(asset.Type))
140 return string.Empty;
141
142 return base.Store(asset);
143 }
144
125 public override bool Delete(string id) 145 public override bool Delete(string id)
126 { 146 {
127 // NOGO 147 // NOGO
diff --git a/OpenSim/Services/HypergridService/HGFriendsService.cs b/OpenSim/Services/HypergridService/HGFriendsService.cs
index 98423d7..a8bcfb2 100644
--- a/OpenSim/Services/HypergridService/HGFriendsService.cs
+++ b/OpenSim/Services/HypergridService/HGFriendsService.cs
@@ -397,7 +397,7 @@ namespace OpenSim.Services.HypergridService
397 if (region != null) 397 if (region != null)
398 { 398 {
399 m_log.DebugFormat("[HGFRIENDS SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline")); 399 m_log.DebugFormat("[HGFRIENDS SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline"));
400 m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID, online); 400 m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID.ToString(), online);
401 } 401 }
402 } 402 }
403 } 403 }
diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
index 6e4b68c..784f136 100644
--- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
+++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
@@ -56,10 +56,12 @@ namespace OpenSim.Services.HypergridService
56 56
57 private string m_HomeURL; 57 private string m_HomeURL;
58 private IUserAccountService m_UserAccountService; 58 private IUserAccountService m_UserAccountService;
59 private IAvatarService m_AvatarService;
59 60
60// private UserAccountCache m_Cache; 61// private UserAccountCache m_Cache;
61 62
62 private ExpiringCache<UUID, List<XInventoryFolder>> m_SuitcaseTrees = new ExpiringCache<UUID, List<XInventoryFolder>>(); 63 private ExpiringCache<UUID, List<XInventoryFolder>> m_SuitcaseTrees = new ExpiringCache<UUID, List<XInventoryFolder>>();
64 private ExpiringCache<UUID, AvatarAppearance> m_Appearances = new ExpiringCache<UUID, AvatarAppearance>();
63 65
64 public HGSuitcaseInventoryService(IConfigSource config, string configName) 66 public HGSuitcaseInventoryService(IConfigSource config, string configName)
65 : base(config, configName) 67 : base(config, configName)
@@ -69,7 +71,7 @@ namespace OpenSim.Services.HypergridService
69 m_ConfigName = configName; 71 m_ConfigName = configName;
70 72
71 if (m_Database == null) 73 if (m_Database == null)
72 m_log.WarnFormat("[XXX]: m_Database is null!"); 74 m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: m_Database is null!");
73 75
74 // 76 //
75 // Try reading the [InventoryService] section, if it exists 77 // Try reading the [InventoryService] section, if it exists
@@ -77,7 +79,6 @@ namespace OpenSim.Services.HypergridService
77 IConfig invConfig = config.Configs[m_ConfigName]; 79 IConfig invConfig = config.Configs[m_ConfigName];
78 if (invConfig != null) 80 if (invConfig != null)
79 { 81 {
80 // realm = authConfig.GetString("Realm", realm);
81 string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty); 82 string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty);
82 if (userAccountsDll == string.Empty) 83 if (userAccountsDll == string.Empty)
83 throw new Exception("Please specify UserAccountsService in HGInventoryService configuration"); 84 throw new Exception("Please specify UserAccountsService in HGInventoryService configuration");
@@ -87,8 +88,14 @@ namespace OpenSim.Services.HypergridService
87 if (m_UserAccountService == null) 88 if (m_UserAccountService == null)
88 throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); 89 throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll));
89 90
90 // legacy configuration [obsolete] 91 string avatarDll = invConfig.GetString("AvatarService", string.Empty);
91 m_HomeURL = invConfig.GetString("ProfileServerURI", string.Empty); 92 if (avatarDll == string.Empty)
93 throw new Exception("Please specify AvatarService in HGInventoryService configuration");
94
95 m_AvatarService = ServerUtils.LoadPlugin<IAvatarService>(avatarDll, args);
96 if (m_AvatarService == null)
97 throw new Exception(String.Format("Unable to create m_AvatarService from {0}", avatarDll));
98
92 // Preferred 99 // Preferred
93 m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL); 100 m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL);
94 101
@@ -294,7 +301,7 @@ namespace OpenSim.Services.HypergridService
294 301
295 public override bool AddFolder(InventoryFolderBase folder) 302 public override bool AddFolder(InventoryFolderBase folder)
296 { 303 {
297 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID); 304 //m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID);
298 // Let's do a bit of sanity checking, more than the base service does 305 // Let's do a bit of sanity checking, more than the base service does
299 // make sure the given folder's parent folder exists under the suitcase tree of this user 306 // make sure the given folder's parent folder exists under the suitcase tree of this user
300 307
@@ -316,7 +323,7 @@ namespace OpenSim.Services.HypergridService
316 323
317 public override bool UpdateFolder(InventoryFolderBase folder) 324 public override bool UpdateFolder(InventoryFolderBase folder)
318 { 325 {
319 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version); 326 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version);
320 if (!IsWithinSuitcaseTree(folder.Owner, folder.ID)) 327 if (!IsWithinSuitcaseTree(folder.Owner, folder.ID))
321 { 328 {
322 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name); 329 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name);
@@ -394,7 +401,7 @@ namespace OpenSim.Services.HypergridService
394 return null; 401 return null;
395 } 402 }
396 403
397 if (!IsWithinSuitcaseTree(it.Owner, it.Folder)) 404 if (!IsWithinSuitcaseTree(it.Owner, it.Folder) && !IsPartOfAppearance(it.Owner, it.ID))
398 { 405 {
399 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase", 406 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase",
400 it.Name, it.Folder); 407 it.Name, it.Folder);
@@ -453,6 +460,15 @@ namespace OpenSim.Services.HypergridService
453 460
454 if (folders != null && folders.Length > 0) 461 if (folders != null && folders.Length > 0)
455 return folders[0]; 462 return folders[0];
463
464 // OK, so the RootFolder type didn't work. Let's look for any type with parent UUID.Zero.
465 folders = m_Database.GetFolders(
466 new string[] { "agentID", "folderName", "parentFolderID" },
467 new string[] { principalID.ToString(), "My Inventory", UUID.Zero.ToString() });
468
469 if (folders != null && folders.Length > 0)
470 return folders[0];
471
456 return null; 472 return null;
457 } 473 }
458 474
@@ -549,6 +565,52 @@ namespace OpenSim.Services.HypergridService
549 else return true; 565 else return true;
550 } 566 }
551 #endregion 567 #endregion
568
569 #region Avatar Appearance
570
571 private AvatarAppearance GetAppearance(UUID principalID)
572 {
573 AvatarAppearance a = null;
574 if (m_Appearances.TryGetValue(principalID, out a))
575 return a;
576
577 a = m_AvatarService.GetAppearance(principalID);
578 m_Appearances.AddOrUpdate(principalID, a, 5 * 60); // 5minutes
579 return a;
580 }
581
582 private bool IsPartOfAppearance(UUID principalID, UUID itemID)
583 {
584 AvatarAppearance a = GetAppearance(principalID);
585
586 if (a == null)
587 return false;
588
589 // Check wearables (body parts and clothes)
590 for (int i = 0; i < a.Wearables.Length; i++)
591 {
592 for (int j = 0; j < a.Wearables[i].Count; j++)
593 {
594 if (a.Wearables[i][j].ItemID == itemID)
595 {
596 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: item {0} is a wearable", itemID);
597 return true;
598 }
599 }
600 }
601
602 // Check attachments
603 if (a.GetAttachmentForItem(itemID) != null)
604 {
605 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: item {0} is an attachment", itemID);
606 return true;
607 }
608
609 return false;
610 }
611
612 #endregion
613
552 } 614 }
553 615
554} 616}
diff --git a/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs b/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..49f2176
--- /dev/null
+++ b/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.HypergridService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("8584f3c1-26dd-4d95-86f4-cd8f0110a18f")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
index a49993c..416ad16 100644
--- a/OpenSim/Services/HypergridService/UserAgentService.cs
+++ b/OpenSim/Services/HypergridService/UserAgentService.cs
@@ -77,6 +77,10 @@ namespace OpenSim.Services.HypergridService
77 77
78 protected static bool m_BypassClientVerification; 78 protected static bool m_BypassClientVerification;
79 79
80 private static Dictionary<int, bool> m_ForeignTripsAllowed = new Dictionary<int, bool>();
81 private static Dictionary<int, List<string>> m_TripsAllowedExceptions = new Dictionary<int, List<string>>();
82 private static Dictionary<int, List<string>> m_TripsDisallowedExceptions = new Dictionary<int, List<string>>();
83
80 public UserAgentService(IConfigSource config) : this(config, null) 84 public UserAgentService(IConfigSource config) : this(config, null)
81 { 85 {
82 } 86 }
@@ -121,6 +125,12 @@ namespace OpenSim.Services.HypergridService
121 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args); 125 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
122 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(userAccountService, args); 126 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(userAccountService, args);
123 127
128 m_LevelOutsideContacts = serverConfig.GetInt("LevelOutsideContacts", 0);
129
130 LoadTripPermissionsFromConfig(serverConfig, "ForeignTripsAllowed");
131 LoadDomainExceptionsFromConfig(serverConfig, "AllowExcept", m_TripsAllowedExceptions);
132 LoadDomainExceptionsFromConfig(serverConfig, "DisallowExcept", m_TripsDisallowedExceptions);
133
124 m_GridName = serverConfig.GetString("ExternalName", string.Empty); 134 m_GridName = serverConfig.GetString("ExternalName", string.Empty);
125 if (m_GridName == string.Empty) 135 if (m_GridName == string.Empty)
126 { 136 {
@@ -130,10 +140,43 @@ namespace OpenSim.Services.HypergridService
130 if (!m_GridName.EndsWith("/")) 140 if (!m_GridName.EndsWith("/"))
131 m_GridName = m_GridName + "/"; 141 m_GridName = m_GridName + "/";
132 142
133 m_LevelOutsideContacts = serverConfig.GetInt("LevelOutsideContacts", 0);
134 } 143 }
135 } 144 }
136 145
146 protected void LoadTripPermissionsFromConfig(IConfig config, string variable)
147 {
148 foreach (string keyName in config.GetKeys())
149 {
150 if (keyName.StartsWith(variable + "_Level_"))
151 {
152 int level = 0;
153 if (Int32.TryParse(keyName.Replace(variable + "_Level_", ""), out level))
154 m_ForeignTripsAllowed.Add(level, config.GetBoolean(keyName, true));
155 }
156 }
157 }
158
159 protected void LoadDomainExceptionsFromConfig(IConfig config, string variable, Dictionary<int, List<string>> exceptions)
160 {
161 foreach (string keyName in config.GetKeys())
162 {
163 if (keyName.StartsWith(variable + "_Level_"))
164 {
165 int level = 0;
166 if (Int32.TryParse(keyName.Replace(variable + "_Level_", ""), out level) && !exceptions.ContainsKey(level))
167 {
168 exceptions.Add(level, new List<string>());
169 string value = config.GetString(keyName, string.Empty);
170 string[] parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
171
172 foreach (string s in parts)
173 exceptions[level].Add(s.Trim());
174 }
175 }
176 }
177 }
178
179
137 public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt) 180 public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt)
138 { 181 {
139 position = new Vector3(128, 128, 0); lookAt = Vector3.UnitY; 182 position = new Vector3(128, 128, 0); lookAt = Vector3.UnitY;
@@ -166,13 +209,39 @@ namespace OpenSim.Services.HypergridService
166 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", 209 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}",
167 agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI); 210 agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI);
168 211
169 if (m_UserAccountService.GetUserAccount(UUID.Zero, agentCircuit.AgentID) == null) 212 string gridName = gatekeeper.ServerURI;
213
214 UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, agentCircuit.AgentID);
215 if (account == null)
170 { 216 {
171 m_log.WarnFormat("[USER AGENT SERVICE]: Someone attempted to lauch a foreign user from here {0} {1}", agentCircuit.firstname, agentCircuit.lastname); 217 m_log.WarnFormat("[USER AGENT SERVICE]: Someone attempted to lauch a foreign user from here {0} {1}", agentCircuit.firstname, agentCircuit.lastname);
172 reason = "Forbidden to launch your agents from here"; 218 reason = "Forbidden to launch your agents from here";
173 return false; 219 return false;
174 } 220 }
175 221
222 // Is this user allowed to go there?
223 if (m_GridName != gridName)
224 {
225 if (m_ForeignTripsAllowed.ContainsKey(account.UserLevel))
226 {
227 bool allowed = m_ForeignTripsAllowed[account.UserLevel];
228
229 if (m_ForeignTripsAllowed[account.UserLevel] && IsException(gridName, account.UserLevel, m_TripsAllowedExceptions))
230 allowed = false;
231
232 if (!m_ForeignTripsAllowed[account.UserLevel] && IsException(gridName, account.UserLevel, m_TripsDisallowedExceptions))
233 allowed = true;
234
235 if (!allowed)
236 {
237 reason = "Your world does not allow you to visit the destination";
238 m_log.InfoFormat("[USER AGENT SERVICE]: Agents not permitted to visit {0}. Refusing service.", gridName);
239 return false;
240 }
241 }
242 }
243
244
176 // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination 245 // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination
177 GridRegion region = new GridRegion(gatekeeper); 246 GridRegion region = new GridRegion(gatekeeper);
178 region.ServerURI = gatekeeper.ServerURI; 247 region.ServerURI = gatekeeper.ServerURI;
@@ -189,7 +258,6 @@ namespace OpenSim.Services.HypergridService
189 258
190 bool success = false; 259 bool success = false;
191 string myExternalIP = string.Empty; 260 string myExternalIP = string.Empty;
192 string gridName = gatekeeper.ServerURI;
193 261
194 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); 262 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName);
195 263
@@ -434,7 +502,7 @@ namespace OpenSim.Services.HypergridService
434 if (region != null) 502 if (region != null)
435 { 503 {
436 m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline")); 504 m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline"));
437 m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID, online); 505 m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID.ToString(), online);
438 } 506 }
439 } 507 }
440 } 508 }
@@ -586,6 +654,35 @@ namespace OpenSim.Services.HypergridService
586 else 654 else
587 return UUID.Zero; 655 return UUID.Zero;
588 } 656 }
657
658 #region Misc
659
660 private bool IsException(string dest, int level, Dictionary<int, List<string>> exceptions)
661 {
662 if (!exceptions.ContainsKey(level))
663 return false;
664
665 bool exception = false;
666 if (exceptions[level].Count > 0) // we have exceptions
667 {
668 string destination = dest;
669 if (!destination.EndsWith("/"))
670 destination += "/";
671
672 if (exceptions[level].Find(delegate(string s)
673 {
674 if (!s.EndsWith("/"))
675 s += "/";
676 return s == destination;
677 }) != null)
678 exception = true;
679 }
680
681 return exception;
682 }
683
684 #endregion
685
589 } 686 }
590 687
591 class TravelingAgentInfo 688 class TravelingAgentInfo
diff --git a/OpenSim/Services/Interfaces/IAssetService.cs b/OpenSim/Services/Interfaces/IAssetService.cs
index 80494f1..3c469c6 100644
--- a/OpenSim/Services/Interfaces/IAssetService.cs
+++ b/OpenSim/Services/Interfaces/IAssetService.cs
@@ -68,7 +68,11 @@ namespace OpenSim.Services.Interfaces
68 /// </summary> 68 /// </summary>
69 /// <param name="id">The asset id</param> 69 /// <param name="id">The asset id</param>
70 /// <param name="sender">Represents the requester. Passed back via the handler</param> 70 /// <param name="sender">Represents the requester. Passed back via the handler</param>
71 /// <param name="handler">The handler to call back once the asset has been retrieved</param> 71 /// <param name="handler">
72 /// The handler to call back once the asset has been retrieved. This will be called back with a null AssetBase
73 /// if the asset could not be found for some reason (e.g. if it does not exist, if a remote asset service
74 /// was not contactable, if it is not in the database, etc.).
75 /// </param>
72 /// <returns>True if the id was parseable, false otherwise</returns> 76 /// <returns>True if the id was parseable, false otherwise</returns>
73 bool Get(string id, Object sender, AssetRetrieved handler); 77 bool Get(string id, Object sender, AssetRetrieved handler);
74 78
diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs
index cdcb961..3f4c958 100644
--- a/OpenSim/Services/Interfaces/IGridService.cs
+++ b/OpenSim/Services/Interfaces/IGridService.cs
@@ -100,6 +100,19 @@ namespace OpenSim.Services.Interfaces
100 List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y); 100 List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y);
101 List<GridRegion> GetHyperlinks(UUID scopeID); 101 List<GridRegion> GetHyperlinks(UUID scopeID);
102 102
103 /// <summary>
104 /// Get internal OpenSimulator region flags.
105 /// </summary>
106 /// <remarks>
107 /// See OpenSimulator.Framework.RegionFlags. These are not returned in the GridRegion structure -
108 /// they currently need to be requested separately. Possibly this should change to avoid multiple service calls
109 /// in some situations.
110 /// </remarks>
111 /// <returns>
112 /// The region flags.
113 /// </returns>
114 /// <param name='scopeID'></param>
115 /// <param name='regionID'></param>
103 int GetRegionFlags(UUID scopeID, UUID regionID); 116 int GetRegionFlags(UUID scopeID, UUID regionID);
104 } 117 }
105 118
diff --git a/OpenSim/Services/Interfaces/IGridUserService.cs b/OpenSim/Services/Interfaces/IGridUserService.cs
index 0a52bfa..2e7237e 100644
--- a/OpenSim/Services/Interfaces/IGridUserService.cs
+++ b/OpenSim/Services/Interfaces/IGridUserService.cs
@@ -80,7 +80,7 @@ namespace OpenSim.Services.Interfaces
80 80
81 } 81 }
82 82
83 public Dictionary<string, object> ToKeyValuePairs() 83 public virtual Dictionary<string, object> ToKeyValuePairs()
84 { 84 {
85 Dictionary<string, object> result = new Dictionary<string, object>(); 85 Dictionary<string, object> result = new Dictionary<string, object>();
86 result["UserID"] = UserID; 86 result["UserID"] = UserID;
@@ -96,7 +96,6 @@ namespace OpenSim.Services.Interfaces
96 result["Online"] = Online.ToString(); 96 result["Online"] = Online.ToString();
97 result["Login"] = Login.ToString(); 97 result["Login"] = Login.ToString();
98 result["Logout"] = Logout.ToString(); 98 result["Logout"] = Logout.ToString();
99
100 99
101 return result; 100 return result;
102 } 101 }
diff --git a/OpenSim/Services/Interfaces/IPresenceService.cs b/OpenSim/Services/Interfaces/IPresenceService.cs
index 8d583ff..90f9842 100644
--- a/OpenSim/Services/Interfaces/IPresenceService.cs
+++ b/OpenSim/Services/Interfaces/IPresenceService.cs
@@ -61,13 +61,49 @@ namespace OpenSim.Services.Interfaces
61 61
62 public interface IPresenceService 62 public interface IPresenceService
63 { 63 {
64 /// <summary>
65 /// Store session information.
66 /// </summary>
67 /// <returns>/returns>
68 /// <param name='userID'></param>
69 /// <param name='sessionID'></param>
70 /// <param name='secureSessionID'></param>
64 bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID); 71 bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID);
72
73 /// <summary>
74 /// Remove session information.
75 /// </summary>
76 /// <returns></returns>
77 /// <param name='sessionID'></param>
65 bool LogoutAgent(UUID sessionID); 78 bool LogoutAgent(UUID sessionID);
79
80 /// <summary>
81 /// Remove session information for all agents in the given region.
82 /// </summary>
83 /// <returns></returns>
84 /// <param name='regionID'></param>
66 bool LogoutRegionAgents(UUID regionID); 85 bool LogoutRegionAgents(UUID regionID);
67 86
87 /// <summary>
88 /// Update data for an existing session.
89 /// </summary>
90 /// <returns></returns>
91 /// <param name='sessionID'></param>
92 /// <param name='regionID'></param>
68 bool ReportAgent(UUID sessionID, UUID regionID); 93 bool ReportAgent(UUID sessionID, UUID regionID);
69 94
95 /// <summary>
96 /// Get session information for a given session ID.
97 /// </summary>
98 /// <returns></returns>
99 /// <param name='sessionID'></param>
70 PresenceInfo GetAgent(UUID sessionID); 100 PresenceInfo GetAgent(UUID sessionID);
101
102 /// <summary>
103 /// Get session information for a collection of users.
104 /// </summary>
105 /// <returns>Session information for the users.</returns>
106 /// <param name='userIDs'></param>
71 PresenceInfo[] GetAgents(string[] userIDs); 107 PresenceInfo[] GetAgents(string[] userIDs);
72 } 108 }
73} 109} \ No newline at end of file
diff --git a/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs b/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..4723553
--- /dev/null
+++ b/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.Interfaces")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("39091de1-1c4c-4ebe-bb01-31551ec1749d")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/InventoryService/InventoryService.cs b/OpenSim/Services/InventoryService/InventoryService.cs
deleted file mode 100644
index 73dd06a..0000000
--- a/OpenSim/Services/InventoryService/InventoryService.cs
+++ /dev/null
@@ -1,700 +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.Reflection;
31using log4net;
32using Nini.Config;
33using OpenMetaverse;
34using OpenSim.Data;
35using OpenSim.Framework;
36using OpenSim.Services.Interfaces;
37
38namespace OpenSim.Services.InventoryService
39{
40 /// <summary>
41 /// The Inventory service reference implementation
42 /// </summary>
43 public class InventoryService : InventoryServiceBase, IInventoryService
44 {
45 private static readonly ILog m_log
46 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 public InventoryService(IConfigSource config) : base(config)
49 {
50 m_log.Debug("[INVENTORY SERVICE]: Initialized.");
51 }
52
53 #region IInventoryServices methods
54
55 public string Host
56 {
57 get { return "default"; }
58 }
59
60 public List<InventoryFolderBase> GetInventorySkeleton(UUID userId)
61 {
62 m_log.DebugFormat("[INVENTORY SERVICE]: Getting inventory skeleton for {0}", userId);
63
64 InventoryFolderBase rootFolder = GetRootFolder(userId);
65
66 // Agent has no inventory structure yet.
67 if (null == rootFolder)
68 {
69 m_log.DebugFormat("[INVENTORY SERVICE]: No root folder");
70 return null;
71 }
72
73 List<InventoryFolderBase> userFolders = new List<InventoryFolderBase>();
74
75 userFolders.Add(rootFolder);
76
77 IList<InventoryFolderBase> folders = m_Database.getFolderHierarchy(rootFolder.ID);
78 userFolders.AddRange(folders);
79
80// m_log.DebugFormat("[INVENTORY SERVICE]: Got folder {0} {1}", folder.name, folder.folderID);
81
82 return userFolders;
83 }
84
85 public virtual bool HasInventoryForUser(UUID userID)
86 {
87 return false;
88 }
89
90 // See IInventoryServices
91 public virtual InventoryFolderBase GetRootFolder(UUID userID)
92 {
93 //m_log.DebugFormat("[INVENTORY SERVICE]: Getting root folder for {0}", userID);
94
95 // Retrieve the first root folder we get from the DB.
96 InventoryFolderBase rootFolder = m_Database.getUserRootFolder(userID);
97 if (rootFolder != null)
98 return rootFolder;
99
100 // Return nothing if the plugin was unable to supply a root folder
101 return null;
102 }
103
104 // See IInventoryServices
105 public bool CreateUserInventory(UUID user)
106 {
107 InventoryFolderBase existingRootFolder;
108 try
109 {
110 existingRootFolder = GetRootFolder(user);
111 }
112 catch /*(Exception e)*/
113 {
114 // Munch the exception, it has already been reported
115 //
116 return false;
117 }
118
119 if (null != existingRootFolder)
120 {
121 m_log.WarnFormat(
122 "[INVENTORY SERVICE]: Did not create a new inventory for user {0} since they already have "
123 + "a root inventory folder with id {1}",
124 user, existingRootFolder.ID);
125 }
126 else
127 {
128 UsersInventory inven = new UsersInventory();
129 inven.CreateNewInventorySet(user);
130 AddNewInventorySet(inven);
131
132 return true;
133 }
134
135 return false;
136 }
137
138 // See IInventoryServices
139
140 /// <summary>
141 /// Return a user's entire inventory synchronously
142 /// </summary>
143 /// <param name="rawUserID"></param>
144 /// <returns>The user's inventory. If an inventory cannot be found then an empty collection is returned.</returns>
145 public InventoryCollection GetUserInventory(UUID userID)
146 {
147 m_log.InfoFormat("[INVENTORY SERVICE]: Processing request for inventory of {0}", userID);
148
149 // Uncomment me to simulate a slow responding inventory server
150 //Thread.Sleep(16000);
151
152 InventoryCollection invCollection = new InventoryCollection();
153
154 List<InventoryFolderBase> allFolders = GetInventorySkeleton(userID);
155
156 if (null == allFolders)
157 {
158 m_log.WarnFormat("[INVENTORY SERVICE]: No inventory found for user {0}", userID);
159
160 return invCollection;
161 }
162
163 List<InventoryItemBase> allItems = new List<InventoryItemBase>();
164
165 foreach (InventoryFolderBase folder in allFolders)
166 {
167 List<InventoryItemBase> items = GetFolderItems(userID, folder.ID);
168
169 if (items != null)
170 {
171 allItems.InsertRange(0, items);
172 }
173 }
174
175 invCollection.UserID = userID;
176 invCollection.Folders = allFolders;
177 invCollection.Items = allItems;
178
179 // foreach (InventoryFolderBase folder in invCollection.Folders)
180 // {
181 // m_log.DebugFormat("[GRID INVENTORY SERVICE]: Sending back folder {0} {1}", folder.Name, folder.ID);
182 // }
183 //
184 // foreach (InventoryItemBase item in invCollection.Items)
185 // {
186 // m_log.DebugFormat("[GRID INVENTORY SERVICE]: Sending back item {0} {1}, folder {2}", item.Name, item.ID, item.Folder);
187 // }
188
189 m_log.InfoFormat(
190 "[INVENTORY SERVICE]: Sending back inventory response to user {0} containing {1} folders and {2} items",
191 invCollection.UserID, invCollection.Folders.Count, invCollection.Items.Count);
192
193 return invCollection;
194 }
195
196 /// <summary>
197 /// Asynchronous inventory fetch.
198 /// </summary>
199 /// <param name="userID"></param>
200 /// <param name="callback"></param>
201 public void GetUserInventory(UUID userID, InventoryReceiptCallback callback)
202 {
203 m_log.InfoFormat("[INVENTORY SERVICE]: Requesting inventory for user {0}", userID);
204
205 List<InventoryFolderImpl> folders = new List<InventoryFolderImpl>();
206 List<InventoryItemBase> items = new List<InventoryItemBase>();
207
208 List<InventoryFolderBase> skeletonFolders = GetInventorySkeleton(userID);
209
210 if (skeletonFolders != null)
211 {
212 InventoryFolderImpl rootFolder = null;
213
214 // Need to retrieve the root folder on the first pass
215 foreach (InventoryFolderBase folder in skeletonFolders)
216 {
217 if (folder.ParentID == UUID.Zero)
218 {
219 rootFolder = new InventoryFolderImpl(folder);
220 folders.Add(rootFolder);
221 items.AddRange(GetFolderItems(userID, rootFolder.ID));
222 break; // Only 1 root folder per user
223 }
224 }
225
226 if (rootFolder != null)
227 {
228 foreach (InventoryFolderBase folder in skeletonFolders)
229 {
230 if (folder.ID != rootFolder.ID)
231 {
232 folders.Add(new InventoryFolderImpl(folder));
233 items.AddRange(GetFolderItems(userID, folder.ID));
234 }
235 }
236 }
237
238 m_log.InfoFormat(
239 "[INVENTORY SERVICE]: Received inventory response for user {0} containing {1} folders and {2} items",
240 userID, folders.Count, items.Count);
241 }
242 else
243 {
244 m_log.WarnFormat("[INVENTORY SERVICE]: User {0} inventory not available", userID);
245 }
246
247 Util.FireAndForget(delegate { callback(folders, items); });
248 }
249
250 public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
251 {
252 // Uncomment me to simulate a slow responding inventory server
253 //Thread.Sleep(16000);
254
255 InventoryCollection invCollection = new InventoryCollection();
256
257 List<InventoryItemBase> items = GetFolderItems(userID, folderID);
258 List<InventoryFolderBase> folders = RequestSubFolders(folderID);
259
260 invCollection.UserID = userID;
261 invCollection.Folders = folders;
262 invCollection.Items = items;
263
264 m_log.DebugFormat("[INVENTORY SERVICE]: Found {0} items and {1} folders in folder {2}", items.Count, folders.Count, folderID);
265
266 return invCollection;
267 }
268
269 public InventoryFolderBase GetFolderForType(UUID userID, AssetType type)
270 {
271// m_log.DebugFormat("[INVENTORY SERVICE]: Looking for folder type {0} for user {1}", type, userID);
272
273 InventoryFolderBase root = m_Database.getUserRootFolder(userID);
274 if (root != null)
275 {
276 List<InventoryFolderBase> folders = RequestSubFolders(root.ID);
277
278 foreach (InventoryFolderBase folder in folders)
279 {
280 if (folder.Type == (short)type)
281 {
282// m_log.DebugFormat(
283// "[INVENTORY SERVICE]: Found folder {0} type {1}", folder.Name, (AssetType)folder.Type);
284
285 return folder;
286 }
287 }
288 }
289
290 // we didn't find any folder of that type. Return the root folder
291 // hopefully the root folder is not null. If it is, too bad
292 return root;
293 }
294
295 public Dictionary<AssetType, InventoryFolderBase> GetSystemFolders(UUID userID)
296 {
297 InventoryFolderBase root = GetRootFolder(userID);
298 if (root != null)
299 {
300 InventoryCollection content = GetFolderContent(userID, root.ID);
301 if (content != null)
302 {
303 Dictionary<AssetType, InventoryFolderBase> folders = new Dictionary<AssetType, InventoryFolderBase>();
304 foreach (InventoryFolderBase folder in content.Folders)
305 {
306 if ((folder.Type != (short)AssetType.Folder) && (folder.Type != (short)AssetType.Unknown))
307 folders[(AssetType)folder.Type] = folder;
308 }
309 m_log.DebugFormat("[INVENTORY SERVICE]: Got {0} system folders for {1}", folders.Count, userID);
310 return folders;
311 }
312 }
313 m_log.WarnFormat("[INVENTORY SERVICE]: System folders for {0} not found", userID);
314 return new Dictionary<AssetType, InventoryFolderBase>();
315 }
316
317 public List<InventoryItemBase> GetActiveGestures(UUID userId)
318 {
319 List<InventoryItemBase> activeGestures = new List<InventoryItemBase>();
320 activeGestures.AddRange(m_Database.fetchActiveGestures(userId));
321
322 return activeGestures;
323 }
324
325 #endregion
326
327 #region Methods used by GridInventoryService
328
329 public List<InventoryFolderBase> RequestSubFolders(UUID parentFolderID)
330 {
331 List<InventoryFolderBase> inventoryList = new List<InventoryFolderBase>();
332
333 inventoryList.AddRange(m_Database.getInventoryFolders(parentFolderID));
334
335 return inventoryList;
336 }
337
338 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
339 {
340 List<InventoryItemBase> itemsList = new List<InventoryItemBase>();
341
342 itemsList.AddRange(m_Database.getInventoryInFolder(folderID));
343
344// m_log.DebugFormat(
345// "[INVENTORY SERVICE]: Found {0} items in folder {1} for {2}", itemsList.Count, folderID, userID);
346
347 return itemsList;
348 }
349
350 #endregion
351
352 // See IInventoryServices
353 public virtual bool AddFolder(InventoryFolderBase folder)
354 {
355 m_log.DebugFormat(
356 "[INVENTORY SERVICE]: Adding folder {0} {1} to folder {2}", folder.Name, folder.ID, folder.ParentID);
357
358 m_Database.addInventoryFolder(folder);
359
360 // FIXME: Should return false on failure
361 return true;
362 }
363
364 // See IInventoryServices
365 public virtual bool UpdateFolder(InventoryFolderBase folder)
366 {
367 m_log.DebugFormat(
368 "[INVENTORY SERVICE]: Updating folder {0} {1} to folder {2}", folder.Name, folder.ID, folder.ParentID);
369
370 m_Database.updateInventoryFolder(folder);
371
372 // FIXME: Should return false on failure
373 return true;
374 }
375
376 // See IInventoryServices
377 public virtual bool MoveFolder(InventoryFolderBase folder)
378 {
379 m_log.DebugFormat(
380 "[INVENTORY SERVICE]: Moving folder {0} {1} to folder {2}", folder.Name, folder.ID, folder.ParentID);
381
382 m_Database.moveInventoryFolder(folder);
383
384 // FIXME: Should return false on failure
385 return true;
386 }
387
388 // See IInventoryServices
389 public virtual bool AddItem(InventoryItemBase item)
390 {
391// m_log.DebugFormat(
392// "[INVENTORY SERVICE]: Adding item {0} {1} to folder {2} for {3}",
393// item.Name, item.ID, item.Folder, item.Owner);
394
395 m_Database.addInventoryItem(item);
396
397 // FIXME: Should return false on failure
398 return true;
399 }
400
401 // See IInventoryServices
402 public virtual bool UpdateItem(InventoryItemBase item)
403 {
404 m_log.InfoFormat(
405 "[INVENTORY SERVICE]: Updating item {0} {1} in folder {2}", item.Name, item.ID, item.Folder);
406
407 m_Database.updateInventoryItem(item);
408
409 // FIXME: Should return false on failure
410 return true;
411 }
412
413 public virtual bool MoveItems(UUID ownerID, List<InventoryItemBase> items)
414 {
415 m_log.InfoFormat(
416 "[INVENTORY SERVICE]: Moving {0} items from user {1}", items.Count, ownerID);
417
418 InventoryItemBase itm = null;
419 foreach (InventoryItemBase item in items)
420 {
421 itm = GetInventoryItem(item.ID);
422 itm.Folder = item.Folder;
423 if ((item.Name != null) && !item.Name.Equals(string.Empty))
424 itm.Name = item.Name;
425 m_Database.updateInventoryItem(itm);
426 }
427
428 return true;
429 }
430
431 // See IInventoryServices
432 public virtual bool DeleteItems(UUID owner, List<UUID> itemIDs)
433 {
434 m_log.InfoFormat(
435 "[INVENTORY SERVICE]: Deleting {0} items from user {1}", itemIDs.Count, owner);
436
437 // uhh.....
438 foreach (UUID uuid in itemIDs)
439 m_Database.deleteInventoryItem(uuid);
440
441 // FIXME: Should return false on failure
442 return true;
443 }
444
445 public virtual InventoryItemBase GetItem(InventoryItemBase item)
446 {
447 InventoryItemBase result = m_Database.getInventoryItem(item.ID);
448 if (result != null)
449 return result;
450 m_log.DebugFormat("[INVENTORY SERVICE]: GetItem failed to find item {0}", item.ID);
451 return null;
452 }
453
454 public virtual InventoryFolderBase GetFolder(InventoryFolderBase folder)
455 {
456 InventoryFolderBase result = m_Database.getInventoryFolder(folder.ID);
457 if (result != null)
458 return result;
459
460 m_log.DebugFormat("[INVENTORY SERVICE]: GetFolder failed to find folder {0}", folder.ID);
461 return null;
462 }
463
464 public virtual bool DeleteFolders(UUID ownerID, List<UUID> folderIDs)
465 {
466 m_log.InfoFormat("[INVENTORY SERVICE]: Deleting {0} folders from user {1}", folderIDs.Count, ownerID);
467 foreach (UUID id in folderIDs)
468 {
469 InventoryFolderBase folder = new InventoryFolderBase(id, ownerID);
470 PurgeFolder(folder);
471 m_Database.deleteInventoryFolder(id);
472 }
473 return true;
474 }
475
476 /// <summary>
477 /// Purge a folder of all items items and subfolders.
478 ///
479 /// FIXME: Really nasty in a sense, because we have to query the database to get information we may
480 /// already know... Needs heavy refactoring.
481 /// </summary>
482 /// <param name="folder"></param>
483 public virtual bool PurgeFolder(InventoryFolderBase folder)
484 {
485 m_log.DebugFormat(
486 "[INVENTORY SERVICE]: Purging folder {0} {1} of its contents", folder.Name, folder.ID);
487
488 List<InventoryFolderBase> subFolders = RequestSubFolders(folder.ID);
489
490 foreach (InventoryFolderBase subFolder in subFolders)
491 {
492// m_log.DebugFormat("[INVENTORY SERVICE]: Deleting folder {0} {1}", subFolder.Name, subFolder.ID);
493
494 m_Database.deleteInventoryFolder(subFolder.ID);
495 }
496
497 List<InventoryItemBase> items = GetFolderItems(folder.Owner, folder.ID);
498
499 List<UUID> uuids = new List<UUID>();
500 foreach (InventoryItemBase item in items)
501 {
502 uuids.Add(item.ID);
503 }
504 DeleteItems(folder.Owner, uuids);
505
506 // FIXME: Should return false on failure
507 return true;
508 }
509
510 private void AddNewInventorySet(UsersInventory inventory)
511 {
512 foreach (InventoryFolderBase folder in inventory.Folders.Values)
513 {
514 AddFolder(folder);
515 }
516 }
517
518 public InventoryItemBase GetInventoryItem(UUID itemID)
519 {
520 InventoryItemBase item = m_Database.getInventoryItem(itemID);
521 if (item != null)
522 return item;
523
524 return null;
525 }
526
527 public int GetAssetPermissions(UUID userID, UUID assetID)
528 {
529 InventoryFolderBase parent = GetRootFolder(userID);
530 return FindAssetPerms(parent, assetID);
531 }
532
533 private int FindAssetPerms(InventoryFolderBase folder, UUID assetID)
534 {
535 InventoryCollection contents = GetFolderContent(folder.Owner, folder.ID);
536
537 int perms = 0;
538 foreach (InventoryItemBase item in contents.Items)
539 {
540 if (item.AssetID == assetID)
541 perms = (int)item.CurrentPermissions | perms;
542 }
543
544 foreach (InventoryFolderBase subfolder in contents.Folders)
545 perms = perms | FindAssetPerms(subfolder, assetID);
546
547 return perms;
548 }
549
550 /// <summary>
551 /// Used to create a new user inventory.
552 /// </summary>
553 private class UsersInventory
554 {
555 public Dictionary<UUID, InventoryFolderBase> Folders = new Dictionary<UUID, InventoryFolderBase>();
556 public Dictionary<UUID, InventoryItemBase> Items = new Dictionary<UUID, InventoryItemBase>();
557
558 public virtual void CreateNewInventorySet(UUID user)
559 {
560 InventoryFolderBase folder = new InventoryFolderBase();
561
562 folder.ParentID = UUID.Zero;
563 folder.Owner = user;
564 folder.ID = UUID.Random();
565 folder.Name = "My Inventory";
566 folder.Type = (short)AssetType.Folder;
567 folder.Version = 1;
568 Folders.Add(folder.ID, folder);
569
570 UUID rootFolder = folder.ID;
571
572 folder = new InventoryFolderBase();
573 folder.ParentID = rootFolder;
574 folder.Owner = user;
575 folder.ID = UUID.Random();
576 folder.Name = "Animations";
577 folder.Type = (short)AssetType.Animation;
578 folder.Version = 1;
579 Folders.Add(folder.ID, folder);
580
581 folder = new InventoryFolderBase();
582 folder.ParentID = rootFolder;
583 folder.Owner = user;
584 folder.ID = UUID.Random();
585 folder.Name = "Body Parts";
586 folder.Type = (short)AssetType.Bodypart;
587 folder.Version = 1;
588 Folders.Add(folder.ID, folder);
589
590 folder = new InventoryFolderBase();
591 folder.ParentID = rootFolder;
592 folder.Owner = user;
593 folder.ID = UUID.Random();
594 folder.Name = "Calling Cards";
595 folder.Type = (short)AssetType.CallingCard;
596 folder.Version = 1;
597 Folders.Add(folder.ID, folder);
598
599 folder = new InventoryFolderBase();
600 folder.ParentID = rootFolder;
601 folder.Owner = user;
602 folder.ID = UUID.Random();
603 folder.Name = "Clothing";
604 folder.Type = (short)AssetType.Clothing;
605 folder.Version = 1;
606 Folders.Add(folder.ID, folder);
607
608 folder = new InventoryFolderBase();
609 folder.ParentID = rootFolder;
610 folder.Owner = user;
611 folder.ID = UUID.Random();
612 folder.Name = "Gestures";
613 folder.Type = (short)AssetType.Gesture;
614 folder.Version = 1;
615 Folders.Add(folder.ID, folder);
616
617 folder = new InventoryFolderBase();
618 folder.ParentID = rootFolder;
619 folder.Owner = user;
620 folder.ID = UUID.Random();
621 folder.Name = "Landmarks";
622 folder.Type = (short)AssetType.Landmark;
623 folder.Version = 1;
624 Folders.Add(folder.ID, folder);
625
626 folder = new InventoryFolderBase();
627 folder.ParentID = rootFolder;
628 folder.Owner = user;
629 folder.ID = UUID.Random();
630 folder.Name = "Lost And Found";
631 folder.Type = (short)AssetType.LostAndFoundFolder;
632 folder.Version = 1;
633 Folders.Add(folder.ID, folder);
634
635 folder = new InventoryFolderBase();
636 folder.ParentID = rootFolder;
637 folder.Owner = user;
638 folder.ID = UUID.Random();
639 folder.Name = "Notecards";
640 folder.Type = (short)AssetType.Notecard;
641 folder.Version = 1;
642 Folders.Add(folder.ID, folder);
643
644 folder = new InventoryFolderBase();
645 folder.ParentID = rootFolder;
646 folder.Owner = user;
647 folder.ID = UUID.Random();
648 folder.Name = "Objects";
649 folder.Type = (short)AssetType.Object;
650 folder.Version = 1;
651 Folders.Add(folder.ID, folder);
652
653 folder = new InventoryFolderBase();
654 folder.ParentID = rootFolder;
655 folder.Owner = user;
656 folder.ID = UUID.Random();
657 folder.Name = "Photo Album";
658 folder.Type = (short)AssetType.SnapshotFolder;
659 folder.Version = 1;
660 Folders.Add(folder.ID, folder);
661
662 folder = new InventoryFolderBase();
663 folder.ParentID = rootFolder;
664 folder.Owner = user;
665 folder.ID = UUID.Random();
666 folder.Name = "Scripts";
667 folder.Type = (short)AssetType.LSLText;
668 folder.Version = 1;
669 Folders.Add(folder.ID, folder);
670
671 folder = new InventoryFolderBase();
672 folder.ParentID = rootFolder;
673 folder.Owner = user;
674 folder.ID = UUID.Random();
675 folder.Name = "Sounds";
676 folder.Type = (short)AssetType.Sound;
677 folder.Version = 1;
678 Folders.Add(folder.ID, folder);
679
680 folder = new InventoryFolderBase();
681 folder.ParentID = rootFolder;
682 folder.Owner = user;
683 folder.ID = UUID.Random();
684 folder.Name = "Textures";
685 folder.Type = (short)AssetType.Texture;
686 folder.Version = 1;
687 Folders.Add(folder.ID, folder);
688
689 folder = new InventoryFolderBase();
690 folder.ParentID = rootFolder;
691 folder.Owner = user;
692 folder.ID = UUID.Random();
693 folder.Name = "Trash";
694 folder.Type = (short)AssetType.TrashFolder;
695 folder.Version = 1;
696 Folders.Add(folder.ID, folder);
697 }
698 }
699 }
700}
diff --git a/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..41ad9f8
--- /dev/null
+++ b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.InventoryService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("d96d6d8c-9769-47e7-88dc-dbeb8fe7105a")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/InventoryService/Tests/XInventoryServiceTests.cs b/OpenSim/Services/InventoryService/Tests/XInventoryServiceTests.cs
new file mode 100644
index 0000000..9e3fa69
--- /dev/null
+++ b/OpenSim/Services/InventoryService/Tests/XInventoryServiceTests.cs
@@ -0,0 +1,177 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using Nini.Config;
30using NUnit.Framework;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Server.Base;
34using OpenSim.Services.Interfaces;
35using OpenSim.Tests.Common;
36
37namespace OpenSim.Services.InventoryService.Tests
38{
39 /// <summary>
40 /// Tests for the XInventoryService
41 /// </summary>
42 /// <remarks>
43 /// TODO: Fill out more tests.
44 /// </remarks>
45 [TestFixture]
46 public class XInventoryServiceTests : OpenSimTestCase
47 {
48 private IInventoryService CreateXInventoryService()
49 {
50 IConfigSource config = new IniConfigSource();
51 config.AddConfig("InventoryService");
52 config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
53
54 return ServerUtils.LoadPlugin<IInventoryService>(
55 "OpenSim.Services.InventoryService.dll:XInventoryService", new Object[] { config });
56 }
57
58 /// <summary>
59 /// Tests add item operation.
60 /// </summary>
61 /// <remarks>
62 /// TODO: Test all operations.
63 /// </remarks>
64 [Test]
65 public void TestAddItem()
66 {
67 TestHelpers.InMethod();
68
69 string creatorId = TestHelpers.ParseTail(0x1).ToString();
70 UUID ownerId = TestHelpers.ParseTail(0x2);
71 UUID itemId = TestHelpers.ParseTail(0x10);
72 UUID assetId = TestHelpers.ParseTail(0x20);
73 UUID folderId = TestHelpers.ParseTail(0x30);
74 int invType = (int)InventoryType.Animation;
75 int assetType = (int)AssetType.Animation;
76 string itemName = "item1";
77
78 IInventoryService xis = CreateXInventoryService();
79
80 InventoryItemBase itemToStore
81 = new InventoryItemBase(itemId, ownerId)
82 {
83 CreatorIdentification = creatorId.ToString(),
84 AssetID = assetId,
85 Name = itemName,
86 Folder = folderId,
87 InvType = invType,
88 AssetType = assetType
89 };
90
91 Assert.That(xis.AddItem(itemToStore), Is.True);
92
93 InventoryItemBase itemRetrieved = new InventoryItemBase(itemId);
94 itemRetrieved = xis.GetItem(itemRetrieved);
95
96 Assert.That(itemRetrieved, Is.Not.Null);
97 Assert.That(itemRetrieved.CreatorId, Is.EqualTo(creatorId));
98 Assert.That(itemRetrieved.Owner, Is.EqualTo(ownerId));
99 Assert.That(itemRetrieved.AssetID, Is.EqualTo(assetId));
100 Assert.That(itemRetrieved.Folder, Is.EqualTo(folderId));
101 Assert.That(itemRetrieved.InvType, Is.EqualTo(invType));
102 Assert.That(itemRetrieved.AssetType, Is.EqualTo(assetType));
103 Assert.That(itemRetrieved.Name, Is.EqualTo(itemName));
104 }
105
106 [Test]
107 public void TestUpdateItem()
108 {
109 TestHelpers.InMethod();
110// TestHelpers.EnableLogging();
111
112 string creatorId = TestHelpers.ParseTail(0x1).ToString();
113 UUID ownerId = TestHelpers.ParseTail(0x2);
114 UUID itemId = TestHelpers.ParseTail(0x10);
115 UUID assetId = TestHelpers.ParseTail(0x20);
116 UUID folderId = TestHelpers.ParseTail(0x30);
117 int invType = (int)InventoryType.Animation;
118 int assetType = (int)AssetType.Animation;
119 string itemName = "item1";
120 string itemName2 = "item2";
121
122 IInventoryService xis = CreateXInventoryService();
123
124 InventoryItemBase itemToStore
125 = new InventoryItemBase(itemId, ownerId)
126 {
127 CreatorIdentification = creatorId.ToString(),
128 AssetID = assetId,
129 Name = itemName,
130 Folder = folderId,
131 InvType = invType,
132 AssetType = assetType
133 };
134
135 Assert.That(xis.AddItem(itemToStore), Is.True);
136
137 // Normal update
138 itemToStore.Name = itemName2;
139
140 Assert.That(xis.UpdateItem(itemToStore), Is.True);
141
142 InventoryItemBase itemRetrieved = new InventoryItemBase(itemId);
143 itemRetrieved = xis.GetItem(itemRetrieved);
144
145 Assert.That(itemRetrieved, Is.Not.Null);
146 Assert.That(itemRetrieved.Name, Is.EqualTo(itemName2));
147
148 // Attempt to update properties that should never change
149 string creatorId2 = TestHelpers.ParseTail(0x7).ToString();
150 UUID ownerId2 = TestHelpers.ParseTail(0x8);
151 UUID folderId2 = TestHelpers.ParseTail(0x70);
152 int invType2 = (int)InventoryType.CallingCard;
153 int assetType2 = (int)AssetType.CallingCard;
154 string itemName3 = "item3";
155
156 itemToStore.CreatorIdentification = creatorId2.ToString();
157 itemToStore.Owner = ownerId2;
158 itemToStore.Folder = folderId2;
159 itemToStore.InvType = invType2;
160 itemToStore.AssetType = assetType2;
161 itemToStore.Name = itemName3;
162
163 Assert.That(xis.UpdateItem(itemToStore), Is.True);
164
165 itemRetrieved = xis.GetItem(itemRetrieved);
166
167 Assert.That(itemRetrieved, Is.Not.Null);
168 Assert.That(itemRetrieved.CreatorId, Is.EqualTo(creatorId));
169 Assert.That(itemRetrieved.Owner, Is.EqualTo(ownerId));
170 Assert.That(itemRetrieved.AssetID, Is.EqualTo(assetId));
171 Assert.That(itemRetrieved.Folder, Is.EqualTo(folderId));
172 Assert.That(itemRetrieved.InvType, Is.EqualTo(invType));
173 Assert.That(itemRetrieved.AssetType, Is.EqualTo(assetType));
174 Assert.That(itemRetrieved.Name, Is.EqualTo(itemName3));
175 }
176 }
177} \ No newline at end of file
diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs
index 7518b86..00faa44 100644
--- a/OpenSim/Services/InventoryService/XInventoryService.cs
+++ b/OpenSim/Services/InventoryService/XInventoryService.cs
@@ -94,6 +94,7 @@ namespace OpenSim.Services.InventoryService
94 94
95 m_Database = LoadPlugin<IXInventoryData>(dllName, 95 m_Database = LoadPlugin<IXInventoryData>(dllName,
96 new Object[] {connString, String.Empty}); 96 new Object[] {connString, String.Empty});
97
97 if (m_Database == null) 98 if (m_Database == null)
98 throw new Exception("Could not find a storage interface in the given module"); 99 throw new Exception("Could not find a storage interface in the given module");
99 } 100 }
@@ -229,10 +230,28 @@ namespace OpenSim.Services.InventoryService
229 public virtual InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) 230 public virtual InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
230 { 231 {
231// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID); 232// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
233
234 InventoryFolderBase rootFolder = GetRootFolder(principalID);
235
236 if (rootFolder == null)
237 {
238 m_log.WarnFormat(
239 "[XINVENTORY]: Found no root folder for {0} in GetFolderForType() when looking for {1}",
240 principalID, type);
241
242 return null;
243 }
244
245 return GetSystemFolderForType(rootFolder, type);
246 }
247
248 private InventoryFolderBase GetSystemFolderForType(InventoryFolderBase rootFolder, AssetType type)
249 {
250// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
232 251
233 XInventoryFolder[] folders = m_Database.GetFolders( 252 XInventoryFolder[] folders = m_Database.GetFolders(
234 new string[] { "agentID", "type"}, 253 new string[] { "agentID", "parentFolderID", "type"},
235 new string[] { principalID.ToString(), ((int)type).ToString() }); 254 new string[] { rootFolder.Owner.ToString(), rootFolder.ID.ToString(), ((int)type).ToString() });
236 255
237 if (folders.Length == 0) 256 if (folders.Length == 0)
238 { 257 {
@@ -308,22 +327,38 @@ namespace OpenSim.Services.InventoryService
308 if (check != null) 327 if (check != null)
309 return false; 328 return false;
310 329
311 if (folder.Type == (short)AssetType.Folder 330 if (folder.Type != (short)AssetType.Folder && folder.Type != (short)AssetType.Unknown)
312 || folder.Type == (short)AssetType.Unknown
313 || folder.Type == (short)AssetType.OutfitFolder
314 || GetFolderForType(folder.Owner, (AssetType)(folder.Type)) == null)
315 { 331 {
316 XInventoryFolder xFolder = ConvertFromOpenSim(folder); 332 InventoryFolderBase rootFolder = GetRootFolder(folder.Owner);
317 return m_Database.StoreFolder(xFolder); 333
318 } 334 if (rootFolder == null)
319 else 335 {
320 { 336 m_log.WarnFormat(
321 m_log.WarnFormat( 337 "[XINVENTORY]: Found no root folder for {0} in AddFolder() when looking for {1}",
322 "[XINVENTORY]: Folder of type {0} already exists when tried to add {1} to {2} for {3}", 338 folder.Owner, folder.Type);
323 folder.Type, folder.Name, folder.ParentID, folder.Owner); 339
340 return false;
341 }
342
343 // Check we're not trying to add this as a system folder.
344 if (folder.ParentID == rootFolder.ID)
345 {
346 InventoryFolderBase existingSystemFolder
347 = GetSystemFolderForType(rootFolder, (AssetType)folder.Type);
348
349 if (existingSystemFolder != null)
350 {
351 m_log.WarnFormat(
352 "[XINVENTORY]: System folder of type {0} already exists when tried to add {1} to {2} for {3}",
353 folder.Type, folder.Name, folder.ParentID, folder.Owner);
354
355 return false;
356 }
357 }
324 } 358 }
325 359
326 return false; 360 XInventoryFolder xFolder = ConvertFromOpenSim(folder);
361 return m_Database.StoreFolder(xFolder);
327 } 362 }
328 363
329 public virtual bool UpdateFolder(InventoryFolderBase folder) 364 public virtual bool UpdateFolder(InventoryFolderBase folder)
@@ -365,16 +400,7 @@ namespace OpenSim.Services.InventoryService
365 400
366 public virtual bool MoveFolder(InventoryFolderBase folder) 401 public virtual bool MoveFolder(InventoryFolderBase folder)
367 { 402 {
368 XInventoryFolder[] x = m_Database.GetFolders( 403 return m_Database.MoveFolder(folder.ID.ToString(), folder.ParentID.ToString());
369 new string[] { "folderID" },
370 new string[] { folder.ID.ToString() });
371
372 if (x.Length == 0)
373 return false;
374
375 x[0].parentFolderID = folder.ParentID;
376
377 return m_Database.StoreFolder(x[0]);
378 } 404 }
379 405
380 // We don't check the principal's ID here 406 // We don't check the principal's ID here
@@ -450,6 +476,46 @@ namespace OpenSim.Services.InventoryService
450// m_log.InfoFormat( 476// m_log.InfoFormat(
451// "[XINVENTORY SERVICE]: Updating item {0} {1} in folder {2}", item.Name, item.ID, item.Folder); 477// "[XINVENTORY SERVICE]: Updating item {0} {1} in folder {2}", item.Name, item.ID, item.Folder);
452 478
479 InventoryItemBase retrievedItem = GetItem(item);
480
481 if (retrievedItem == null)
482 {
483 m_log.WarnFormat(
484 "[XINVENTORY SERVICE]: Tried to update item {0} {1}, owner {2} but no existing item found.",
485 item.Name, item.ID, item.Owner);
486
487 return false;
488 }
489
490 // Do not allow invariants to change. Changes to folder ID occur in MoveItems()
491 if (retrievedItem.InvType != item.InvType
492 || retrievedItem.AssetType != item.AssetType
493 || retrievedItem.Folder != item.Folder
494 || retrievedItem.CreatorIdentification != item.CreatorIdentification
495 || retrievedItem.Owner != item.Owner)
496 {
497 m_log.WarnFormat(
498 "[XINVENTORY SERVICE]: Caller to UpdateItem() for {0} {1} tried to alter property(s) that should be invariant, (InvType, AssetType, Folder, CreatorIdentification, Owner), existing ({2}, {3}, {4}, {5}, {6}), update ({7}, {8}, {9}, {10}, {11})",
499 retrievedItem.Name,
500 retrievedItem.ID,
501 retrievedItem.InvType,
502 retrievedItem.AssetType,
503 retrievedItem.Folder,
504 retrievedItem.CreatorIdentification,
505 retrievedItem.Owner,
506 item.InvType,
507 item.AssetType,
508 item.Folder,
509 item.CreatorIdentification,
510 item.Owner);
511
512 item.InvType = retrievedItem.InvType;
513 item.AssetType = retrievedItem.AssetType;
514 item.Folder = retrievedItem.Folder;
515 item.CreatorIdentification = retrievedItem.CreatorIdentification;
516 item.Owner = retrievedItem.Owner;
517 }
518
453 return m_Database.StoreItem(ConvertFromOpenSim(item)); 519 return m_Database.StoreItem(ConvertFromOpenSim(item));
454 } 520 }
455 521
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index 988a9b9..cbb6e6c 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -300,7 +300,7 @@ namespace OpenSim.Services.LLLoginService
300 { 300 {
301 m_log.InfoFormat( 301 m_log.InfoFormat(
302 "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: user level is {2} but minimum login level is {3}", 302 "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: user level is {2} but minimum login level is {3}",
303 firstName, lastName, m_MinLoginLevel, account.UserLevel); 303 firstName, lastName, account.UserLevel, m_MinLoginLevel);
304 return LLFailedLoginResponse.LoginBlockedProblem; 304 return LLFailedLoginResponse.LoginBlockedProblem;
305 } 305 }
306 306
diff --git a/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs b/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..62c6e0f
--- /dev/null
+++ b/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.LLLoginService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("cbeb8f23-3896-4076-97fd-f955b0af6a93")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs b/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..23eb664
--- /dev/null
+++ b/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.MapImageService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("5e679df7-1d2a-401a-8966-b93677bb5839")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs b/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..8c03dd7
--- /dev/null
+++ b/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.PresenceService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("a875a0bd-eab0-40a2-b5c4-3afddc3b4d2d")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/UserAccountService/GridUserService.cs b/OpenSim/Services/UserAccountService/GridUserService.cs
index ac3d8fd..43fa04b 100644
--- a/OpenSim/Services/UserAccountService/GridUserService.cs
+++ b/OpenSim/Services/UserAccountService/GridUserService.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Services.UserAccountService
49 m_log.Debug("[USER GRID SERVICE]: Starting user grid service"); 49 m_log.Debug("[USER GRID SERVICE]: Starting user grid service");
50 } 50 }
51 51
52 public GridUserInfo GetGridUserInfo(string userID) 52 public virtual GridUserInfo GetGridUserInfo(string userID)
53 { 53 {
54 GridUserData d = m_Database.Get(userID); 54 GridUserData d = m_Database.Get(userID);
55 55
@@ -122,17 +122,6 @@ namespace OpenSim.Services.UserAccountService
122 return m_Database.Store(d); 122 return m_Database.Store(d);
123 } 123 }
124 124
125 protected bool StoreGridUserInfo(GridUserInfo info)
126 {
127 GridUserData d = new GridUserData();
128
129 d.Data["HomeRegionID"] = info.HomeRegionID.ToString();
130 d.Data["HomePosition"] = info.HomePosition.ToString();
131 d.Data["HomeLookAt"] = info.HomeLookAt.ToString();
132
133 return m_Database.Store(d);
134 }
135
136 public bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt) 125 public bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt)
137 { 126 {
138 GridUserData d = m_Database.Get(userID); 127 GridUserData d = m_Database.Get(userID);
diff --git a/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs b/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..24e1d16
--- /dev/null
+++ b/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.UserAccountService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("fdb4771d-9928-4db4-aeb5-90cac2976584")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
index 7598cc3..ea3e348 100644
--- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
@@ -139,11 +139,11 @@ namespace OpenSim.Tests.Common
139 SceneCommunicationService scs = new SceneCommunicationService(); 139 SceneCommunicationService scs = new SceneCommunicationService();
140 140
141 TestScene testScene = new TestScene( 141 TestScene testScene = new TestScene(
142 regInfo, m_acm, scs, m_simDataService, m_estateDataService, null, false, configSource, null); 142 regInfo, m_acm, scs, m_simDataService, m_estateDataService, false, configSource, null);
143 143
144 IRegionModule godsModule = new GodsModule(); 144 INonSharedRegionModule godsModule = new GodsModule();
145 godsModule.Initialise(testScene, new IniConfigSource()); 145 godsModule.Initialise(new IniConfigSource());
146 testScene.AddModule(godsModule.Name, godsModule); 146 godsModule.AddRegion(testScene);
147 147
148 // Add scene to services 148 // Add scene to services
149 m_assetService.AddRegion(testScene); 149 m_assetService.AddRegion(testScene);
@@ -245,7 +245,7 @@ namespace OpenSim.Tests.Common
245 config.AddConfig("Modules"); 245 config.AddConfig("Modules");
246 config.AddConfig("InventoryService"); 246 config.AddConfig("InventoryService");
247 config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector"); 247 config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector");
248 config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:InventoryService"); 248 config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:XInventoryService");
249 config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); 249 config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
250 250
251 LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector(); 251 LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector();
@@ -350,6 +350,10 @@ namespace OpenSim.Tests.Common
350 /// </summary> 350 /// </summary>
351 /// <remarks> 351 /// <remarks>
352 /// If called directly, then all the modules must be shared modules. 352 /// If called directly, then all the modules must be shared modules.
353 ///
354 /// We are emulating here the normal calls made to setup region modules
355 /// (Initialise(), PostInitialise(), AddRegion, RegionLoaded()).
356 /// TODO: Need to reuse normal runtime module code.
353 /// </remarks> 357 /// </remarks>
354 /// <param name="scenes"></param> 358 /// <param name="scenes"></param>
355 /// <param name="config"></param> 359 /// <param name="config"></param>
@@ -359,28 +363,10 @@ namespace OpenSim.Tests.Common
359 List<IRegionModuleBase> newModules = new List<IRegionModuleBase>(); 363 List<IRegionModuleBase> newModules = new List<IRegionModuleBase>();
360 foreach (object module in modules) 364 foreach (object module in modules)
361 { 365 {
362// Console.WriteLine("MODULE RAW {0}", module); 366 IRegionModuleBase m = (IRegionModuleBase)module;
363 if (module is IRegionModule) 367// Console.WriteLine("MODULE {0}", m.Name);
364 { 368 m.Initialise(config);
365 IRegionModule m = (IRegionModule)module; 369 newModules.Add(m);
366
367 foreach (Scene scene in scenes)
368 {
369 m.Initialise(scene, config);
370 scene.AddModule(m.Name, m);
371 }
372
373 m.PostInitialise();
374 }
375 else if (module is IRegionModuleBase)
376 {
377 // for the new system, everything has to be initialised first,
378 // shared modules have to be post-initialised, then all get an AddRegion with the scene
379 IRegionModuleBase m = (IRegionModuleBase)module;
380// Console.WriteLine("MODULE {0}", m.Name);
381 m.Initialise(config);
382 newModules.Add(m);
383 }
384 } 370 }
385 371
386 foreach (IRegionModuleBase module in newModules) 372 foreach (IRegionModuleBase module in newModules)
@@ -396,7 +382,7 @@ namespace OpenSim.Tests.Common
396 scene.AddRegionModule(module.Name, module); 382 scene.AddRegionModule(module.Name, module);
397 } 383 }
398 } 384 }
399 385
400 // RegionLoaded is fired after all modules have been appropriately added to all scenes 386 // RegionLoaded is fired after all modules have been appropriately added to all scenes
401 foreach (IRegionModuleBase module in newModules) 387 foreach (IRegionModuleBase module in newModules)
402 foreach (Scene scene in scenes) 388 foreach (Scene scene in scenes)
@@ -709,4 +695,4 @@ namespace OpenSim.Tests.Common
709 return sog; 695 return sog;
710 } 696 }
711 } 697 }
712} \ No newline at end of file 698}
diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
index b3a7c9e..87d9410 100644
--- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
@@ -199,7 +199,9 @@ namespace OpenSim.Tests.Common
199 string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); 199 string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
200 200
201 InventoryFolderBase newFolder 201 InventoryFolderBase newFolder
202 = new InventoryFolderBase(UUID.Random(), components[0], parentFolder.Owner, parentFolder.ID); 202 = new InventoryFolderBase(
203 UUID.Random(), components[0], parentFolder.Owner, (short)AssetType.Unknown, parentFolder.ID, 0);
204
203 inventoryService.AddFolder(newFolder); 205 inventoryService.AddFolder(newFolder);
204 206
205 if (components.Length > 1) 207 if (components.Length > 1)
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 49a8d26..2714429 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -320,7 +320,7 @@ namespace OpenSim.Tests.Common.Mock
320 public event MuteListEntryRemove OnRemoveMuteListEntry; 320 public event MuteListEntryRemove OnRemoveMuteListEntry;
321 public event GodlikeMessage onGodlikeMessage; 321 public event GodlikeMessage onGodlikeMessage;
322 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 322 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
323 323 public event GenericCall2 OnUpdateThrottles;
324#pragma warning restore 67 324#pragma warning restore 67
325 325
326 /// <value> 326 /// <value>
@@ -521,6 +521,12 @@ namespace OpenSim.Tests.Common.Mock
521 public virtual void SetChildAgentThrottle(byte[] throttle) 521 public virtual void SetChildAgentThrottle(byte[] throttle)
522 { 522 {
523 } 523 }
524
525 public void SetAgentThrottleSilent(int throttle, int setting)
526 {
527
528
529 }
524 public byte[] GetThrottlesPacked(float multiplier) 530 public byte[] GetThrottlesPacked(float multiplier)
525 { 531 {
526 return new byte[0]; 532 return new byte[0];
@@ -531,13 +537,9 @@ namespace OpenSim.Tests.Common.Mock
531 { 537 {
532 } 538 }
533 539
534 public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, 540 public virtual void SendChatMessage(
535 UUID fromAgentID, byte source, byte audible) 541 string message, byte type, Vector3 fromPos, string fromName,
536 { 542 UUID fromAgentID, UUID ownerID, byte source, byte audible)
537 }
538
539 public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName,
540 UUID fromAgentID, byte source, byte audible)
541 { 543 {
542 } 544 }
543 545
@@ -939,12 +941,12 @@ namespace OpenSim.Tests.Common.Mock
939 Close(); 941 Close();
940 } 942 }
941 943
942 public void Close(bool c) 944 public void Close()
943 { 945 {
944 Close(); 946 Close(true, false);
945 } 947 }
946 948
947 public void Close() 949 public void Close(bool sendStop, bool force)
948 { 950 {
949 // Fire the callback for this connection closing 951 // Fire the callback for this connection closing
950 // This is necesary to get the presence detector to notice that a client has logged out. 952 // This is necesary to get the presence detector to notice that a client has logged out.
diff --git a/OpenSim/Tests/Common/Mock/TestScene.cs b/OpenSim/Tests/Common/Mock/TestScene.cs
index eea68c3..d4b5648 100644
--- a/OpenSim/Tests/Common/Mock/TestScene.cs
+++ b/OpenSim/Tests/Common/Mock/TestScene.cs
@@ -41,9 +41,9 @@ namespace OpenSim.Tests.Common.Mock
41 public TestScene( 41 public TestScene(
42 RegionInfo regInfo, AgentCircuitManager authen, 42 RegionInfo regInfo, AgentCircuitManager authen,
43 SceneCommunicationService sceneGridService, ISimulationDataService simDataService, IEstateDataService estateDataService, 43 SceneCommunicationService sceneGridService, ISimulationDataService simDataService, IEstateDataService estateDataService,
44 ModuleLoader moduleLoader, bool dumpAssetsToFile, 44 bool dumpAssetsToFile,
45 IConfigSource config, string simulatorVersion) 45 IConfigSource config, string simulatorVersion)
46 : base(regInfo, authen, sceneGridService, simDataService, estateDataService, moduleLoader, 46 : base(regInfo, authen, sceneGridService, simDataService, estateDataService,
47 dumpAssetsToFile, config, simulatorVersion) 47 dumpAssetsToFile, config, simulatorVersion)
48 { 48 {
49 } 49 }
@@ -73,4 +73,4 @@ namespace OpenSim.Tests.Common.Mock
73 get { return m_asyncSceneObjectDeleter; } 73 get { return m_asyncSceneObjectDeleter; }
74 } 74 }
75 } 75 }
76} \ No newline at end of file 76}
diff --git a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
new file mode 100644
index 0000000..f9bf768
--- /dev/null
+++ b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
@@ -0,0 +1,132 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Data;
36
37namespace OpenSim.Tests.Common.Mock
38{
39 public class TestXInventoryDataPlugin : IXInventoryData
40 {
41 private Dictionary<UUID, XInventoryFolder> m_allFolders = new Dictionary<UUID, XInventoryFolder>();
42 private Dictionary<UUID, XInventoryItem> m_allItems = new Dictionary<UUID, XInventoryItem>();
43
44 public TestXInventoryDataPlugin(string conn, string realm) {}
45
46 public XInventoryItem[] GetItems(string[] fields, string[] vals)
47 {
48 List<XInventoryItem> origItems = Get<XInventoryItem>(fields, vals, m_allItems.Values.ToList());
49
50 return origItems.Select(i => i.Clone()).ToArray();
51 }
52
53 public XInventoryFolder[] GetFolders(string[] fields, string[] vals)
54 {
55 List<XInventoryFolder> origFolders
56 = Get<XInventoryFolder>(fields, vals, m_allFolders.Values.ToList());
57
58 return origFolders.Select(f => f.Clone()).ToArray();
59 }
60
61 private List<T> Get<T>(string[] fields, string[] vals, List<T> inputEntities)
62 {
63 List<T> entities = inputEntities;
64
65 for (int i = 0; i < fields.Length; i++)
66 {
67 entities
68 = entities.Where(
69 e =>
70 {
71 FieldInfo fi = typeof(T).GetField(fields[i]);
72 if (fi == null)
73 throw new NotImplementedException(string.Format("No field {0} for val {1}", fields[i], vals[i]));
74
75 return fi.GetValue(e).ToString() == vals[i];
76 }
77 ).ToList();
78 }
79
80 return entities;
81 }
82
83 public bool StoreFolder(XInventoryFolder folder)
84 {
85 m_allFolders[folder.folderID] = folder.Clone();
86
87// Console.WriteLine("Added folder {0} {1}", folder.folderName, folder.folderID);
88
89 return true;
90 }
91
92 public bool StoreItem(XInventoryItem item)
93 {
94 m_allItems[item.inventoryID] = item.Clone();
95
96// Console.WriteLine("Added item {0} {1}, creator {2}, owner {3}", item.inventoryName, item.inventoryID, item.creatorID, item.avatarID);
97
98 return true;
99 }
100
101 public bool DeleteFolders(string field, string val)
102 {
103 return DeleteFolders(new string[] { field }, new string[] { val });
104 }
105
106 public bool DeleteFolders(string[] fields, string[] vals)
107 {
108 XInventoryFolder[] foldersToDelete = GetFolders(fields, vals);
109 Array.ForEach(foldersToDelete, f => m_allFolders.Remove(f.folderID));
110
111 return true;
112 }
113
114 public bool DeleteItems(string field, string val)
115 {
116 return DeleteItems(new string[] { field }, new string[] { val });
117 }
118
119 public bool DeleteItems(string[] fields, string[] vals)
120 {
121 XInventoryItem[] itemsToDelete = GetItems(fields, vals);
122 Array.ForEach(itemsToDelete, i => m_allItems.Remove(i.inventoryID));
123
124 return true;
125 }
126
127 public bool MoveItem(string id, string newParent) { throw new NotImplementedException(); }
128 public bool MoveFolder(string id, string newParent) { throw new NotImplementedException(); }
129 public XInventoryItem[] GetActiveGestures(UUID principalID) { throw new NotImplementedException(); }
130 public int GetAssetPermissions(UUID principalID, UUID assetID) { throw new NotImplementedException(); }
131 }
132} \ No newline at end of file
diff --git a/OpenSim/Tests/Common/TestHelpers.cs b/OpenSim/Tests/Common/TestHelpers.cs
index 30121fe..57da802 100644
--- a/OpenSim/Tests/Common/TestHelpers.cs
+++ b/OpenSim/Tests/Common/TestHelpers.cs
@@ -95,6 +95,7 @@ namespace OpenSim.Tests.Common
95 public static void EnableLogging() 95 public static void EnableLogging()
96 { 96 {
97 log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream); 97 log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream);
98 EnableLoggingConfigStream.Position = 0;
98 } 99 }
99 100
100 /// <summary> 101 /// <summary>
diff --git a/OpenSim/Tests/Torture/NPCTortureTests.cs b/OpenSim/Tests/Performance/NPCPerformanceTests.cs
index 731df68..627765b 100644
--- a/OpenSim/Tests/Torture/NPCTortureTests.cs
+++ b/OpenSim/Tests/Performance/NPCPerformanceTests.cs
@@ -47,10 +47,10 @@ using OpenSim.Services.AvatarService;
47using OpenSim.Tests.Common; 47using OpenSim.Tests.Common;
48using OpenSim.Tests.Common.Mock; 48using OpenSim.Tests.Common.Mock;
49 49
50namespace OpenSim.Tests.Torture 50namespace OpenSim.Tests.Performance
51{ 51{
52 /// <summary> 52 /// <summary>
53 /// NPC torture tests 53 /// NPC performance tests
54 /// </summary> 54 /// </summary>
55 /// <remarks> 55 /// <remarks>
56 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, 56 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@@ -58,7 +58,7 @@ namespace OpenSim.Tests.Torture
58 /// earlier tests. 58 /// earlier tests.
59 /// </remarks> 59 /// </remarks>
60 [TestFixture] 60 [TestFixture]
61 public class NPCTortureTests 61 public class NPCPerformanceTests
62 { 62 {
63 private TestScene scene; 63 private TestScene scene;
64 private AvatarFactoryModule afm; 64 private AvatarFactoryModule afm;
diff --git a/OpenSim/Tests/Torture/ObjectTortureTests.cs b/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
index 195d47b..2264d86 100644
--- a/OpenSim/Tests/Torture/ObjectTortureTests.cs
+++ b/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
@@ -36,10 +36,10 @@ using OpenSim.Region.Framework.Scenes;
36using OpenSim.Tests.Common; 36using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock; 37using OpenSim.Tests.Common.Mock;
38 38
39namespace OpenSim.Tests.Torture 39namespace OpenSim.Tests.Performance
40{ 40{
41 /// <summary> 41 /// <summary>
42 /// Object torture tests 42 /// Object performance tests
43 /// </summary> 43 /// </summary>
44 /// <remarks> 44 /// <remarks>
45 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, 45 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@@ -47,7 +47,7 @@ namespace OpenSim.Tests.Torture
47 /// earlier tests. 47 /// earlier tests.
48 /// </remarks> 48 /// </remarks>
49 [TestFixture] 49 [TestFixture]
50 public class ObjectTortureTests 50 public class ObjectPerformanceTests
51 { 51 {
52 [TearDown] 52 [TearDown]
53 public void TearDown() 53 public void TearDown()
diff --git a/OpenSim/Tests/Torture/ScriptTortureTests.cs b/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
index 24f278f..d708abd 100644
--- a/OpenSim/Tests/Torture/ScriptTortureTests.cs
+++ b/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
@@ -42,10 +42,10 @@ using OpenSim.Region.ScriptEngine.XEngine;
42using OpenSim.Tests.Common; 42using OpenSim.Tests.Common;
43using OpenSim.Tests.Common.Mock; 43using OpenSim.Tests.Common.Mock;
44 44
45namespace OpenSim.Tests.Torture 45namespace OpenSim.Tests.Performance
46{ 46{
47 /// <summary> 47 /// <summary>
48 /// Script torture tests 48 /// Script performance tests
49 /// </summary> 49 /// </summary>
50 /// <remarks> 50 /// <remarks>
51 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, 51 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@@ -53,7 +53,7 @@ namespace OpenSim.Tests.Torture
53 /// earlier tests. 53 /// earlier tests.
54 /// </remarks> 54 /// </remarks>
55 [TestFixture] 55 [TestFixture]
56 public class ScriptTortureTests 56 public class ScriptPerformanceTests
57 { 57 {
58 private TestScene m_scene; 58 private TestScene m_scene;
59 private XEngine m_xEngine; 59 private XEngine m_xEngine;
diff --git a/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs b/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs
new file mode 100644
index 0000000..1f220c0
--- /dev/null
+++ b/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs
@@ -0,0 +1,132 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Linq;
32using System.Reflection;
33using System.Threading;
34using log4net.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenMetaverse.Assets;
38using OpenSim.Framework;
39using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
40using OpenSim.Region.CoreModules.Scripting.VectorRender;
41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.Framework.Scenes.Serialization;
43using OpenSim.Tests.Common;
44using OpenSim.Tests.Common.Mock;
45
46namespace OpenSim.Tests.Stress
47{
48 [TestFixture]
49 public class VectorRenderModuleStressTests : OpenSimTestCase
50 {
51 public Scene Scene { get; private set; }
52 public DynamicTextureModule Dtm { get; private set; }
53 public VectorRenderModule Vrm { get; private set; }
54
55 private void SetupScene(bool reuseTextures)
56 {
57 Scene = new SceneHelpers().SetupScene();
58
59 Dtm = new DynamicTextureModule();
60 Dtm.ReuseTextures = reuseTextures;
61
62 Vrm = new VectorRenderModule();
63
64 SceneHelpers.SetupSceneModules(Scene, Dtm, Vrm);
65 }
66
67 [Test]
68 public void TestConcurrentRepeatedDraw()
69 {
70 int threads = 4;
71 TestHelpers.InMethod();
72
73 SetupScene(false);
74
75 List<Drawer> drawers = new List<Drawer>();
76
77 for (int i = 0; i < threads; i++)
78 {
79 Drawer d = new Drawer(this, i);
80 drawers.Add(d);
81 Console.WriteLine("Starting drawer {0}", i);
82 Util.FireAndForget(o => d.Draw());
83 }
84
85 Thread.Sleep(10 * 60 * 1000);
86
87 drawers.ForEach(d => d.Ready = false);
88 drawers.ForEach(d => Console.WriteLine("Drawer {0} drew {1} textures", d.Number, d.Pass + 1));
89 }
90
91 class Drawer
92 {
93 public int Number { get; private set; }
94 public int Pass { get; private set; }
95 public bool Ready { get; set; }
96
97 private VectorRenderModuleStressTests m_tests;
98
99 public Drawer(VectorRenderModuleStressTests tests, int number)
100 {
101 m_tests = tests;
102 Number = number;
103 Ready = true;
104 }
105
106 public void Draw()
107 {
108 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_tests.Scene);
109
110 while (Ready)
111 {
112 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
113
114 // Ensure unique text
115 string text = string.Format("{0:D2}{1}", Number, Pass);
116
117 m_tests.Dtm.AddDynamicTextureData(
118 m_tests.Scene.RegionInfo.RegionID,
119 so.UUID,
120 m_tests.Vrm.GetContentType(),
121 string.Format("PenColour BLACK; MoveTo 40,220; FontSize 32; Text {0};", text),
122 "",
123 0);
124
125 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
126
127 Pass++;
128 }
129 }
130 }
131 }
132} \ No newline at end of file
diff --git a/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs b/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e1a1fda
--- /dev/null
+++ b/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Tools.lslc")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("002864e7-b2a2-41d2-add8-82f653663160")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs b/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..62a2f2d
--- /dev/null
+++ b/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Tools.Configger")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("67d7fdf2-554c-40f0-8f9d-f71373c20926")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs b/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..20598f1
--- /dev/null
+++ b/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("pCampBot")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("84a69c60-76d3-4846-bd5b-0e1083774039")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]