aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorMelanie Thielker2014-06-21 00:39:55 +0200
committerMelanie Thielker2014-06-21 00:39:55 +0200
commit159fcbf150b7da0e229b29aa7b94793484543d12 (patch)
treeb8c0ff3b4c758a3fba8315b556c923ef4c02a185 /OpenSim
parentMerge commit '68c8633ba18f0a11cfc0ed04d1d0c7c59e6cec76' (diff)
parentMerge branch 'master' into careminster (diff)
downloadopensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.zip
opensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.tar.gz
opensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.tar.bz2
opensim-SC_OLD-159fcbf150b7da0e229b29aa7b94793484543d12.tar.xz
Merge branch 'master' of ssh://3dhosting.de/var/git/careminster
Conflicts: OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs4
-rw-r--r--OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs9
-rw-r--r--OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs2
-rw-r--r--OpenSim/Addons/Groups/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs2
-rw-r--r--OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs2
-rw-r--r--OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs5
-rw-r--r--OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs8
-rw-r--r--OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs22
-rw-r--r--OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs24
-rw-r--r--OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs23
-rw-r--r--OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs231
-rw-r--r--OpenSim/Capabilities/Caps.cs95
-rw-r--r--OpenSim/Capabilities/CapsHandlers.cs16
-rw-r--r--OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs116
-rw-r--r--OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs4
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs3
-rw-r--r--OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureServerConnector.cs76
-rw-r--r--OpenSim/Capabilities/LLSDAvatarPicker.cs51
-rw-r--r--OpenSim/Capabilities/LLSDStreamHandler.cs2
-rw-r--r--OpenSim/Data/IGridUserData.cs1
-rw-r--r--OpenSim/Data/IHGTravelingData.cs59
-rw-r--r--OpenSim/Data/IOfflineIMData.cs3
-rw-r--r--OpenSim/Data/IProfilesData.cs56
-rw-r--r--OpenSim/Data/IRegionData.cs1
-rw-r--r--OpenSim/Data/MSSQL/MSSQLGridUserData.cs7
-rw-r--r--OpenSim/Data/MSSQL/MSSQLRegionData.cs5
-rw-r--r--OpenSim/Data/MSSQL/MSSQLSimulationData.cs19
-rw-r--r--OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/MSSQL/Resources/RegionStore.migrations12
-rw-r--r--OpenSim/Data/MySQL/MySQLAssetData.cs22
-rw-r--r--OpenSim/Data/MySQL/MySQLGridUserData.cs7
-rw-r--r--OpenSim/Data/MySQL/MySQLGroupsData.cs2
-rw-r--r--OpenSim/Data/MySQL/MySQLHGTravelData.cs80
-rw-r--r--OpenSim/Data/MySQL/MySQLOfflineIMData.cs7
-rw-r--r--OpenSim/Data/MySQL/MySQLRegionData.cs5
-rw-r--r--OpenSim/Data/MySQL/MySQLSimulationData.cs31
-rw-r--r--OpenSim/Data/MySQL/MySQLUserProfilesData.cs1102
-rw-r--r--OpenSim/Data/MySQL/MySQLXAssetData.cs2
-rw-r--r--OpenSim/Data/MySQL/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/MySQL/Resources/EstateStore.migrations6
-rw-r--r--OpenSim/Data/MySQL/Resources/FriendsStore.migrations2
-rw-r--r--OpenSim/Data/MySQL/Resources/HGTravelStore.migrations18
-rw-r--r--OpenSim/Data/MySQL/Resources/IM_Store.migrations12
-rw-r--r--OpenSim/Data/MySQL/Resources/RegionStore.migrations17
-rw-r--r--OpenSim/Data/MySQL/Resources/UserProfiles.migrations83
-rwxr-xr-xOpenSim/Data/Null/NullEstateData.cs28
-rw-r--r--OpenSim/Data/Null/NullRegionData.cs5
-rw-r--r--OpenSim/Data/Null/NullSimulationData.cs20
-rw-r--r--OpenSim/Data/Null/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/PGSQL/PGSQLAssetData.cs296
-rw-r--r--OpenSim/Data/PGSQL/PGSQLAuthenticationData.cs254
-rw-r--r--OpenSim/Data/PGSQL/PGSQLAvatarData.cs72
-rw-r--r--OpenSim/Data/PGSQL/PGSQLEstateData.cs602
-rw-r--r--OpenSim/Data/PGSQL/PGSQLFramework.cs111
-rw-r--r--OpenSim/Data/PGSQL/PGSQLFriendsData.cs116
-rw-r--r--OpenSim/Data/PGSQL/PGSQLGenericTableHandler.cs519
-rw-r--r--OpenSim/Data/PGSQL/PGSQLGridUserData.cs68
-rw-r--r--OpenSim/Data/PGSQL/PGSQLGroupsData.cs481
-rw-r--r--OpenSim/Data/PGSQL/PGSQLHGTravelData.cs80
-rw-r--r--OpenSim/Data/PGSQL/PGSQLInventoryData.cs831
-rw-r--r--OpenSim/Data/PGSQL/PGSQLManager.cs350
-rw-r--r--OpenSim/Data/PGSQL/PGSQLMigration.cs102
-rw-r--r--OpenSim/Data/PGSQL/PGSQLOfflineIMData.cs56
-rw-r--r--OpenSim/Data/PGSQL/PGSQLPresenceData.cs115
-rw-r--r--OpenSim/Data/PGSQL/PGSQLRegionData.cs392
-rw-r--r--OpenSim/Data/PGSQL/PGSQLSimulationData.cs2253
-rw-r--r--OpenSim/Data/PGSQL/PGSQLUserAccountData.cs330
-rw-r--r--OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs1073
-rw-r--r--OpenSim/Data/PGSQL/PGSQLXAssetData.cs535
-rw-r--r--OpenSim/Data/PGSQL/PGSQLXInventoryData.cs330
-rw-r--r--OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs65
-rw-r--r--OpenSim/Data/PGSQL/Resources/AssetStore.migrations94
-rw-r--r--OpenSim/Data/PGSQL/Resources/AuthStore.migrations32
-rw-r--r--OpenSim/Data/PGSQL/Resources/Avatar.migrations59
-rw-r--r--OpenSim/Data/PGSQL/Resources/EstateStore.migrations307
-rw-r--r--OpenSim/Data/PGSQL/Resources/FriendsStore.migrations44
-rw-r--r--OpenSim/Data/PGSQL/Resources/GridStore.migrations242
-rw-r--r--OpenSim/Data/PGSQL/Resources/GridUserStore.migrations60
-rw-r--r--OpenSim/Data/PGSQL/Resources/HGTravelStore.migrations17
-rw-r--r--OpenSim/Data/PGSQL/Resources/IM_Store.migrations26
-rw-r--r--OpenSim/Data/PGSQL/Resources/InventoryStore.migrations220
-rw-r--r--OpenSim/Data/PGSQL/Resources/LogStore.migrations16
-rw-r--r--OpenSim/Data/PGSQL/Resources/Presence.migrations30
-rw-r--r--OpenSim/Data/PGSQL/Resources/RegionStore.migrations1154
-rw-r--r--OpenSim/Data/PGSQL/Resources/UserAccount.migrations51
-rw-r--r--OpenSim/Data/PGSQL/Resources/UserProfiles.migrations83
-rw-r--r--OpenSim/Data/PGSQL/Resources/UserStore.migrations404
-rw-r--r--OpenSim/Data/PGSQL/Resources/XAssetStore.migrations27
-rw-r--r--OpenSim/Data/PGSQL/Resources/os_groups_Store.migrations94
-rw-r--r--OpenSim/Data/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/SQLite/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Data/SQLite/Resources/EstateStore.migrations9
-rw-r--r--OpenSim/Data/SQLite/Resources/HGTravelStore.migrations18
-rw-r--r--OpenSim/Data/SQLite/Resources/RegionStore.migrations20
-rw-r--r--OpenSim/Data/SQLite/Resources/UserProfiles.migrations90
-rw-r--r--OpenSim/Data/SQLite/SQLiteGridUserData.cs4
-rw-r--r--OpenSim/Data/SQLite/SQLiteHGTravelData.cs82
-rw-r--r--OpenSim/Data/SQLite/SQLiteSimulationData.cs40
-rw-r--r--OpenSim/Data/SQLite/SQLiteUserProfilesData.cs988
-rw-r--r--OpenSim/Framework/AgentCircuitData.cs26
-rw-r--r--OpenSim/Framework/Animation.cs19
-rw-r--r--OpenSim/Framework/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/BasicDOSProtector.cs275
-rw-r--r--OpenSim/Framework/BlockingQueue.cs36
-rw-r--r--OpenSim/Framework/CachedTextureEventArg.cs46
-rw-r--r--OpenSim/Framework/ChildAgentDataUpdate.cs20
-rw-r--r--OpenSim/Framework/CircularBuffer.cs312
-rw-r--r--OpenSim/Framework/ClientInfo.cs11
-rw-r--r--OpenSim/Framework/Communications/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/ConfigSettings.cs1
-rw-r--r--OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Configuration/XML/XmlConfiguration.cs2
-rw-r--r--OpenSim/Framework/Console/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Console/ConsoleUtil.cs47
-rw-r--r--OpenSim/Framework/Console/LocalConsole.cs15
-rw-r--r--OpenSim/Framework/Console/RemoteConsole.cs2
-rw-r--r--OpenSim/Framework/Constants.cs11
-rw-r--r--OpenSim/Framework/DAMap.cs295
-rw-r--r--OpenSim/Framework/DOMap.cs8
-rw-r--r--OpenSim/Framework/EstateSettings.cs1
-rw-r--r--OpenSim/Framework/IClientAPI.cs11
-rw-r--r--OpenSim/Framework/IImprovedAssetCache.cs26
-rw-r--r--OpenSim/Framework/IPeople.cs47
-rw-r--r--OpenSim/Framework/IScene.cs21
-rw-r--r--OpenSim/Framework/InventoryItemBase.cs2
-rw-r--r--OpenSim/Framework/Location.cs16
-rw-r--r--OpenSim/Framework/Monitoring/BaseStatsCollector.cs14
-rw-r--r--OpenSim/Framework/Monitoring/Checks/Check.cs118
-rw-r--r--OpenSim/Framework/Monitoring/ChecksManager.cs262
-rw-r--r--OpenSim/Framework/Monitoring/MemoryWatchdog.cs8
-rw-r--r--OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Monitoring/ServerStatsCollector.cs349
-rw-r--r--OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs25
-rwxr-xr-xOpenSim/Framework/Monitoring/Stats/CounterStat.cs163
-rwxr-xr-xOpenSim/Framework/Monitoring/Stats/EventHistogram.cs173
-rw-r--r--OpenSim/Framework/Monitoring/Stats/PercentageStat.cs16
-rw-r--r--OpenSim/Framework/Monitoring/Stats/Stat.cs79
-rw-r--r--OpenSim/Framework/Monitoring/StatsLogger.cs108
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs334
-rw-r--r--OpenSim/Framework/Monitoring/Watchdog.cs1
-rw-r--r--OpenSim/Framework/PermissionsUtil.cs87
-rw-r--r--OpenSim/Framework/PrimitiveBaseShape.cs11
-rw-r--r--OpenSim/Framework/RegionFlags.cs3
-rw-r--r--OpenSim/Framework/RegionInfo.cs172
-rw-r--r--OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/RegionSettings.cs25
-rw-r--r--OpenSim/Framework/SLUtil.cs70
-rw-r--r--OpenSim/Framework/Serialization/ArchiveConstants.cs3
-rw-r--r--OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs2
-rw-r--r--OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs50
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs59
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseOutputStreamHandler.cs60
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs4
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs27
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs107
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs119
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs15
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs18
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs45
-rw-r--r--OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs16
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs4
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestSessionService.cs13
-rw-r--r--OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs2
-rw-r--r--OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs87
-rw-r--r--OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs91
-rw-r--r--OpenSim/Framework/Servers/MainServer.cs13
-rw-r--r--OpenSim/Framework/Servers/ServerBase.cs254
-rw-r--r--OpenSim/Framework/Servers/VersionInfo.cs2
-rw-r--r--OpenSim/Framework/TaskInventoryItem.cs2
-rw-r--r--OpenSim/Framework/Tests/LocationTest.cs21
-rw-r--r--OpenSim/Framework/Tests/MundaneFrameworkTests.cs2
-rw-r--r--OpenSim/Framework/Tests/UtilTest.cs82
-rw-r--r--OpenSim/Framework/UserProfiles.cs117
-rw-r--r--OpenSim/Framework/Util.cs192
-rw-r--r--OpenSim/Framework/WebUtil.cs82
-rw-r--r--OpenSim/Region/Application/Application.cs42
-rw-r--r--OpenSim/Region/Application/ConfigurationLoader.cs76
-rw-r--r--OpenSim/Region/Application/OpenSim.cs297
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs92
-rw-r--r--OpenSim/Region/ClientStack/IClientNetworkServer.cs15
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs136
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs27
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs147
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs36
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs8
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs6
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs20
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs1
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs26
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs44
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs115
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs719
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs7
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs110
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs628
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs111
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs25
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs6
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs16
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs6
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs9
-rw-r--r--OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs6
-rw-r--r--OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs3
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs264
-rw-r--r--OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs129
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs129
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs59
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs65
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs23
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs16
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs12
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs24
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs36
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs12
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs111
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs449
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs1343
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs426
-rw-r--r--OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs353
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs42
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs19
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs69
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs211
-rw-r--r--OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs197
-rw-r--r--OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs256
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs76
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs401
-rw-r--r--OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs66
-rw-r--r--OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs9
-rw-r--r--OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs198
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs21
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs226
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs46
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs49
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs20
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs5
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs7
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs66
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs3
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs26
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs79
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs73
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs12
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs33
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs61
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs218
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs256
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs298
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs227
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs27
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs538
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs27
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs19
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs30
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs44
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs9
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/WindModule.cs38
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs147
-rw-r--r--OpenSim/Region/DataSnapshot/DataRequestHandler.cs4
-rw-r--r--OpenSim/Region/DataSnapshot/DataSnapshotManager.cs2
-rw-r--r--OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/DataSnapshot/SnapshotStore.cs12
-rw-r--r--OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs33
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs20
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEventQueue.cs11
-rw-r--r--OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs48
-rw-r--r--OpenSim/Region/Framework/Interfaces/IGroupsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInterregionComms.cs119
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs19
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISoundModule.cs8
-rw-r--r--OpenSim/Region/Framework/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs114
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs36
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs66
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs60
-rw-r--r--OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs185
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs39
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs823
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs34
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs49
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs192
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs738
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs113
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs86
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs111
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs90
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs175
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs71
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs119
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs12
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs167
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs13
-rw-r--r--OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs163
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs6
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs220
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs18
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs67
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs195
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs5
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs65
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs5
-rw-r--r--OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs339
-rw-r--r--OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs590
-rw-r--r--OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs2
-rwxr-xr-xOpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs432
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs195
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs41
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs41
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs10
-rw-r--r--OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs38
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs26
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs18
-rw-r--r--OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs2
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs9
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs145
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs430
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs411
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs173
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs136
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs219
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs137
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs138
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActors.cs67
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs72
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs527
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs25
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs54
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs55
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs103
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs490
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs240
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs393
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs730
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs97
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs350
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs404
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs741
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs121
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs230
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs381
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs998
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapes.cs1163
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs33
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs82
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs56
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs51
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt131
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs34
-rw-r--r--OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/Manager/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsActor.cs6
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs10
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs265
-rw-r--r--OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs1
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs2
-rw-r--r--OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs6
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs83
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs326
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs227
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs51
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs25
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs27
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs25
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/LSL2CSCodeTransformer.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/LSL_EventTests.cs359
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/lsl.parser.cs18172
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs35
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs85
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs399
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs238
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs24
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs6
-rw-r--r--OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Server/Base/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Server/Base/ServerUtils.cs1
-rw-r--r--OpenSim/Server/Base/ServicesServerBase.cs25
-rw-r--r--OpenSim/Server/Handlers/Asset/AssetServerConnector.cs12
-rw-r--r--OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs2
-rw-r--r--OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs2
-rw-r--r--OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs2
-rw-r--r--OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs2
-rw-r--r--OpenSim/Server/Handlers/Authentication/OpenIdServerHandler.cs30
-rw-r--r--OpenSim/Server/Handlers/Authorization/AuthorizationServerPostHandler.cs2
-rw-r--r--OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs2
-rw-r--r--OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs2
-rw-r--r--OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs35
-rw-r--r--OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs8
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs2
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/GatekeeperServerConnector.cs8
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs2
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/HeloServerConnector.cs2
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs201
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs7
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs15
-rw-r--r--OpenSim/Server/Handlers/Inventory/InventoryServerMoveItemsHandler.cs2
-rw-r--r--OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs4
-rw-r--r--OpenSim/Server/Handlers/Login/LLLoginHandlers.cs67
-rw-r--r--OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs25
-rw-r--r--OpenSim/Server/Handlers/Map/MapAddServerConnector.cs2
-rw-r--r--OpenSim/Server/Handlers/Map/MapGetServerConnector.cs2
-rw-r--r--OpenSim/Server/Handlers/Neighbour/NeighbourHandlers.cs8
-rw-r--r--OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs2
-rw-r--r--OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs112
-rw-r--r--OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs461
-rw-r--r--OpenSim/Server/Handlers/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Server/Handlers/Simulation/AgentHandlers.cs182
-rw-r--r--OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs2
-rw-r--r--OpenSim/Services/AssetService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/AssetService/XAssetService.cs7
-rw-r--r--OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Base/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs6
-rw-r--r--OpenSim/Services/Connectors/Grid/GridServicesConnector.cs51
-rw-r--r--OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs2
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs68
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/HGFriendsServicesConnector.cs2
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs140
-rw-r--r--OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs1
-rw-r--r--OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs124
-rw-r--r--OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs19
-rw-r--r--OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs10
-rw-r--r--OpenSim/Services/Connectors/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs507
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs12
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs8
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs180
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs8
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs114
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs131
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs30
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs30
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs212
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs6
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs8
-rw-r--r--OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs102
-rw-r--r--OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/Friends/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/GridService/GridService.cs99
-rw-r--r--OpenSim/Services/GridService/HypergridLinker.cs2
-rw-r--r--OpenSim/Services/GridService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/HypergridService/GatekeeperService.cs43
-rw-r--r--OpenSim/Services/HypergridService/HGInventoryService.cs2
-rw-r--r--OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs69
-rw-r--r--OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/HypergridService/UserAgentService.cs216
-rw-r--r--OpenSim/Services/HypergridService/UserAgentServiceBase.cs84
-rw-r--r--OpenSim/Services/Interfaces/IBansService.cs48
-rw-r--r--OpenSim/Services/Interfaces/IGridService.cs47
-rw-r--r--OpenSim/Services/Interfaces/IHypergridServices.cs8
-rw-r--r--OpenSim/Services/Interfaces/IOfflineIMService.cs7
-rw-r--r--OpenSim/Services/Interfaces/ISimulationService.cs12
-rw-r--r--OpenSim/Services/Interfaces/IUserProfilesService.cs75
-rw-r--r--OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginResponse.cs44
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginService.cs14
-rw-r--r--OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/MapImageService/MapImageService.cs2
-rw-r--r--OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/UserAccountService/GridUserService.cs63
-rw-r--r--OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Services/UserProfilesService/UserProfilesService.cs262
-rw-r--r--OpenSim/Services/UserProfilesService/UserProfilesServiceBase.cs86
-rw-r--r--OpenSim/Tests/Clients/Assets/AssetsClient.cs126
-rw-r--r--OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs47
-rw-r--r--OpenSim/Tests/Common/Helpers/SceneHelpers.cs56
-rw-r--r--OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs41
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs84
-rw-r--r--OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs14
-rw-r--r--OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs28
-rw-r--r--OpenSim/Tests/Common/OpenSimTestCase.cs12
-rw-r--r--OpenSim/Tests/Common/TestHelpers.cs21
-rw-r--r--OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Tools/Configger/ConfigurationLoader.cs6
-rw-r--r--OpenSim/Tools/Configger/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Tools/OpenSim.32BitLaunch/OpenSim.32BitLaunch.csproj141
-rw-r--r--OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.csproj147
-rw-r--r--OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.sln40
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs7
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/CrossBehaviour.cs6
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs9
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs47
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs7
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs9
-rw-r--r--OpenSim/Tools/pCampBot/Bot.cs263
-rw-r--r--OpenSim/Tools/pCampBot/BotManager.cs768
-rw-r--r--OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs13
-rw-r--r--OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs2
-rw-r--r--OpenSim/Tools/pCampBot/pCampBot.cs89
577 files changed, 55262 insertions, 18116 deletions
diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs
index 59fec6f..653dbac 100644
--- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs
+++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnector.cs
@@ -101,7 +101,7 @@ namespace OpenSim.Groups
101 Dictionary<string, object> sendData = new Dictionary<string, object>(); 101 Dictionary<string, object> sendData = new Dictionary<string, object>();
102 if (GroupID != UUID.Zero) 102 if (GroupID != UUID.Zero)
103 sendData["GroupID"] = GroupID.ToString(); 103 sendData["GroupID"] = GroupID.ToString();
104 if (GroupName != null && GroupName != string.Empty) 104 if (!string.IsNullOrEmpty(GroupName))
105 sendData["Name"] = GroupsDataUtils.Sanitize(GroupName); 105 sendData["Name"] = GroupsDataUtils.Sanitize(GroupName);
106 106
107 sendData["RequestingAgentID"] = RequestingAgentID; 107 sendData["RequestingAgentID"] = RequestingAgentID;
@@ -275,7 +275,7 @@ namespace OpenSim.Groups
275 275
276 //m_log.DebugFormat("[XXX]: reply was {0}", reply); 276 //m_log.DebugFormat("[XXX]: reply was {0}", reply);
277 277
278 if (reply == string.Empty || reply == null) 278 if (string.IsNullOrEmpty(reply))
279 return null; 279 return null;
280 280
281 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse( 281 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
diff --git a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs
index 4642b2a..7d48516 100644
--- a/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs
+++ b/OpenSim/Addons/Groups/Hypergrid/GroupsServiceHGConnectorModule.cs
@@ -623,10 +623,13 @@ namespace OpenSim.Groups
623 if (agent != null) 623 if (agent != null)
624 break; 624 break;
625 } 625 }
626 if (agent == null) // oops 626 if (agent != null)
627 return AgentID.ToString(); 627 return Util.ProduceUserUniversalIdentifier(agent);
628
629 // we don't know anything about this foreign user
630 // try asking the user management module, which may know more
631 return m_UserManagement.GetUserUUI(AgentID);
628 632
629 return Util.ProduceUserUniversalIdentifier(agent);
630 } 633 }
631 634
632 private string AgentUUIForOutside(string AgentIDStr) 635 private string AgentUUIForOutside(string AgentIDStr)
diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs
index 6f58922..d2bcba5 100644
--- a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs
+++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs
@@ -112,7 +112,7 @@ namespace OpenSim.Groups
112 m_GroupsService = service; 112 m_GroupsService = service;
113 } 113 }
114 114
115 public override byte[] Handle(string path, Stream requestData, 115 protected override byte[] ProcessRequest(string path, Stream requestData,
116 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 116 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
117 { 117 {
118 StreamReader sr = new StreamReader(requestData); 118 StreamReader sr = new StreamReader(requestData);
diff --git a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs
index 5ccd7fe..16fe03b 100644
--- a/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs
+++ b/OpenSim/Addons/Groups/Properties/AssemblyInfo.cs
@@ -30,7 +30,7 @@ using Mono.Addins;
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.7.6.*")] 33[assembly: AssemblyVersion("0.8.0.*")]
34 34
35[assembly: Addin("OpenSim.Groups", "0.1")] 35[assembly: Addin("OpenSim.Groups", "0.1")]
36[assembly: AddinDependency("OpenSim", "0.5")] 36[assembly: AddinDependency("OpenSim", "0.5")]
diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs
index 161ca0c..ed41978 100644
--- a/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs
+++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRemoteConnector.cs
@@ -120,7 +120,7 @@ namespace OpenSim.Groups
120 Dictionary<string, object> sendData = new Dictionary<string, object>(); 120 Dictionary<string, object> sendData = new Dictionary<string, object>();
121 if (GroupID != UUID.Zero) 121 if (GroupID != UUID.Zero)
122 sendData["GroupID"] = GroupID.ToString(); 122 sendData["GroupID"] = GroupID.ToString();
123 if (GroupName != null && GroupName != string.Empty) 123 if (!string.IsNullOrEmpty(GroupName))
124 sendData["Name"] = GroupsDataUtils.Sanitize(GroupName); 124 sendData["Name"] = GroupsDataUtils.Sanitize(GroupName);
125 125
126 sendData["RequestingAgentID"] = RequestingAgentID; 126 sendData["RequestingAgentID"] = RequestingAgentID;
diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs
index 7e55d3c..249d974 100644
--- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs
+++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs
@@ -75,7 +75,7 @@ namespace OpenSim.Groups
75 m_GroupsService = service; 75 m_GroupsService = service;
76 } 76 }
77 77
78 public override byte[] Handle(string path, Stream requestData, 78 protected override byte[] ProcessRequest(string path, Stream requestData,
79 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 79 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
80 { 80 {
81 StreamReader sr = new StreamReader(requestData); 81 StreamReader sr = new StreamReader(requestData);
diff --git a/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs
index 050ebd2..5ef068a 100644
--- a/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs
+++ b/OpenSim/Addons/OfflineIM/OfflineIMRegionModule.cs
@@ -261,6 +261,11 @@ namespace OpenSim.OfflineIM
261 return m_OfflineIMService.StoreMessage(im, out reason); 261 return m_OfflineIMService.StoreMessage(im, out reason);
262 } 262 }
263 263
264 public void DeleteMessages(UUID userID)
265 {
266 m_OfflineIMService.DeleteMessages(userID);
267 }
268
264 #endregion 269 #endregion
265 } 270 }
266} 271}
diff --git a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs
index ffe8a3e..5d71edc 100644
--- a/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs
+++ b/OpenSim/Addons/OfflineIM/Properties/AssemblyInfo.cs
@@ -30,7 +30,7 @@ using Mono.Addins;
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.7.6.*")] 33[assembly: AssemblyVersion("0.8.0.*")]
34 34
35[assembly: Addin("OpenSim.OfflineIM", "0.1")] 35[assembly: Addin("OpenSim.OfflineIM", "0.1")]
36[assembly: AddinDependency("OpenSim", "0.5")] 36[assembly: AddinDependency("OpenSim", "0.5")]
diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs
index 69feb76..f6b17e5 100644
--- a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs
+++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRemoteConnector.cs
@@ -117,6 +117,14 @@ namespace OpenSim.OfflineIM
117 return true; 117 return true;
118 } 118 }
119 119
120 public void DeleteMessages(UUID userID)
121 {
122 Dictionary<string, object> sendData = new Dictionary<string, object>();
123 sendData["UserID"] = userID;
124
125 MakeRequest("DELETE", sendData);
126 }
127
120 #endregion 128 #endregion
121 129
122 130
diff --git a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs
index 2b3a01d..13b0e7e 100644
--- a/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.cs
+++ b/OpenSim/Addons/OfflineIM/Remote/OfflineIMServiceRobustConnector.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 *
@@ -75,7 +75,7 @@ namespace OpenSim.OfflineIM
75 m_OfflineIMService = service; 75 m_OfflineIMService = service;
76 } 76 }
77 77
78 public override byte[] Handle(string path, Stream requestData, 78 protected override byte[] ProcessRequest(string path, Stream requestData,
79 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 79 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
80 { 80 {
81 StreamReader sr = new StreamReader(requestData); 81 StreamReader sr = new StreamReader(requestData);
@@ -96,13 +96,14 @@ namespace OpenSim.OfflineIM
96 string method = request["METHOD"].ToString(); 96 string method = request["METHOD"].ToString();
97 request.Remove("METHOD"); 97 request.Remove("METHOD");
98 98
99 m_log.DebugFormat("[OfflineIM.V2.Handler]: {0}", method);
100 switch (method) 99 switch (method)
101 { 100 {
102 case "GET": 101 case "GET":
103 return HandleGet(request); 102 return HandleGet(request);
104 case "STORE": 103 case "STORE":
105 return HandleStore(request); 104 return HandleStore(request);
105 case "DELETE":
106 return HandleDelete(request);
106 } 107 }
107 m_log.DebugFormat("[OFFLINE IM HANDLER]: unknown method request: {0}", method); 108 m_log.DebugFormat("[OFFLINE IM HANDLER]: unknown method request: {0}", method);
108 } 109 }
@@ -159,6 +160,21 @@ namespace OpenSim.OfflineIM
159 return Util.UTF8NoBomEncoding.GetBytes(xmlString); 160 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
160 } 161 }
161 162
163 byte[] HandleDelete(Dictionary<string, object> request)
164 {
165 if (!request.ContainsKey("UserID"))
166 {
167 return FailureResult();
168 }
169 else
170 {
171 UUID userID = new UUID(request["UserID"].ToString());
172 m_OfflineIMService.DeleteMessages(userID);
173
174 return SuccessResult();
175 }
176 }
177
162 #region Helpers 178 #region Helpers
163 179
164 private void NullResult(Dictionary<string, object> result, string reason) 180 private void NullResult(Dictionary<string, object> result, string reason)
diff --git a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs
index 6ba022c..690c955 100644
--- a/OpenSim/Addons/OfflineIM/Service/OfflineIMService.cs
+++ b/OpenSim/Addons/OfflineIM/Service/OfflineIMService.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 *
@@ -46,7 +46,7 @@ namespace OpenSim.OfflineIM
46{ 46{
47 public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService 47 public class OfflineIMService : OfflineIMServiceBase, IOfflineIMService
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);
50 private const int MAX_IM = 25; 50 private const int MAX_IM = 25;
51 51
52 private XmlSerializer m_serializer; 52 private XmlSerializer m_serializer;
@@ -91,7 +91,7 @@ namespace OpenSim.OfflineIM
91 { 91 {
92 reason = string.Empty; 92 reason = string.Empty;
93 93
94 // TODO Check limits 94 // Check limits
95 UUID principalID = new UUID(im.toAgentID); 95 UUID principalID = new UUID(im.toAgentID);
96 long count = m_Database.GetCount("PrincipalID", principalID.ToString()); 96 long count = m_Database.GetCount("PrincipalID", principalID.ToString());
97 if (count >= MAX_IM) 97 if (count >= MAX_IM)
@@ -100,7 +100,7 @@ namespace OpenSim.OfflineIM
100 return false; 100 return false;
101 } 101 }
102 102
103 string imXml = string.Empty; 103 string imXml;
104 using (MemoryStream mstream = new MemoryStream()) 104 using (MemoryStream mstream = new MemoryStream())
105 { 105 {
106 XmlWriterSettings settings = new XmlWriterSettings(); 106 XmlWriterSettings settings = new XmlWriterSettings();
@@ -110,22 +110,26 @@ namespace OpenSim.OfflineIM
110 { 110 {
111 m_serializer.Serialize(writer, im); 111 m_serializer.Serialize(writer, im);
112 writer.Flush(); 112 writer.Flush();
113
114 mstream.Position = 0;
115 using (StreamReader sreader = new StreamReader(mstream))
116 {
117 imXml = sreader.ReadToEnd();
118 }
119 } 113 }
114
115 imXml = Util.UTF8.GetString(mstream.ToArray());
120 } 116 }
121 117
122 OfflineIMData data = new OfflineIMData(); 118 OfflineIMData data = new OfflineIMData();
123 data.PrincipalID = principalID; 119 data.PrincipalID = principalID;
120 data.FromID = new UUID(im.fromAgentID);
124 data.Data = new Dictionary<string, string>(); 121 data.Data = new Dictionary<string, string>();
125 data.Data["Message"] = imXml; 122 data.Data["Message"] = imXml;
126 123
127 return m_Database.Store(data); 124 return m_Database.Store(data);
128 125
129 } 126 }
127
128 public void DeleteMessages(UUID userID)
129 {
130 m_Database.Delete("PrincipalID", userID.ToString());
131 m_Database.Delete("FromID", userID.ToString());
132 }
133
130 } 134 }
131} 135}
diff --git a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs
index fcb6991..1d63d26 100644
--- a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs
+++ b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs
@@ -115,6 +115,8 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
115 Environment.Exit(1); 115 Environment.Exit(1);
116 } 116 }
117 117
118 List<IScene> createdScenes = new List<IScene>();
119
118 for (int i = 0; i < regionsToLoad.Length; i++) 120 for (int i = 0; i < regionsToLoad.Length; i++)
119 { 121 {
120 IScene scene; 122 IScene scene;
@@ -123,17 +125,22 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
123 ")"); 125 ")");
124 126
125 bool changed = m_openSim.PopulateRegionEstateInfo(regionsToLoad[i]); 127 bool changed = m_openSim.PopulateRegionEstateInfo(regionsToLoad[i]);
128
126 m_openSim.CreateRegion(regionsToLoad[i], true, out scene); 129 m_openSim.CreateRegion(regionsToLoad[i], true, out scene);
130 createdScenes.Add(scene);
131
127 if (changed) 132 if (changed)
128 regionsToLoad[i].EstateSettings.Save(); 133 regionsToLoad[i].EstateSettings.Save();
129 134 }
130 if (scene != null) 135
136 foreach (IScene scene in createdScenes)
137 {
138 scene.Start();
139
140 m_newRegionCreatedHandler = OnNewRegionCreated;
141 if (m_newRegionCreatedHandler != null)
131 { 142 {
132 m_newRegionCreatedHandler = OnNewRegionCreated; 143 m_newRegionCreatedHandler(scene);
133 if (m_newRegionCreatedHandler != null)
134 {
135 m_newRegionCreatedHandler(scene);
136 }
137 } 144 }
138 } 145 }
139 } 146 }
diff --git a/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
index 1b6a3e1..4968e7b 100644
--- a/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
+++ b/OpenSim/ApplicationPlugins/LoadRegions/Properties/AssemblyInfo.cs
@@ -62,4 +62,4 @@ using System.Runtime.InteropServices;
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63// [assembly: AssemblyVersion("0.7.6.*")] 63// [assembly: AssemblyVersion("0.7.6.*")]
64 64
65[assembly : AssemblyVersion("0.7.6.*")] 65[assembly : AssemblyVersion("0.8.0.*")]
diff --git a/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs
index 5683a72..ddef158 100644
--- a/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs
+++ b/OpenSim/ApplicationPlugins/RegionModulesController/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs b/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs
index a9d3f74..dd34cc8 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index e50dac6..cf2e037 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Globalization;
31using System.IO; 32using System.IO;
32using System.Xml; 33using System.Xml;
33using System.Net; 34using System.Net;
@@ -51,6 +52,7 @@ using OpenSim.Services.Interfaces;
51using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; 52using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
52using GridRegion = OpenSim.Services.Interfaces.GridRegion; 53using GridRegion = OpenSim.Services.Interfaces.GridRegion;
53using PermissionMask = OpenSim.Framework.PermissionMask; 54using PermissionMask = OpenSim.Framework.PermissionMask;
55using RegionInfo = OpenSim.Framework.RegionInfo;
54 56
55namespace OpenSim.ApplicationPlugins.RemoteController 57namespace OpenSim.ApplicationPlugins.RemoteController
56{ 58{
@@ -149,6 +151,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
149 availableMethods["admin_create_user_email"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcCreateUserMethod); 151 availableMethods["admin_create_user_email"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcCreateUserMethod);
150 availableMethods["admin_exists_user"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcUserExistsMethod); 152 availableMethods["admin_exists_user"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcUserExistsMethod);
151 availableMethods["admin_update_user"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcUpdateUserAccountMethod); 153 availableMethods["admin_update_user"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcUpdateUserAccountMethod);
154 availableMethods["admin_authenticate_user"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAuthenticateUserMethod);
152 155
153 // Region state management 156 // Region state management
154 availableMethods["admin_load_xml"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcLoadXMLMethod); 157 availableMethods["admin_load_xml"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcLoadXMLMethod);
@@ -161,6 +164,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
161 availableMethods["admin_acl_add"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListAdd); 164 availableMethods["admin_acl_add"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListAdd);
162 availableMethods["admin_acl_remove"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListRemove); 165 availableMethods["admin_acl_remove"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListRemove);
163 availableMethods["admin_acl_list"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListList); 166 availableMethods["admin_acl_list"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAccessListList);
167 availableMethods["admin_estate_reload"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcEstateReload);
164 168
165 // Misc 169 // Misc
166 availableMethods["admin_refresh_search"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRefreshSearch); 170 availableMethods["admin_refresh_search"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcRefreshSearch);
@@ -438,18 +442,26 @@ namespace OpenSim.ApplicationPlugins.RemoteController
438 // k, (string)requestData[k], ((string)requestData[k]).Length); 442 // k, (string)requestData[k], ((string)requestData[k]).Length);
439 // } 443 // }
440 444
441 CheckStringParameters(requestData, responseData, new string[] {"filename", "regionid"}); 445 CheckStringParameters(requestData, responseData, new string[] { "filename" });
442 CheckRegionParams(requestData, responseData); 446 CheckRegionParams(requestData, responseData);
443 447
444 Scene scene = null; 448 Scene scene = null;
445 GetSceneFromRegionParams(requestData, responseData, out scene); 449 GetSceneFromRegionParams(requestData, responseData, out scene);
446 string file = (string)requestData["filename"];
447 450
448 responseData["accepted"] = true; 451 if (scene != null)
452 {
453 string file = (string)requestData["filename"];
449 454
450 LoadHeightmap(file, scene.RegionInfo.RegionID); 455 responseData["accepted"] = true;
451 456
452 responseData["success"] = true; 457 LoadHeightmap(file, scene.RegionInfo.RegionID);
458
459 responseData["success"] = true;
460 }
461 else
462 {
463 responseData["success"] = false;
464 }
453 465
454 m_log.Info("[RADMIN]: Load height maps request complete"); 466 m_log.Info("[RADMIN]: Load height maps request complete");
455 } 467 }
@@ -463,23 +475,30 @@ namespace OpenSim.ApplicationPlugins.RemoteController
463 475
464// m_log.DebugFormat("[RADMIN]: Save Terrain: XmlRpc {0}", request.ToString()); 476// m_log.DebugFormat("[RADMIN]: Save Terrain: XmlRpc {0}", request.ToString());
465 477
466 CheckStringParameters(requestData, responseData, new string[] { "filename", "regionid" }); 478 CheckStringParameters(requestData, responseData, new string[] { "filename" });
467 CheckRegionParams(requestData, responseData); 479 CheckRegionParams(requestData, responseData);
468 480
469 Scene region = null; 481 Scene scene = null;
470 GetSceneFromRegionParams(requestData, responseData, out region); 482 GetSceneFromRegionParams(requestData, responseData, out scene);
471 483
472 string file = (string)requestData["filename"]; 484 if (scene != null)
473 m_log.InfoFormat("[RADMIN]: Terrain Saving: {0}", file); 485 {
486 string file = (string)requestData["filename"];
487 m_log.InfoFormat("[RADMIN]: Terrain Saving: {0}", file);
474 488
475 responseData["accepted"] = true; 489 responseData["accepted"] = true;
476 490
477 ITerrainModule terrainModule = region.RequestModuleInterface<ITerrainModule>(); 491 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
478 if (null == terrainModule) throw new Exception("terrain module not available"); 492 if (null == terrainModule) throw new Exception("terrain module not available");
479 493
480 terrainModule.SaveToFile(file); 494 terrainModule.SaveToFile(file);
481 495
482 responseData["success"] = true; 496 responseData["success"] = true;
497 }
498 else
499 {
500 responseData["success"] = false;
501 }
483 502
484 m_log.Info("[RADMIN]: Save height maps request complete"); 503 m_log.Info("[RADMIN]: Save height maps request complete");
485 } 504 }
@@ -831,6 +850,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
831 850
832 IScene newScene; 851 IScene newScene;
833 m_application.CreateRegion(region, out newScene); 852 m_application.CreateRegion(region, out newScene);
853 newScene.Start();
834 854
835 // If an access specification was provided, use it. 855 // If an access specification was provided, use it.
836 // Otherwise accept the default. 856 // Otherwise accept the default.
@@ -1225,7 +1245,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1225 { 1245 {
1226 GridUserInfo userInfo = m_application.SceneManager.CurrentOrFirstScene.GridUserService.GetGridUserInfo(account.PrincipalID.ToString()); 1246 GridUserInfo userInfo = m_application.SceneManager.CurrentOrFirstScene.GridUserService.GetGridUserInfo(account.PrincipalID.ToString());
1227 if (userInfo != null) 1247 if (userInfo != null)
1228 responseData["lastlogin"] = userInfo.Login; 1248 responseData["lastlogin"] = Util.ToUnixTime(userInfo.Login);
1229 else 1249 else
1230 responseData["lastlogin"] = 0; 1250 responseData["lastlogin"] = 0;
1231 1251
@@ -1395,6 +1415,139 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1395 } 1415 }
1396 1416
1397 /// <summary> 1417 /// <summary>
1418 /// Authenticate an user.
1419 /// <summary>
1420 /// <param name="request">incoming XML RPC request</param>
1421 /// <remarks>
1422 /// XmlRpcAuthenticateUserMethod takes the following XMLRPC
1423 /// parameters
1424 /// <list type="table">
1425 /// <listheader><term>parameter name</term><description>description</description></listheader>
1426 /// <item><term>password</term>
1427 /// <description>admin password as set in OpenSim.ini</description></item>
1428 /// <item><term>user_firstname</term>
1429 /// <description>avatar's first name</description></item>
1430 /// <item><term>user_lastname</term>
1431 /// <description>avatar's last name</description></item>
1432 /// <item><term>user_password</term>
1433 /// <description>MD5 hash of avatar's password</description></item>
1434 /// <item><term>token_lifetime</term>
1435 /// <description>the lifetime of the returned token (upper bounded to 30s)</description></item>
1436 /// </list>
1437 ///
1438 /// XmlRpcAuthenticateUserMethod returns
1439 /// <list type="table">
1440 /// <listheader><term>name</term><description>description</description></listheader>
1441 /// <item><term>success</term>
1442 /// <description>true or false</description></item>
1443 /// <item><term>token</term>
1444 /// <description>the authentication token sent by OpenSim</description></item>
1445 /// <item><term>error</term>
1446 /// <description>error message if success is false</description></item>
1447 /// </list>
1448 /// </remarks>
1449 private void XmlRpcAuthenticateUserMethod(XmlRpcRequest request, XmlRpcResponse response,
1450 IPEndPoint remoteClient)
1451 {
1452 m_log.Info("[RADMIN]: AuthenticateUser: new request");
1453
1454 var responseData = (Hashtable)response.Value;
1455 var requestData = (Hashtable)request.Params[0];
1456
1457 lock (m_requestLock)
1458 {
1459 try
1460 {
1461 CheckStringParameters(requestData, responseData, new[]
1462 {
1463 "user_firstname",
1464 "user_lastname",
1465 "user_password",
1466 "token_lifetime"
1467 });
1468
1469 var firstName = (string)requestData["user_firstname"];
1470 var lastName = (string)requestData["user_lastname"];
1471 var password = (string)requestData["user_password"];
1472
1473 var scene = m_application.SceneManager.CurrentOrFirstScene;
1474
1475 if (scene.Equals(null))
1476 {
1477 m_log.Debug("scene does not exist");
1478 throw new Exception("Scene does not exist.");
1479 }
1480
1481 var scopeID = scene.RegionInfo.ScopeID;
1482 var account = scene.UserAccountService.GetUserAccount(scopeID, firstName, lastName);
1483
1484 if (account.Equals(null) || account.PrincipalID.Equals(UUID.Zero))
1485 {
1486 m_log.DebugFormat("avatar {0} {1} does not exist", firstName, lastName);
1487 throw new Exception(String.Format("avatar {0} {1} does not exist", firstName, lastName));
1488 }
1489
1490 if (String.IsNullOrEmpty(password))
1491 {
1492 m_log.DebugFormat("[RADMIN]: AuthenticateUser: no password provided for {0} {1}", firstName,
1493 lastName);
1494 throw new Exception(String.Format("no password provided for {0} {1}", firstName,
1495 lastName));
1496 }
1497
1498 int lifetime;
1499 if (int.TryParse((string)requestData["token_lifetime"], NumberStyles.Integer, CultureInfo.InvariantCulture, out lifetime) == false)
1500 {
1501 m_log.DebugFormat("[RADMIN]: AuthenticateUser: no token lifetime provided for {0} {1}", firstName,
1502 lastName);
1503 throw new Exception(String.Format("no token lifetime provided for {0} {1}", firstName,
1504 lastName));
1505 }
1506
1507 // Upper bound on lifetime set to 30s.
1508 if (lifetime > 30)
1509 {
1510 m_log.DebugFormat("[RADMIN]: AuthenticateUser: token lifetime longer than 30s for {0} {1}", firstName,
1511 lastName);
1512 throw new Exception(String.Format("token lifetime longer than 30s for {0} {1}", firstName,
1513 lastName));
1514 }
1515
1516 var authModule = scene.RequestModuleInterface<IAuthenticationService>();
1517 if (authModule == null)
1518 {
1519 m_log.Debug("[RADMIN]: AuthenticateUser: no authentication module loded");
1520 throw new Exception("no authentication module loaded");
1521 }
1522
1523 var token = authModule.Authenticate(account.PrincipalID, password, lifetime);
1524 if (String.IsNullOrEmpty(token))
1525 {
1526 m_log.DebugFormat("[RADMIN]: AuthenticateUser: authentication failed for {0} {1}", firstName,
1527 lastName);
1528 throw new Exception(String.Format("authentication failed for {0} {1}", firstName,
1529 lastName));
1530 }
1531
1532 m_log.DebugFormat("[RADMIN]: AuthenticateUser: account for user {0} {1} identified with token {2}",
1533 firstName, lastName, token);
1534
1535 responseData["token"] = token;
1536 responseData["success"] = true;
1537
1538 }
1539 catch (Exception e)
1540 {
1541 responseData["success"] = false;
1542 responseData["error"] = e.Message;
1543 throw e;
1544 }
1545
1546 m_log.Info("[RADMIN]: AuthenticateUser: request complete");
1547 }
1548 }
1549
1550 /// <summary>
1398 /// Load an OAR file into a region.. 1551 /// Load an OAR file into a region..
1399 /// <summary> 1552 /// <summary>
1400 /// <param name="request">incoming XML RPC request</param> 1553 /// <param name="request">incoming XML RPC request</param>
@@ -1522,7 +1675,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1522 /// </remarks> 1675 /// </remarks>
1523 private void XmlRpcSaveOARMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) 1676 private void XmlRpcSaveOARMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
1524 { 1677 {
1525 m_log.Info("[RADMIN]: Received Save OAR Administrator Request"); 1678 m_log.Info("[RADMIN]: Received Save OAR Request");
1526 1679
1527 Hashtable responseData = (Hashtable)response.Value; 1680 Hashtable responseData = (Hashtable)response.Value;
1528 Hashtable requestData = (Hashtable)request.Params[0]; 1681 Hashtable requestData = (Hashtable)request.Params[0];
@@ -1568,8 +1721,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1568 1721
1569 if (archiver != null) 1722 if (archiver != null)
1570 { 1723 {
1724 Guid requestId = Guid.NewGuid();
1571 scene.EventManager.OnOarFileSaved += RemoteAdminOarSaveCompleted; 1725 scene.EventManager.OnOarFileSaved += RemoteAdminOarSaveCompleted;
1572 archiver.ArchiveRegion(filename, options); 1726
1727 m_log.InfoFormat(
1728 "[RADMIN]: Submitting save OAR request for {0} to file {1}, request ID {2}",
1729 scene.Name, filename, requestId);
1730
1731 archiver.ArchiveRegion(filename, requestId, options);
1573 1732
1574 lock (m_saveOarLock) 1733 lock (m_saveOarLock)
1575 Monitor.Wait(m_saveOarLock,5000); 1734 Monitor.Wait(m_saveOarLock,5000);
@@ -1590,12 +1749,16 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1590 throw e; 1749 throw e;
1591 } 1750 }
1592 1751
1593 m_log.Info("[RADMIN]: Save OAR Administrator Request complete"); 1752 m_log.Info("[RADMIN]: Save OAR Request complete");
1594 } 1753 }
1595 1754
1596 private void RemoteAdminOarSaveCompleted(Guid uuid, string name) 1755 private void RemoteAdminOarSaveCompleted(Guid uuid, string name)
1597 { 1756 {
1598 m_log.DebugFormat("[RADMIN]: File processing complete for {0}", name); 1757 if (name != "")
1758 m_log.ErrorFormat("[RADMIN]: Saving of OAR file with request ID {0} failed with message {1}", uuid, name);
1759 else
1760 m_log.DebugFormat("[RADMIN]: Saved OAR file for request {0}", uuid);
1761
1599 lock (m_saveOarLock) 1762 lock (m_saveOarLock)
1600 Monitor.Pulse(m_saveOarLock); 1763 Monitor.Pulse(m_saveOarLock);
1601 } 1764 }
@@ -1902,6 +2065,22 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1902 m_log.Info("[RADMIN]: Access List List Request complete"); 2065 m_log.Info("[RADMIN]: Access List List Request complete");
1903 } 2066 }
1904 2067
2068 private void XmlRpcEstateReload(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
2069 {
2070 m_log.Info("[RADMIN]: Received Estate Reload Request");
2071
2072 Hashtable responseData = (Hashtable)response.Value;
2073// Hashtable requestData = (Hashtable)request.Params[0];
2074
2075 m_application.SceneManager.ForEachScene(s =>
2076 s.RegionInfo.EstateSettings = m_application.EstateDataService.LoadEstateSettings(s.RegionInfo.RegionID, false)
2077 );
2078
2079 responseData["success"] = true;
2080
2081 m_log.Info("[RADMIN]: Estate Reload Request complete");
2082 }
2083
1905 private void XmlRpcGetAgentsMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient) 2084 private void XmlRpcGetAgentsMethod(XmlRpcRequest request, XmlRpcResponse response, IPEndPoint remoteClient)
1906 { 2085 {
1907 Hashtable responseData = (Hashtable)response.Value; 2086 Hashtable responseData = (Hashtable)response.Value;
@@ -2763,15 +2942,13 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2763 /// </summary> 2942 /// </summary>
2764 private void ApplyNextOwnerPermissions(InventoryItemBase item) 2943 private void ApplyNextOwnerPermissions(InventoryItemBase item)
2765 { 2944 {
2766 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 2945 if (item.InvType == (int)InventoryType.Object)
2767 { 2946 {
2768 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 2947 uint perms = item.CurrentPermissions;
2769 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 2948 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref perms);
2770 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 2949 item.CurrentPermissions = perms;
2771 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
2772 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
2773 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
2774 } 2950 }
2951
2775 item.CurrentPermissions &= item.NextPermissions; 2952 item.CurrentPermissions &= item.NextPermissions;
2776 item.BasePermissions &= item.NextPermissions; 2953 item.BasePermissions &= item.NextPermissions;
2777 item.EveryOnePermissions &= item.NextPermissions; 2954 item.EveryOnePermissions &= item.NextPermissions;
diff --git a/OpenSim/Capabilities/Caps.cs b/OpenSim/Capabilities/Caps.cs
index 241fef3..30a323e 100644
--- a/OpenSim/Capabilities/Caps.cs
+++ b/OpenSim/Capabilities/Caps.cs
@@ -64,7 +64,11 @@ namespace OpenSim.Framework.Capabilities
64 public string CapsObjectPath { get { return m_capsObjectPath; } } 64 public string CapsObjectPath { get { return m_capsObjectPath; } }
65 65
66 private CapsHandlers m_capsHandlers; 66 private CapsHandlers m_capsHandlers;
67 private Dictionary<string, string> m_externalCapsHandlers; 67
68 private Dictionary<string, PollServiceEventArgs> m_pollServiceHandlers
69 = new Dictionary<string, PollServiceEventArgs>();
70
71 private Dictionary<string, string> m_externalCapsHandlers = new Dictionary<string, string>();
68 72
69 private IHttpServer m_httpListener; 73 private IHttpServer m_httpListener;
70 private UUID m_agentID; 74 private UUID m_agentID;
@@ -134,7 +138,6 @@ namespace OpenSim.Framework.Capabilities
134 138
135 m_agentID = agent; 139 m_agentID = agent;
136 m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL); 140 m_capsHandlers = new CapsHandlers(httpServer, httpListen, httpPort, (httpServer == null) ? false : httpServer.UseSSL);
137 m_externalCapsHandlers = new Dictionary<string, string>();
138 m_regionName = regionName; 141 m_regionName = regionName;
139 } 142 }
140 143
@@ -145,8 +148,29 @@ namespace OpenSim.Framework.Capabilities
145 /// <param name="handler"></param> 148 /// <param name="handler"></param>
146 public void RegisterHandler(string capName, IRequestHandler handler) 149 public void RegisterHandler(string capName, IRequestHandler handler)
147 { 150 {
148 m_capsHandlers[capName] = handler;
149 //m_log.DebugFormat("[CAPS]: Registering handler for \"{0}\": path {1}", capName, handler.Path); 151 //m_log.DebugFormat("[CAPS]: Registering handler for \"{0}\": path {1}", capName, handler.Path);
152 m_capsHandlers[capName] = handler;
153 }
154
155 public void RegisterPollHandler(string capName, PollServiceEventArgs pollServiceHandler)
156 {
157 m_pollServiceHandlers.Add(capName, pollServiceHandler);
158
159 m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler);
160
161// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
162// string protocol = "http";
163// string hostName = m_httpListenerHostName;
164//
165// if (MainServer.Instance.UseSSL)
166// {
167// hostName = MainServer.Instance.SSLCommonName;
168// port = MainServer.Instance.SSLPort;
169// protocol = "https";
170// }
171
172// RegisterHandler(
173// capName, String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, pollServiceHandler.Url));
150 } 174 }
151 175
152 /// <summary> 176 /// <summary>
@@ -165,13 +189,70 @@ namespace OpenSim.Framework.Capabilities
165 /// </summary> 189 /// </summary>
166 public void DeregisterHandlers() 190 public void DeregisterHandlers()
167 { 191 {
168 if (m_capsHandlers != null) 192 foreach (string capsName in m_capsHandlers.Caps)
193 {
194 m_capsHandlers.Remove(capsName);
195 }
196
197 foreach (PollServiceEventArgs handler in m_pollServiceHandlers.Values)
198 {
199 m_httpListener.RemovePollServiceHTTPHandler("", handler.Url);
200 }
201 }
202
203 public bool TryGetPollHandler(string name, out PollServiceEventArgs pollHandler)
204 {
205 return m_pollServiceHandlers.TryGetValue(name, out pollHandler);
206 }
207
208 public Dictionary<string, PollServiceEventArgs> GetPollHandlers()
209 {
210 return new Dictionary<string, PollServiceEventArgs>(m_pollServiceHandlers);
211 }
212
213 /// <summary>
214 /// Return an LLSD-serializable Hashtable describing the
215 /// capabilities and their handler details.
216 /// </summary>
217 /// <param name="excludeSeed">If true, then exclude the seed cap.</param>
218 public Hashtable GetCapsDetails(bool excludeSeed, List<string> requestedCaps)
219 {
220 Hashtable caps = CapsHandlers.GetCapsDetails(excludeSeed, requestedCaps);
221
222 lock (m_pollServiceHandlers)
169 { 223 {
170 foreach (string capsName in m_capsHandlers.Caps) 224 foreach (KeyValuePair <string, PollServiceEventArgs> kvp in m_pollServiceHandlers)
171 { 225 {
172 m_capsHandlers.Remove(capsName); 226 if (!requestedCaps.Contains(kvp.Key))
227 continue;
228
229 string hostName = m_httpListenerHostName;
230 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
231 string protocol = "http";
232
233 if (MainServer.Instance.UseSSL)
234 {
235 hostName = MainServer.Instance.SSLCommonName;
236 port = MainServer.Instance.SSLPort;
237 protocol = "https";
238 }
239 //
240 // caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
241
242 caps[kvp.Key] = string.Format("{0}://{1}:{2}{3}", protocol, hostName, port, kvp.Value.Url);
173 } 243 }
174 } 244 }
245
246 // Add the external too
247 foreach (KeyValuePair<string, string> kvp in ExternalCapsHandlers)
248 {
249 if (!requestedCaps.Contains(kvp.Key))
250 continue;
251
252 caps[kvp.Key] = kvp.Value;
253 }
254
255 return caps;
175 } 256 }
176 257
177 public void Activate() 258 public void Activate()
@@ -185,4 +266,4 @@ namespace OpenSim.Framework.Capabilities
185 return m_capsActive.WaitOne(30000); 266 return m_capsActive.WaitOne(30000);
186 } 267 }
187 } 268 }
188} 269} \ No newline at end of file
diff --git a/OpenSim/Capabilities/CapsHandlers.cs b/OpenSim/Capabilities/CapsHandlers.cs
index 458272d..890df90 100644
--- a/OpenSim/Capabilities/CapsHandlers.cs
+++ b/OpenSim/Capabilities/CapsHandlers.cs
@@ -39,7 +39,7 @@ namespace OpenSim.Framework.Capabilities
39 /// </summary> 39 /// </summary>
40 public class CapsHandlers 40 public class CapsHandlers
41 { 41 {
42 private Dictionary <string, IRequestHandler> m_capsHandlers = new Dictionary<string, IRequestHandler>(); 42 private Dictionary<string, IRequestHandler> m_capsHandlers = new Dictionary<string, IRequestHandler>();
43 private IHttpServer m_httpListener; 43 private IHttpServer m_httpListener;
44 private string m_httpListenerHostName; 44 private string m_httpListenerHostName;
45 private uint m_httpListenerPort; 45 private uint m_httpListenerPort;
@@ -184,5 +184,17 @@ namespace OpenSim.Framework.Capabilities
184 184
185 return caps; 185 return caps;
186 } 186 }
187
188 /// <summary>
189 /// Returns a copy of the dictionary of all the HTTP cap handlers
190 /// </summary>
191 /// <returns>
192 /// The dictionary copy. The key is the capability name, the value is the HTTP handler.
193 /// </returns>
194 public Dictionary<string, IRequestHandler> GetCapsHandlers()
195 {
196 lock (m_capsHandlers)
197 return new Dictionary<string, IRequestHandler>(m_capsHandlers);
198 }
187 } 199 }
188} 200} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs b/OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs
new file mode 100644
index 0000000..426174d
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs
@@ -0,0 +1,116 @@
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.Collections.Specialized;
31using System.IO;
32using System.Reflection;
33using System.Web;
34using log4net;
35using Nini.Config;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Framework.Capabilities;
39using OpenSim.Framework.Servers;
40using OpenSim.Framework.Servers.HttpServer;
41//using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Services.Interfaces;
43using Caps = OpenSim.Framework.Capabilities.Caps;
44
45namespace OpenSim.Capabilities.Handlers
46{
47 public class AvatarPickerSearchHandler : BaseStreamHandler
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 private IPeople m_PeopleService;
52
53 public AvatarPickerSearchHandler(string path, IPeople peopleService, string name, string description)
54 : base("GET", path, name, description)
55 {
56 m_PeopleService = peopleService;
57 }
58
59 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
60 {
61 // Try to parse the texture ID from the request URL
62 NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
63 string names = query.GetOne("names");
64 string psize = query.GetOne("page_size");
65 string pnumber = query.GetOne("page");
66
67 if (m_PeopleService == null)
68 return FailureResponse(names, (int)System.Net.HttpStatusCode.InternalServerError, httpResponse);
69
70 if (string.IsNullOrEmpty(names) || names.Length < 3)
71 return FailureResponse(names, (int)System.Net.HttpStatusCode.BadRequest, httpResponse);
72
73 m_log.DebugFormat("[AVATAR PICKER SEARCH]: search for {0}", names);
74
75 int page_size = (string.IsNullOrEmpty(psize) ? 500 : Int32.Parse(psize));
76 int page_number = (string.IsNullOrEmpty(pnumber) ? 1 : Int32.Parse(pnumber));
77
78 // Full content request
79 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK;
80 //httpResponse.ContentLength = ??;
81 httpResponse.ContentType = "application/llsd+xml";
82
83 List<UserData> users = m_PeopleService.GetUserData(names, page_size, page_number);
84
85 LLSDAvatarPicker osdReply = new LLSDAvatarPicker();
86 osdReply.next_page_url = httpRequest.RawUrl;
87 foreach (UserData u in users)
88 osdReply.agents.Array.Add(ConvertUserData(u));
89
90 string reply = LLSDHelpers.SerialiseLLSDReply(osdReply);
91 return System.Text.Encoding.UTF8.GetBytes(reply);
92 }
93
94 private LLSDPerson ConvertUserData(UserData user)
95 {
96 LLSDPerson p = new LLSDPerson();
97 p.legacy_first_name = user.FirstName;
98 p.legacy_last_name = user.LastName;
99 p.display_name = user.FirstName + " " + user.LastName;
100 if (user.LastName.StartsWith("@"))
101 p.username = user.FirstName.ToLower() + user.LastName.ToLower();
102 else
103 p.username = user.FirstName.ToLower() + "." + user.LastName.ToLower();
104 p.id = user.Id;
105 p.is_display_name_default = false;
106 return p;
107 }
108
109 private byte[] FailureResponse(string names, int statuscode, IOSHttpResponse httpResponse)
110 {
111 m_log.Error("[AVATAR PICKER SEARCH]: Error searching for " + names);
112 httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
113 return System.Text.Encoding.UTF8.GetBytes(string.Empty);
114 }
115 }
116} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs b/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs
index c305797..d1503ee 100644
--- a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs
+++ b/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs
@@ -46,7 +46,7 @@ namespace OpenSim.Capabilities.Handlers
46{ 46{
47 public class FetchInventory2Handler 47 public class FetchInventory2Handler
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);
50 50
51 private IInventoryService m_inventoryService; 51 private IInventoryService m_inventoryService;
52 52
@@ -121,4 +121,4 @@ namespace OpenSim.Capabilities.Handlers
121 return llsdItem; 121 return llsdItem;
122 } 122 }
123 } 123 }
124} 124} \ No newline at end of file
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index aa6203b..f3efb53 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -85,7 +85,7 @@ namespace OpenSim.Capabilities.Handlers
85// m_log.DebugFormat("[GETTEXTURE]: Received request for texture id {0}", textureID); 85// m_log.DebugFormat("[GETTEXTURE]: Received request for texture id {0}", textureID);
86 86
87 string[] formats; 87 string[] formats;
88 if (format != null && format != string.Empty) 88 if (!string.IsNullOrEmpty(format))
89 { 89 {
90 formats = new string[1] { format.ToLower() }; 90 formats = new string[1] { format.ToLower() };
91 } 91 }
@@ -174,6 +174,7 @@ namespace OpenSim.Capabilities.Handlers
174 174
175 newTexture.Flags = AssetFlags.Collectable; 175 newTexture.Flags = AssetFlags.Collectable;
176 newTexture.Temporary = true; 176 newTexture.Temporary = true;
177 newTexture.Local = true;
177 m_assetService.Store(newTexture); 178 m_assetService.Store(newTexture);
178 WriteTextureData(request, response, newTexture, format); 179 WriteTextureData(request, response, newTexture, format);
179 return true; 180 return true;
diff --git a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
index f8f63f4..0cf8bf4 100644
--- a/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
+++ b/OpenSim/Capabilities/Handlers/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureServerConnector.cs b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureServerConnector.cs
new file mode 100644
index 0000000..10ea8ee
--- /dev/null
+++ b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureServerConnector.cs
@@ -0,0 +1,76 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using Nini.Config;
30using OpenSim.Server.Base;
31using OpenSim.Services.Interfaces;
32using OpenSim.Framework.Servers.HttpServer;
33using OpenSim.Server.Handlers.Base;
34using OpenMetaverse;
35
36namespace OpenSim.Capabilities.Handlers
37{
38 public class UploadBakedTextureServerConnector : ServiceConnector
39 {
40 private IAssetService m_AssetService;
41 private string m_ConfigName = "CapsService";
42
43 public UploadBakedTextureServerConnector(IConfigSource config, IHttpServer server, string configName) :
44 base(config, server, configName)
45 {
46 if (configName != String.Empty)
47 m_ConfigName = configName;
48
49 IConfig serverConfig = config.Configs[m_ConfigName];
50 if (serverConfig == null)
51 throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName));
52
53 string assetService = serverConfig.GetString("AssetService", String.Empty);
54
55 if (assetService == String.Empty)
56 throw new Exception("No AssetService in config file");
57
58 Object[] args = new Object[] { config };
59 m_AssetService =
60 ServerUtils.LoadPlugin<IAssetService>(assetService, args);
61
62 if (m_AssetService == null)
63 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
64
65 // NEED TO FIX THIS
66 OpenSim.Framework.Capabilities.Caps caps = new OpenSim.Framework.Capabilities.Caps(server, "", server.Port, "", UUID.Zero, "");
67 server.AddStreamHandler(new RestStreamHandler(
68 "POST",
69 "/CAPS/UploadBakedTexture/",
70 new UploadBakedTextureHandler(caps, m_AssetService, true).UploadBakedTexture,
71 "UploadBakedTexture",
72 "Upload Baked Texture Capability"));
73
74 }
75 }
76} \ No newline at end of file
diff --git a/OpenSim/Capabilities/LLSDAvatarPicker.cs b/OpenSim/Capabilities/LLSDAvatarPicker.cs
new file mode 100644
index 0000000..d0b3f3a
--- /dev/null
+++ b/OpenSim/Capabilities/LLSDAvatarPicker.cs
@@ -0,0 +1,51 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenMetaverse;
29
30namespace OpenSim.Framework.Capabilities
31{
32 [OSDMap]
33 public class LLSDAvatarPicker
34 {
35 public string next_page_url;
36 // an array of LLSDPerson
37 public OSDArray agents = new OSDArray();
38 }
39
40 [OSDMap]
41 public class LLSDPerson
42 {
43 public string username;
44 public string display_name;
45 //'display_name_next_update':d"1970-01-01T00:00:00Z"
46 public string legacy_first_name;
47 public string legacy_last_name;
48 public UUID id;
49 public bool is_display_name_default;
50 }
51} \ No newline at end of file
diff --git a/OpenSim/Capabilities/LLSDStreamHandler.cs b/OpenSim/Capabilities/LLSDStreamHandler.cs
index 5df24b2..4fa1153 100644
--- a/OpenSim/Capabilities/LLSDStreamHandler.cs
+++ b/OpenSim/Capabilities/LLSDStreamHandler.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Capabilities
48 m_method = method; 48 m_method = method;
49 } 49 }
50 50
51 public override byte[] Handle(string path, Stream request, 51 protected override byte[] ProcessRequest(string path, Stream request,
52 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 52 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
53 { 53 {
54 //Encoding encoding = Util.UTF8; 54 //Encoding encoding = Util.UTF8;
diff --git a/OpenSim/Data/IGridUserData.cs b/OpenSim/Data/IGridUserData.cs
index e15a1f8..9afa477 100644
--- a/OpenSim/Data/IGridUserData.cs
+++ b/OpenSim/Data/IGridUserData.cs
@@ -50,6 +50,7 @@ namespace OpenSim.Data
50 public interface IGridUserData 50 public interface IGridUserData
51 { 51 {
52 GridUserData Get(string userID); 52 GridUserData Get(string userID);
53 GridUserData[] GetAll(string query);
53 bool Store(GridUserData data); 54 bool Store(GridUserData data);
54 } 55 }
55} \ No newline at end of file 56} \ No newline at end of file
diff --git a/OpenSim/Data/IHGTravelingData.cs b/OpenSim/Data/IHGTravelingData.cs
new file mode 100644
index 0000000..452af7b
--- /dev/null
+++ b/OpenSim/Data/IHGTravelingData.cs
@@ -0,0 +1,59 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32
33namespace OpenSim.Data
34{
35 // This MUST be a ref type!
36 public class HGTravelingData
37 {
38 public UUID SessionID;
39 public UUID UserID;
40 public Dictionary<string, string> Data;
41
42 public HGTravelingData()
43 {
44 Data = new Dictionary<string, string>();
45 }
46 }
47
48 /// <summary>
49 /// An interface for connecting to the user grid datastore
50 /// </summary>
51 public interface IHGTravelingData
52 {
53 HGTravelingData Get(UUID sessionID);
54 HGTravelingData[] GetSessions(UUID userID);
55 bool Store(HGTravelingData data);
56 bool Delete(UUID sessionID);
57 void DeleteOld();
58 }
59} \ No newline at end of file
diff --git a/OpenSim/Data/IOfflineIMData.cs b/OpenSim/Data/IOfflineIMData.cs
index e780304..58501a3 100644
--- a/OpenSim/Data/IOfflineIMData.cs
+++ b/OpenSim/Data/IOfflineIMData.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 *
@@ -34,6 +34,7 @@ namespace OpenSim.Data
34 public class OfflineIMData 34 public class OfflineIMData
35 { 35 {
36 public UUID PrincipalID; 36 public UUID PrincipalID;
37 public UUID FromID;
37 public Dictionary<string, string> Data; 38 public Dictionary<string, string> Data;
38 } 39 }
39 40
diff --git a/OpenSim/Data/IProfilesData.cs b/OpenSim/Data/IProfilesData.cs
new file mode 100644
index 0000000..0de7f68
--- /dev/null
+++ b/OpenSim/Data/IProfilesData.cs
@@ -0,0 +1,56 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenMetaverse;
30using OpenMetaverse.StructuredData;
31using OpenSim.Framework;
32
33namespace OpenSim.Data
34{
35
36 public interface IProfilesData
37 {
38 OSDArray GetClassifiedRecords(UUID creatorId);
39 bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result);
40 bool DeleteClassifiedRecord(UUID recordId);
41 OSDArray GetAvatarPicks(UUID avatarId);
42 UserProfilePick GetPickInfo(UUID avatarId, UUID pickId);
43 bool UpdatePicksRecord(UserProfilePick pick);
44 bool DeletePicksRecord(UUID pickId);
45 bool GetAvatarNotes(ref UserProfileNotes note);
46 bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result);
47 bool GetAvatarProperties(ref UserProfileProperties props, ref string result);
48 bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result);
49 bool UpdateAvatarInterests(UserProfileProperties up, ref string result);
50 bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result);
51 bool GetUserAppData(ref UserAppData props, ref string result);
52 bool SetUserAppData(UserAppData props, ref string result);
53 OSDArray GetUserImageAssets(UUID avatarId);
54 }
55}
56
diff --git a/OpenSim/Data/IRegionData.cs b/OpenSim/Data/IRegionData.cs
index 70e1065..463c621 100644
--- a/OpenSim/Data/IRegionData.cs
+++ b/OpenSim/Data/IRegionData.cs
@@ -81,6 +81,7 @@ namespace OpenSim.Data
81 bool Delete(UUID regionID); 81 bool Delete(UUID regionID);
82 82
83 List<RegionData> GetDefaultRegions(UUID scopeID); 83 List<RegionData> GetDefaultRegions(UUID scopeID);
84 List<RegionData> GetDefaultHypergridRegions(UUID scopeID);
84 List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y); 85 List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y);
85 List<RegionData> GetHyperlinks(UUID scopeID); 86 List<RegionData> GetHyperlinks(UUID scopeID);
86 } 87 }
diff --git a/OpenSim/Data/MSSQL/MSSQLGridUserData.cs b/OpenSim/Data/MSSQL/MSSQLGridUserData.cs
index 1870273..fd52122 100644
--- a/OpenSim/Data/MSSQL/MSSQLGridUserData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLGridUserData.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Data.MSSQL
50 { 50 {
51 } 51 }
52 52
53 public GridUserData Get(string userID) 53 public new GridUserData Get(string userID)
54 { 54 {
55 GridUserData[] ret = Get("UserID", userID); 55 GridUserData[] ret = Get("UserID", userID);
56 56
@@ -60,5 +60,10 @@ namespace OpenSim.Data.MSSQL
60 return ret[0]; 60 return ret[0];
61 } 61 }
62 62
63 public GridUserData[] GetAll(string userID)
64 {
65 return base.Get(String.Format("UserID LIKE '{0}%'", userID));
66 }
67
63 } 68 }
64} 69}
diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
index 0d89706..c0589df 100644
--- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
@@ -315,6 +315,11 @@ namespace OpenSim.Data.MSSQL
315 return Get((int)RegionFlags.DefaultRegion, scopeID); 315 return Get((int)RegionFlags.DefaultRegion, scopeID);
316 } 316 }
317 317
318 public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
319 {
320 return Get((int)RegionFlags.DefaultHGRegion, scopeID);
321 }
322
318 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y) 323 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
319 { 324 {
320 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID); 325 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
index 00af3a0..0d09be6 100644
--- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs
@@ -351,7 +351,7 @@ IF EXISTS (SELECT UUID FROM prims WHERE UUID = @UUID)
351 ScriptAccessPin = @ScriptAccessPin, AllowedDrop = @AllowedDrop, DieAtEdge = @DieAtEdge, SalePrice = @SalePrice, 351 ScriptAccessPin = @ScriptAccessPin, AllowedDrop = @AllowedDrop, DieAtEdge = @DieAtEdge, SalePrice = @SalePrice,
352 SaleType = @SaleType, ColorR = @ColorR, ColorG = @ColorG, ColorB = @ColorB, ColorA = @ColorA, ParticleSystem = @ParticleSystem, 352 SaleType = @SaleType, ColorR = @ColorR, ColorG = @ColorG, ColorB = @ColorB, ColorA = @ColorA, ParticleSystem = @ParticleSystem,
353 ClickAction = @ClickAction, Material = @Material, CollisionSound = @CollisionSound, CollisionSoundVolume = @CollisionSoundVolume, PassTouches = @PassTouches, 353 ClickAction = @ClickAction, Material = @Material, CollisionSound = @CollisionSound, CollisionSoundVolume = @CollisionSoundVolume, PassTouches = @PassTouches,
354 LinkNumber = @LinkNumber, MediaURL = @MediaURL, DynAttrs = @DynAttrs, 354 LinkNumber = @LinkNumber, MediaURL = @MediaURL, AttachedPosX = @AttachedPosX, AttachedPosY = @AttachedPosY, AttachedPosZ = @AttachedPosZ, DynAttrs = @DynAttrs,
355 PhysicsShapeType = @PhysicsShapeType, Density = @Density, GravityModifier = @GravityModifier, Friction = @Friction, Restitution = @Restitution 355 PhysicsShapeType = @PhysicsShapeType, Density = @Density, GravityModifier = @GravityModifier, Friction = @Friction, Restitution = @Restitution
356 WHERE UUID = @UUID 356 WHERE UUID = @UUID
357 END 357 END
@@ -367,7 +367,7 @@ ELSE
367 PayPrice, PayButton1, PayButton2, PayButton3, PayButton4, LoopedSound, LoopedSoundGain, TextureAnimation, OmegaX, 367 PayPrice, PayButton1, PayButton2, PayButton3, PayButton4, LoopedSound, LoopedSoundGain, TextureAnimation, OmegaX,
368 OmegaY, OmegaZ, CameraEyeOffsetX, CameraEyeOffsetY, CameraEyeOffsetZ, CameraAtOffsetX, CameraAtOffsetY, CameraAtOffsetZ, 368 OmegaY, OmegaZ, CameraEyeOffsetX, CameraEyeOffsetY, CameraEyeOffsetZ, CameraAtOffsetX, CameraAtOffsetY, CameraAtOffsetZ,
369 ForceMouselook, ScriptAccessPin, AllowedDrop, DieAtEdge, SalePrice, SaleType, ColorR, ColorG, ColorB, ColorA, 369 ForceMouselook, ScriptAccessPin, AllowedDrop, DieAtEdge, SalePrice, SaleType, ColorR, ColorG, ColorB, ColorA,
370 ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber, MediaURL, DynAttrs, 370 ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber, MediaURL, AttachedPosX, AttachedPosY, AttachedPosZ, DynAttrs,
371 PhysicsShapeType, Density, GravityModifier, Friction, Restitution 371 PhysicsShapeType, Density, GravityModifier, Friction, Restitution
372 ) VALUES ( 372 ) VALUES (
373 @UUID, @CreationDate, @Name, @Text, @Description, @SitName, @TouchName, @ObjectFlags, @OwnerMask, @NextOwnerMask, @GroupMask, 373 @UUID, @CreationDate, @Name, @Text, @Description, @SitName, @TouchName, @ObjectFlags, @OwnerMask, @NextOwnerMask, @GroupMask,
@@ -378,7 +378,7 @@ ELSE
378 @PayPrice, @PayButton1, @PayButton2, @PayButton3, @PayButton4, @LoopedSound, @LoopedSoundGain, @TextureAnimation, @OmegaX, 378 @PayPrice, @PayButton1, @PayButton2, @PayButton3, @PayButton4, @LoopedSound, @LoopedSoundGain, @TextureAnimation, @OmegaX,
379 @OmegaY, @OmegaZ, @CameraEyeOffsetX, @CameraEyeOffsetY, @CameraEyeOffsetZ, @CameraAtOffsetX, @CameraAtOffsetY, @CameraAtOffsetZ, 379 @OmegaY, @OmegaZ, @CameraEyeOffsetX, @CameraEyeOffsetY, @CameraEyeOffsetZ, @CameraAtOffsetX, @CameraAtOffsetY, @CameraAtOffsetZ,
380 @ForceMouselook, @ScriptAccessPin, @AllowedDrop, @DieAtEdge, @SalePrice, @SaleType, @ColorR, @ColorG, @ColorB, @ColorA, 380 @ForceMouselook, @ScriptAccessPin, @AllowedDrop, @DieAtEdge, @SalePrice, @SaleType, @ColorR, @ColorG, @ColorB, @ColorA,
381 @ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber, @MediaURL, @DynAttrs, 381 @ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber, @MediaURL, @AttachedPosX, @AttachedPosY, @AttachedPosZ, @DynAttrs,
382 @PhysicsShapeType, @Density, @GravityModifier, @Friction, @Restitution 382 @PhysicsShapeType, @Density, @GravityModifier, @Friction, @Restitution
383 ) 383 )
384 END"; 384 END";
@@ -1695,6 +1695,12 @@ VALUES
1695 if (!(primRow["MediaURL"] is System.DBNull)) 1695 if (!(primRow["MediaURL"] is System.DBNull))
1696 prim.MediaUrl = (string)primRow["MediaURL"]; 1696 prim.MediaUrl = (string)primRow["MediaURL"];
1697 1697
1698 if (!(primRow["AttachedPosX"] is System.DBNull))
1699 prim.AttachedPos = new Vector3(
1700 Convert.ToSingle(primRow["AttachedPosX"]),
1701 Convert.ToSingle(primRow["AttachedPosY"]),
1702 Convert.ToSingle(primRow["AttachedPosZ"]));
1703
1698 if (!(primRow["DynAttrs"] is System.DBNull)) 1704 if (!(primRow["DynAttrs"] is System.DBNull))
1699 prim.DynAttrs = DAMap.FromXml((string)primRow["DynAttrs"]); 1705 prim.DynAttrs = DAMap.FromXml((string)primRow["DynAttrs"]);
1700 else 1706 else
@@ -2099,8 +2105,11 @@ VALUES
2099 parameters.Add(_Database.CreateParameter("PassTouches", 0)); 2105 parameters.Add(_Database.CreateParameter("PassTouches", 0));
2100 parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum)); 2106 parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum));
2101 parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl)); 2107 parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl));
2102 2108 parameters.Add(_Database.CreateParameter("AttachedPosX", prim.AttachedPos.X));
2103 if (prim.DynAttrs.Count > 0) 2109 parameters.Add(_Database.CreateParameter("AttachedPosY", prim.AttachedPos.Y));
2110 parameters.Add(_Database.CreateParameter("AttachedPosZ", prim.AttachedPos.Z));
2111
2112 if (prim.DynAttrs.CountNamespaces > 0)
2104 parameters.Add(_Database.CreateParameter("DynAttrs", prim.DynAttrs.ToXml())); 2113 parameters.Add(_Database.CreateParameter("DynAttrs", prim.DynAttrs.ToXml()));
2105 else 2114 else
2106 parameters.Add(_Database.CreateParameter("DynAttrs", null)); 2115 parameters.Add(_Database.CreateParameter("DynAttrs", null));
diff --git a/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs b/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs
index 9bc580e..38bb868 100644
--- a/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/MSSQL/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.6.*")] 64[assembly : AssemblyVersion("0.8.0.*")]
65 65
diff --git a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
index 4549801..bb89884 100644
--- a/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
+++ b/OpenSim/Data/MSSQL/Resources/RegionStore.migrations
@@ -1168,3 +1168,15 @@ ALTER TABLE prims ADD `Friction` double NOT NULL default '0.6';
1168ALTER TABLE prims ADD `Restitution` double NOT NULL default '0.5'; 1168ALTER TABLE prims ADD `Restitution` double NOT NULL default '0.5';
1169 1169
1170COMMIT 1170COMMIT
1171
1172:VERSION 40 #---------------- Save Attachment info
1173
1174BEGIN TRANSACTION
1175
1176ALTER TABLE prims ADD AttachedPosX float(53) default 0.0;
1177ALTER TABLE prims ADD AttachedPosY float(53) default 0.0;
1178ALTER TABLE prims ADD AttachedPosZ float(53) default 0.0;
1179ALTER TABLE primshapes ADD LastAttachPoint int not null default 0;
1180
1181COMMIT
1182
diff --git a/OpenSim/Data/MySQL/MySQLAssetData.cs b/OpenSim/Data/MySQL/MySQLAssetData.cs
index 21dd5aa..59cc22a 100644
--- a/OpenSim/Data/MySQL/MySQLAssetData.cs
+++ b/OpenSim/Data/MySQL/MySQLAssetData.cs
@@ -142,7 +142,8 @@ namespace OpenSim.Data.MySQL
142 } 142 }
143 catch (Exception e) 143 catch (Exception e)
144 { 144 {
145 m_log.Error("[ASSETS DB]: MySql failure fetching asset " + assetID + ": " + e.Message); 145 m_log.Error(
146 string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", assetID), e);
146 } 147 }
147 } 148 }
148 } 149 }
@@ -243,10 +244,11 @@ namespace OpenSim.Data.MySQL
243 } 244 }
244 catch (Exception e) 245 catch (Exception e)
245 { 246 {
246 m_log.ErrorFormat( 247 m_log.Error(
247 "[ASSETS DB]: " + 248 string.Format(
248 "MySql failure updating access_time for asset {0} with name {1}" + Environment.NewLine + e.ToString() 249 "[ASSETS DB]: Failure updating access_time for asset {0} with name {1}. Exception ",
249 + Environment.NewLine + "Attempting reconnection", asset.FullID, asset.Name); 250 asset.FullID, asset.Name),
251 e);
250 } 252 }
251 } 253 }
252 } 254 }
@@ -286,8 +288,8 @@ namespace OpenSim.Data.MySQL
286 } 288 }
287 catch (Exception e) 289 catch (Exception e)
288 { 290 {
289 m_log.ErrorFormat( 291 m_log.Error(
290 "[ASSETS DB]: MySql failure fetching asset {0}" + Environment.NewLine + e.ToString(), uuid); 292 string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", uuid), e);
291 } 293 }
292 } 294 }
293 } 295 }
@@ -346,7 +348,11 @@ namespace OpenSim.Data.MySQL
346 } 348 }
347 catch (Exception e) 349 catch (Exception e)
348 { 350 {
349 m_log.Error("[ASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString()); 351 m_log.Error(
352 string.Format(
353 "[ASSETS DB]: MySql failure fetching asset set from {0}, count {1}. Exception ",
354 start, count),
355 e);
350 } 356 }
351 } 357 }
352 } 358 }
diff --git a/OpenSim/Data/MySQL/MySQLGridUserData.cs b/OpenSim/Data/MySQL/MySQLGridUserData.cs
index a9ce94d..00560c1 100644
--- a/OpenSim/Data/MySQL/MySQLGridUserData.cs
+++ b/OpenSim/Data/MySQL/MySQLGridUserData.cs
@@ -46,7 +46,7 @@ namespace OpenSim.Data.MySQL
46 46
47 public MySQLGridUserData(string connectionString, string realm) : base(connectionString, realm, "GridUserStore") {} 47 public MySQLGridUserData(string connectionString, string realm) : base(connectionString, realm, "GridUserStore") {}
48 48
49 public GridUserData Get(string userID) 49 public new GridUserData Get(string userID)
50 { 50 {
51 GridUserData[] ret = Get("UserID", userID); 51 GridUserData[] ret = Get("UserID", userID);
52 52
@@ -56,6 +56,9 @@ namespace OpenSim.Data.MySQL
56 return ret[0]; 56 return ret[0];
57 } 57 }
58 58
59 59 public GridUserData[] GetAll(string userID)
60 {
61 return base.Get(String.Format("UserID LIKE '{0}%'", userID));
62 }
60 } 63 }
61} \ No newline at end of file 64} \ No newline at end of file
diff --git a/OpenSim/Data/MySQL/MySQLGroupsData.cs b/OpenSim/Data/MySQL/MySQLGroupsData.cs
index 2a1bd6c..0318284 100644
--- a/OpenSim/Data/MySQL/MySQLGroupsData.cs
+++ b/OpenSim/Data/MySQL/MySQLGroupsData.cs
@@ -88,7 +88,7 @@ namespace OpenSim.Data.MySQL
88 if (string.IsNullOrEmpty(pattern)) 88 if (string.IsNullOrEmpty(pattern))
89 pattern = "1 ORDER BY Name LIMIT 100"; 89 pattern = "1 ORDER BY Name LIMIT 100";
90 else 90 else
91 pattern = string.Format("Name LIKE %{0}% ORDER BY Name LIMIT 100", pattern); 91 pattern = string.Format("Name LIKE '%{0}%' ORDER BY Name LIMIT 100", pattern);
92 92
93 return m_Groups.Get(pattern); 93 return m_Groups.Get(pattern);
94 } 94 }
diff --git a/OpenSim/Data/MySQL/MySQLHGTravelData.cs b/OpenSim/Data/MySQL/MySQLHGTravelData.cs
new file mode 100644
index 0000000..e81b880
--- /dev/null
+++ b/OpenSim/Data/MySQL/MySQLHGTravelData.cs
@@ -0,0 +1,80 @@
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.Data;
31using System.Reflection;
32using System.Threading;
33using log4net;
34using OpenMetaverse;
35using OpenSim.Framework;
36using MySql.Data.MySqlClient;
37
38namespace OpenSim.Data.MySQL
39{
40 /// <summary>
41 /// A MySQL Interface for user grid data
42 /// </summary>
43 public class MySQLHGTravelData : MySQLGenericTableHandler<HGTravelingData>, IHGTravelingData
44 {
45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 public MySQLHGTravelData(string connectionString, string realm) : base(connectionString, realm, "HGTravelStore") { }
48
49 public HGTravelingData Get(UUID sessionID)
50 {
51 HGTravelingData[] ret = Get("SessionID", sessionID.ToString());
52
53 if (ret.Length == 0)
54 return null;
55
56 return ret[0];
57 }
58
59 public HGTravelingData[] GetSessions(UUID userID)
60 {
61 return base.Get("UserID", userID.ToString());
62 }
63
64 public bool Delete(UUID sessionID)
65 {
66 return Delete("SessionID", sessionID.ToString());
67 }
68
69 public void DeleteOld()
70 {
71 using (MySqlCommand cmd = new MySqlCommand())
72 {
73 cmd.CommandText = String.Format("delete from {0} where TMStamp < NOW() - INTERVAL 2 DAY", m_Realm);
74
75 ExecuteNonQuery(cmd);
76 }
77
78 }
79 }
80} \ No newline at end of file
diff --git a/OpenSim/Data/MySQL/MySQLOfflineIMData.cs b/OpenSim/Data/MySQL/MySQLOfflineIMData.cs
index 252f358..bafd204 100644
--- a/OpenSim/Data/MySQL/MySQLOfflineIMData.cs
+++ b/OpenSim/Data/MySQL/MySQLOfflineIMData.cs
@@ -47,13 +47,10 @@ namespace OpenSim.Data.MySQL
47 47
48 public void DeleteOld() 48 public void DeleteOld()
49 { 49 {
50 uint now = (uint)Util.UnixTimeSinceEpoch();
51
52 using (MySqlCommand cmd = new MySqlCommand()) 50 using (MySqlCommand cmd = new MySqlCommand())
53 { 51 {
54 cmd.CommandText = String.Format("delete from {0} where TMStamp < ?tstamp", m_Realm); 52 cmd.CommandText = String.Format("delete from {0} where TMStamp < NOW() - INTERVAL 2 WEEK", m_Realm);
55 cmd.Parameters.AddWithValue("?tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old 53
56
57 ExecuteNonQuery(cmd); 54 ExecuteNonQuery(cmd);
58 } 55 }
59 56
diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs
index a2d4ae4..2ad7590 100644
--- a/OpenSim/Data/MySQL/MySQLRegionData.cs
+++ b/OpenSim/Data/MySQL/MySQLRegionData.cs
@@ -310,6 +310,11 @@ namespace OpenSim.Data.MySQL
310 return Get((int)RegionFlags.DefaultRegion, scopeID); 310 return Get((int)RegionFlags.DefaultRegion, scopeID);
311 } 311 }
312 312
313 public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
314 {
315 return Get((int)RegionFlags.DefaultHGRegion, scopeID);
316 }
317
313 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y) 318 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
314 { 319 {
315 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID); 320 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index 537ec85..1b3e81e 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -174,7 +174,8 @@ namespace OpenSim.Data.MySQL
174 "CollisionSound, CollisionSoundVolume, " + 174 "CollisionSound, CollisionSoundVolume, " +
175 "PassTouches, " + 175 "PassTouches, " +
176 "PassCollisions, " + 176 "PassCollisions, " +
177 "LinkNumber, MediaURL, KeyframeMotion, " + 177 "LinkNumber, MediaURL, KeyframeMotion, AttachedPosX, " +
178 "AttachedPosY, AttachedPosZ, " +
178 "PhysicsShapeType, Density, GravityModifier, " + 179 "PhysicsShapeType, Density, GravityModifier, " +
179 "Friction, Restitution, Vehicle, DynAttrs " + 180 "Friction, Restitution, Vehicle, DynAttrs " +
180 ") values (" + "?UUID, " + 181 ") values (" + "?UUID, " +
@@ -209,7 +210,8 @@ namespace OpenSim.Data.MySQL
209 "?ColorB, ?ColorA, ?ParticleSystem, " + 210 "?ColorB, ?ColorA, ?ParticleSystem, " +
210 "?ClickAction, ?Material, ?CollisionSound, " + 211 "?ClickAction, ?Material, ?CollisionSound, " +
211 "?CollisionSoundVolume, ?PassTouches, ?PassCollisions, " + 212 "?CollisionSoundVolume, ?PassTouches, ?PassCollisions, " +
212 "?LinkNumber, ?MediaURL, ?KeyframeMotion, " + 213 "?LinkNumber, ?MediaURL, ?KeyframeMotion, ?AttachedPosX, " +
214 "?AttachedPosY, ?AttachedPosZ, " +
213 "?PhysicsShapeType, ?Density, ?GravityModifier, " + 215 "?PhysicsShapeType, ?Density, ?GravityModifier, " +
214 "?Friction, ?Restitution, ?Vehicle, ?DynAttrs)"; 216 "?Friction, ?Restitution, ?Vehicle, ?DynAttrs)";
215 217
@@ -228,7 +230,7 @@ namespace OpenSim.Data.MySQL
228 "PathTaperX, PathTaperY, PathTwist, " + 230 "PathTaperX, PathTaperY, PathTwist, " +
229 "PathTwistBegin, ProfileBegin, ProfileEnd, " + 231 "PathTwistBegin, ProfileBegin, ProfileEnd, " +
230 "ProfileCurve, ProfileHollow, Texture, " + 232 "ProfileCurve, ProfileHollow, Texture, " +
231 "ExtraParams, State, Media) " + 233 "ExtraParams, State, LastAttachPoint, Media) " +
232 "values (?UUID, " + 234 "values (?UUID, " +
233 "?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, " + 235 "?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, " +
234 "?PCode, ?PathBegin, ?PathEnd, " + 236 "?PCode, ?PathBegin, ?PathEnd, " +
@@ -240,7 +242,7 @@ namespace OpenSim.Data.MySQL
240 "?PathTwistBegin, ?ProfileBegin, " + 242 "?PathTwistBegin, ?ProfileBegin, " +
241 "?ProfileEnd, ?ProfileCurve, " + 243 "?ProfileEnd, ?ProfileCurve, " +
242 "?ProfileHollow, ?Texture, ?ExtraParams, " + 244 "?ProfileHollow, ?Texture, ?ExtraParams, " +
243 "?State, ?Media)"; 245 "?State, ?LastAttachPoint, ?Media)";
244 246
245 FillShapeCommand(cmd, prim); 247 FillShapeCommand(cmd, prim);
246 248
@@ -1320,7 +1322,16 @@ namespace OpenSim.Data.MySQL
1320 1322
1321 if (!(row["MediaURL"] is System.DBNull)) 1323 if (!(row["MediaURL"] is System.DBNull))
1322 prim.MediaUrl = (string)row["MediaURL"]; 1324 prim.MediaUrl = (string)row["MediaURL"];
1323 1325
1326 if (!(row["AttachedPosX"] is System.DBNull))
1327 {
1328 prim.AttachedPos = new Vector3(
1329 (float)(double)row["AttachedPosX"],
1330 (float)(double)row["AttachedPosY"],
1331 (float)(double)row["AttachedPosZ"]
1332 );
1333 }
1334
1324 if (!(row["DynAttrs"] is System.DBNull)) 1335 if (!(row["DynAttrs"] is System.DBNull))
1325 prim.DynAttrs = DAMap.FromXml((string)row["DynAttrs"]); 1336 prim.DynAttrs = DAMap.FromXml((string)row["DynAttrs"]);
1326 else 1337 else
@@ -1719,6 +1730,12 @@ namespace OpenSim.Data.MySQL
1719 1730
1720 cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum); 1731 cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum);
1721 cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl); 1732 cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl);
1733 if (prim.AttachedPos != null)
1734 {
1735 cmd.Parameters.AddWithValue("AttachedPosX", (double)prim.AttachedPos.X);
1736 cmd.Parameters.AddWithValue("AttachedPosY", (double)prim.AttachedPos.Y);
1737 cmd.Parameters.AddWithValue("AttachedPosZ", (double)prim.AttachedPos.Z);
1738 }
1722 1739
1723 if (prim.KeyframeMotion != null) 1740 if (prim.KeyframeMotion != null)
1724 cmd.Parameters.AddWithValue("KeyframeMotion", prim.KeyframeMotion.Serialize()); 1741 cmd.Parameters.AddWithValue("KeyframeMotion", prim.KeyframeMotion.Serialize());
@@ -1730,7 +1747,7 @@ namespace OpenSim.Data.MySQL
1730 else 1747 else
1731 cmd.Parameters.AddWithValue("Vehicle", String.Empty); 1748 cmd.Parameters.AddWithValue("Vehicle", String.Empty);
1732 1749
1733 if (prim.DynAttrs.Count > 0) 1750 if (prim.DynAttrs.CountNamespaces > 0)
1734 cmd.Parameters.AddWithValue("DynAttrs", prim.DynAttrs.ToXml()); 1751 cmd.Parameters.AddWithValue("DynAttrs", prim.DynAttrs.ToXml());
1735 else 1752 else
1736 cmd.Parameters.AddWithValue("DynAttrs", null); 1753 cmd.Parameters.AddWithValue("DynAttrs", null);
@@ -1932,6 +1949,7 @@ namespace OpenSim.Data.MySQL
1932 s.ExtraParams = (byte[])row["ExtraParams"]; 1949 s.ExtraParams = (byte[])row["ExtraParams"];
1933 1950
1934 s.State = (byte)(int)row["State"]; 1951 s.State = (byte)(int)row["State"];
1952 s.LastAttachPoint = (byte)(int)row["LastAttachPoint"];
1935 1953
1936 if (!(row["Media"] is System.DBNull)) 1954 if (!(row["Media"] is System.DBNull))
1937 s.Media = PrimitiveBaseShape.MediaList.FromXml((string)row["Media"]); 1955 s.Media = PrimitiveBaseShape.MediaList.FromXml((string)row["Media"]);
@@ -1978,6 +1996,7 @@ namespace OpenSim.Data.MySQL
1978 cmd.Parameters.AddWithValue("Texture", s.TextureEntry); 1996 cmd.Parameters.AddWithValue("Texture", s.TextureEntry);
1979 cmd.Parameters.AddWithValue("ExtraParams", s.ExtraParams); 1997 cmd.Parameters.AddWithValue("ExtraParams", s.ExtraParams);
1980 cmd.Parameters.AddWithValue("State", s.State); 1998 cmd.Parameters.AddWithValue("State", s.State);
1999 cmd.Parameters.AddWithValue("LastAttachPoint", s.LastAttachPoint);
1981 cmd.Parameters.AddWithValue("Media", null == s.Media ? null : s.Media.ToXml()); 2000 cmd.Parameters.AddWithValue("Media", null == s.Media ? null : s.Media.ToXml());
1982 } 2001 }
1983 2002
diff --git a/OpenSim/Data/MySQL/MySQLUserProfilesData.cs b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs
new file mode 100644
index 0000000..8b50c54
--- /dev/null
+++ b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs
@@ -0,0 +1,1102 @@
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.Data;
30using System.Reflection;
31using OpenSim.Data;
32using OpenSim.Framework;
33using MySql.Data.MySqlClient;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using log4net;
37
38namespace OpenSim.Data.MySQL
39{
40 public class UserProfilesData: IProfilesData
41 {
42 static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 #region Properites
45 string ConnectionString
46 {
47 get; set;
48 }
49
50 protected object Lock
51 {
52 get; set;
53 }
54
55 protected virtual Assembly Assembly
56 {
57 get { return GetType().Assembly; }
58 }
59
60 #endregion Properties
61
62 #region class Member Functions
63 public UserProfilesData(string connectionString)
64 {
65 ConnectionString = connectionString;
66 Init();
67 }
68
69 void Init()
70 {
71 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
72 {
73 dbcon.Open();
74
75 Migration m = new Migration(dbcon, Assembly, "UserProfiles");
76 m.Update();
77 }
78 }
79 #endregion Member Functions
80
81 #region Classifieds Queries
82 /// <summary>
83 /// Gets the classified records.
84 /// </summary>
85 /// <returns>
86 /// Array of classified records
87 /// </returns>
88 /// <param name='creatorId'>
89 /// Creator identifier.
90 /// </param>
91 public OSDArray GetClassifiedRecords(UUID creatorId)
92 {
93 OSDArray data = new OSDArray();
94
95 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
96 {
97 string query = "SELECT classifieduuid, name FROM classifieds WHERE creatoruuid = ?Id";
98 dbcon.Open();
99 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
100 {
101 cmd.Parameters.AddWithValue("?Id", creatorId);
102 using( MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.Default))
103 {
104 if(reader.HasRows)
105 {
106 while (reader.Read())
107 {
108 OSDMap n = new OSDMap();
109 UUID Id = UUID.Zero;
110
111 string Name = null;
112 try
113 {
114 UUID.TryParse(Convert.ToString( reader["classifieduuid"]), out Id);
115 Name = Convert.ToString(reader["name"]);
116 }
117 catch (Exception e)
118 {
119 m_log.DebugFormat("[PROFILES_DATA]" +
120 ": UserAccount exception {0}", e.Message);
121 }
122 n.Add("classifieduuid", OSD.FromUUID(Id));
123 n.Add("name", OSD.FromString(Name));
124 data.Add(n);
125 }
126 }
127 }
128 }
129 }
130 return data;
131 }
132
133 public bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result)
134 {
135 string query = string.Empty;
136
137
138 query += "INSERT INTO classifieds (";
139 query += "`classifieduuid`,";
140 query += "`creatoruuid`,";
141 query += "`creationdate`,";
142 query += "`expirationdate`,";
143 query += "`category`,";
144 query += "`name`,";
145 query += "`description`,";
146 query += "`parceluuid`,";
147 query += "`parentestate`,";
148 query += "`snapshotuuid`,";
149 query += "`simname`,";
150 query += "`posglobal`,";
151 query += "`parcelname`,";
152 query += "`classifiedflags`,";
153 query += "`priceforlisting`) ";
154 query += "VALUES (";
155 query += "?ClassifiedId,";
156 query += "?CreatorId,";
157 query += "?CreatedDate,";
158 query += "?ExpirationDate,";
159 query += "?Category,";
160 query += "?Name,";
161 query += "?Description,";
162 query += "?ParcelId,";
163 query += "?ParentEstate,";
164 query += "?SnapshotId,";
165 query += "?SimName,";
166 query += "?GlobalPos,";
167 query += "?ParcelName,";
168 query += "?Flags,";
169 query += "?ListingPrice ) ";
170 query += "ON DUPLICATE KEY UPDATE ";
171 query += "category=?Category, ";
172 query += "expirationdate=?ExpirationDate, ";
173 query += "name=?Name, ";
174 query += "description=?Description, ";
175 query += "parentestate=?ParentEstate, ";
176 query += "posglobal=?GlobalPos, ";
177 query += "parcelname=?ParcelName, ";
178 query += "classifiedflags=?Flags, ";
179 query += "priceforlisting=?ListingPrice, ";
180 query += "snapshotuuid=?SnapshotId";
181
182 if(string.IsNullOrEmpty(ad.ParcelName))
183 ad.ParcelName = "Unknown";
184 if(ad.ParcelId == null)
185 ad.ParcelId = UUID.Zero;
186 if(string.IsNullOrEmpty(ad.Description))
187 ad.Description = "No Description";
188
189 DateTime epoch = new DateTime(1970, 1, 1);
190 DateTime now = DateTime.Now;
191 TimeSpan epochnow = now - epoch;
192 TimeSpan duration;
193 DateTime expiration;
194 TimeSpan epochexp;
195
196 if(ad.Flags == 2)
197 {
198 duration = new TimeSpan(7,0,0,0);
199 expiration = now.Add(duration);
200 epochexp = expiration - epoch;
201 }
202 else
203 {
204 duration = new TimeSpan(365,0,0,0);
205 expiration = now.Add(duration);
206 epochexp = expiration - epoch;
207 }
208 ad.CreationDate = (int)epochnow.TotalSeconds;
209 ad.ExpirationDate = (int)epochexp.TotalSeconds;
210
211 try
212 {
213 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
214 {
215 dbcon.Open();
216 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
217 {
218 cmd.Parameters.AddWithValue("?ClassifiedId", ad.ClassifiedId.ToString());
219 cmd.Parameters.AddWithValue("?CreatorId", ad.CreatorId.ToString());
220 cmd.Parameters.AddWithValue("?CreatedDate", ad.CreationDate.ToString());
221 cmd.Parameters.AddWithValue("?ExpirationDate", ad.ExpirationDate.ToString());
222 cmd.Parameters.AddWithValue("?Category", ad.Category.ToString());
223 cmd.Parameters.AddWithValue("?Name", ad.Name.ToString());
224 cmd.Parameters.AddWithValue("?Description", ad.Description.ToString());
225 cmd.Parameters.AddWithValue("?ParcelId", ad.ParcelId.ToString());
226 cmd.Parameters.AddWithValue("?ParentEstate", ad.ParentEstate.ToString());
227 cmd.Parameters.AddWithValue("?SnapshotId", ad.SnapshotId.ToString ());
228 cmd.Parameters.AddWithValue("?SimName", ad.SimName.ToString());
229 cmd.Parameters.AddWithValue("?GlobalPos", ad.GlobalPos.ToString());
230 cmd.Parameters.AddWithValue("?ParcelName", ad.ParcelName.ToString());
231 cmd.Parameters.AddWithValue("?Flags", ad.Flags.ToString());
232 cmd.Parameters.AddWithValue("?ListingPrice", ad.Price.ToString ());
233
234 cmd.ExecuteNonQuery();
235 }
236 }
237 }
238 catch (Exception e)
239 {
240 m_log.DebugFormat("[PROFILES_DATA]" +
241 ": ClassifiedesUpdate exception {0}", e.Message);
242 result = e.Message;
243 return false;
244 }
245 return true;
246 }
247
248 public bool DeleteClassifiedRecord(UUID recordId)
249 {
250 string query = string.Empty;
251
252 query += "DELETE FROM classifieds WHERE ";
253 query += "classifieduuid = ?ClasifiedId";
254
255 try
256 {
257 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
258 {
259 dbcon.Open();
260
261 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
262 {
263 cmd.Parameters.AddWithValue("?ClassifiedId", recordId.ToString());
264
265 lock(Lock)
266 {
267 cmd.ExecuteNonQuery();
268 }
269 }
270 }
271 }
272 catch (Exception e)
273 {
274 m_log.DebugFormat("[PROFILES_DATA]" +
275 ": DeleteClassifiedRecord exception {0}", e.Message);
276 return false;
277 }
278 return true;
279 }
280
281 public bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result)
282 {
283 string query = string.Empty;
284
285 query += "SELECT * FROM classifieds WHERE ";
286 query += "classifieduuid = ?AdId";
287
288 try
289 {
290 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
291 {
292 dbcon.Open();
293 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
294 {
295 cmd.Parameters.AddWithValue("?AdId", ad.ClassifiedId.ToString());
296
297 using (MySqlDataReader reader = cmd.ExecuteReader())
298 {
299 if(reader.Read ())
300 {
301 ad.CreatorId = new UUID(reader.GetGuid("creatoruuid"));
302 ad.ParcelId = new UUID(reader.GetGuid("parceluuid"));
303 ad.SnapshotId = new UUID(reader.GetGuid("snapshotuuid"));
304 ad.CreationDate = Convert.ToInt32(reader["creationdate"]);
305 ad.ExpirationDate = Convert.ToInt32(reader["expirationdate"]);
306 ad.ParentEstate = Convert.ToInt32(reader["parentestate"]);
307 ad.Flags = (byte)reader.GetUInt32("classifiedflags");
308 ad.Category = reader.GetInt32("category");
309 ad.Price = reader.GetInt16("priceforlisting");
310 ad.Name = reader.GetString("name");
311 ad.Description = reader.GetString("description");
312 ad.SimName = reader.GetString("simname");
313 ad.GlobalPos = reader.GetString("posglobal");
314 ad.ParcelName = reader.GetString("parcelname");
315
316 }
317 }
318 }
319 dbcon.Close();
320 }
321 }
322 catch (Exception e)
323 {
324 m_log.DebugFormat("[PROFILES_DATA]" +
325 ": GetPickInfo exception {0}", e.Message);
326 }
327 return true;
328 }
329 #endregion Classifieds Queries
330
331 #region Picks Queries
332 public OSDArray GetAvatarPicks(UUID avatarId)
333 {
334 string query = string.Empty;
335
336 query += "SELECT `pickuuid`,`name` FROM userpicks WHERE ";
337 query += "creatoruuid = ?Id";
338 OSDArray data = new OSDArray();
339
340 try
341 {
342 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
343 {
344 dbcon.Open();
345 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
346 {
347 cmd.Parameters.AddWithValue("?Id", avatarId.ToString());
348
349 using (MySqlDataReader reader = cmd.ExecuteReader())
350 {
351 if(reader.HasRows)
352 {
353 while (reader.Read())
354 {
355 OSDMap record = new OSDMap();
356
357 record.Add("pickuuid",OSD.FromString((string)reader["pickuuid"]));
358 record.Add("name",OSD.FromString((string)reader["name"]));
359 data.Add(record);
360 }
361 }
362 }
363 }
364 }
365 }
366 catch (Exception e)
367 {
368 m_log.DebugFormat("[PROFILES_DATA]" +
369 ": GetAvatarPicks exception {0}", e.Message);
370 }
371 return data;
372 }
373
374 public UserProfilePick GetPickInfo(UUID avatarId, UUID pickId)
375 {
376 string query = string.Empty;
377 UserProfilePick pick = new UserProfilePick();
378
379 query += "SELECT * FROM userpicks WHERE ";
380 query += "creatoruuid = ?CreatorId AND ";
381 query += "pickuuid = ?PickId";
382
383 try
384 {
385 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
386 {
387 dbcon.Open();
388 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
389 {
390 cmd.Parameters.AddWithValue("?CreatorId", avatarId.ToString());
391 cmd.Parameters.AddWithValue("?PickId", pickId.ToString());
392
393 using (MySqlDataReader reader = cmd.ExecuteReader())
394 {
395 if(reader.HasRows)
396 {
397 reader.Read();
398
399 string description = (string)reader["description"];
400
401 if (string.IsNullOrEmpty(description))
402 description = "No description given.";
403
404 UUID.TryParse((string)reader["pickuuid"], out pick.PickId);
405 UUID.TryParse((string)reader["creatoruuid"], out pick.CreatorId);
406 UUID.TryParse((string)reader["parceluuid"], out pick.ParcelId);
407 UUID.TryParse((string)reader["snapshotuuid"], out pick.SnapshotId);
408 pick.GlobalPos = (string)reader["posglobal"];
409 bool.TryParse((string)reader["toppick"], out pick.TopPick);
410 bool.TryParse((string)reader["enabled"], out pick.Enabled);
411 pick.Name = (string)reader["name"];
412 pick.Desc = description;
413 pick.User = (string)reader["user"];
414 pick.OriginalName = (string)reader["originalname"];
415 pick.SimName = (string)reader["simname"];
416 pick.SortOrder = (int)reader["sortorder"];
417 }
418 }
419 }
420 dbcon.Close();
421 }
422 }
423 catch (Exception e)
424 {
425 m_log.DebugFormat("[PROFILES_DATA]" +
426 ": GetPickInfo exception {0}", e.Message);
427 }
428 return pick;
429 }
430
431 public bool UpdatePicksRecord(UserProfilePick pick)
432 {
433 string query = string.Empty;
434
435 query += "INSERT INTO userpicks VALUES (";
436 query += "?PickId,";
437 query += "?CreatorId,";
438 query += "?TopPick,";
439 query += "?ParcelId,";
440 query += "?Name,";
441 query += "?Desc,";
442 query += "?SnapshotId,";
443 query += "?User,";
444 query += "?Original,";
445 query += "?SimName,";
446 query += "?GlobalPos,";
447 query += "?SortOrder,";
448 query += "?Enabled) ";
449 query += "ON DUPLICATE KEY UPDATE ";
450 query += "parceluuid=?ParcelId,";
451 query += "name=?Name,";
452 query += "description=?Desc,";
453 query += "snapshotuuid=?SnapshotId,";
454 query += "pickuuid=?PickId,";
455 query += "posglobal=?GlobalPos";
456
457 try
458 {
459 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
460 {
461 dbcon.Open();
462 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
463 {
464 cmd.Parameters.AddWithValue("?PickId", pick.PickId.ToString());
465 cmd.Parameters.AddWithValue("?CreatorId", pick.CreatorId.ToString());
466 cmd.Parameters.AddWithValue("?TopPick", pick.TopPick.ToString());
467 cmd.Parameters.AddWithValue("?ParcelId", pick.ParcelId.ToString());
468 cmd.Parameters.AddWithValue("?Name", pick.Name.ToString());
469 cmd.Parameters.AddWithValue("?Desc", pick.Desc.ToString());
470 cmd.Parameters.AddWithValue("?SnapshotId", pick.SnapshotId.ToString());
471 cmd.Parameters.AddWithValue("?User", pick.User.ToString());
472 cmd.Parameters.AddWithValue("?Original", pick.OriginalName.ToString());
473 cmd.Parameters.AddWithValue("?SimName",pick.SimName.ToString());
474 cmd.Parameters.AddWithValue("?GlobalPos", pick.GlobalPos);
475 cmd.Parameters.AddWithValue("?SortOrder", pick.SortOrder.ToString ());
476 cmd.Parameters.AddWithValue("?Enabled", pick.Enabled.ToString());
477
478 cmd.ExecuteNonQuery();
479 }
480 }
481 }
482 catch (Exception e)
483 {
484 m_log.DebugFormat("[PROFILES_DATA]" +
485 ": UpdateAvatarNotes exception {0}", e.Message);
486 return false;
487 }
488 return true;
489 }
490
491 public bool DeletePicksRecord(UUID pickId)
492 {
493 string query = string.Empty;
494
495 query += "DELETE FROM userpicks WHERE ";
496 query += "pickuuid = ?PickId";
497
498 try
499 {
500 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
501 {
502 dbcon.Open();
503
504 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
505 {
506 cmd.Parameters.AddWithValue("?PickId", pickId.ToString());
507
508 cmd.ExecuteNonQuery();
509 }
510 }
511 }
512 catch (Exception e)
513 {
514 m_log.DebugFormat("[PROFILES_DATA]" +
515 ": DeleteUserPickRecord exception {0}", e.Message);
516 return false;
517 }
518 return true;
519 }
520 #endregion Picks Queries
521
522 #region Avatar Notes Queries
523 public bool GetAvatarNotes(ref UserProfileNotes notes)
524 { // WIP
525 string query = string.Empty;
526
527 query += "SELECT `notes` FROM usernotes WHERE ";
528 query += "useruuid = ?Id AND ";
529 query += "targetuuid = ?TargetId";
530 OSDArray data = new OSDArray();
531
532 try
533 {
534 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
535 {
536 dbcon.Open();
537 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
538 {
539 cmd.Parameters.AddWithValue("?Id", notes.UserId.ToString());
540 cmd.Parameters.AddWithValue("?TargetId", notes.TargetId.ToString());
541
542 using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
543 {
544 if(reader.HasRows)
545 {
546 reader.Read();
547 notes.Notes = OSD.FromString((string)reader["notes"]);
548 }
549 else
550 {
551 notes.Notes = OSD.FromString("");
552 }
553 }
554 }
555 }
556 }
557 catch (Exception e)
558 {
559 m_log.DebugFormat("[PROFILES_DATA]" +
560 ": GetAvatarNotes exception {0}", e.Message);
561 }
562 return true;
563 }
564
565 public bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result)
566 {
567 string query = string.Empty;
568 bool remove;
569
570 if(string.IsNullOrEmpty(note.Notes))
571 {
572 remove = true;
573 query += "DELETE FROM usernotes WHERE ";
574 query += "useruuid=?UserId AND ";
575 query += "targetuuid=?TargetId";
576 }
577 else
578 {
579 remove = false;
580 query += "INSERT INTO usernotes VALUES ( ";
581 query += "?UserId,";
582 query += "?TargetId,";
583 query += "?Notes )";
584 query += "ON DUPLICATE KEY ";
585 query += "UPDATE ";
586 query += "notes=?Notes";
587 }
588
589 try
590 {
591 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
592 {
593 dbcon.Open();
594 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
595 {
596 if(!remove)
597 cmd.Parameters.AddWithValue("?Notes", note.Notes);
598 cmd.Parameters.AddWithValue("?TargetId", note.TargetId.ToString ());
599 cmd.Parameters.AddWithValue("?UserId", note.UserId.ToString());
600
601 cmd.ExecuteNonQuery();
602 }
603 }
604 }
605 catch (Exception e)
606 {
607 m_log.DebugFormat("[PROFILES_DATA]" +
608 ": UpdateAvatarNotes exception {0}", e.Message);
609 return false;
610 }
611 return true;
612
613 }
614 #endregion Avatar Notes Queries
615
616 #region Avatar Properties
617 public bool GetAvatarProperties(ref UserProfileProperties props, ref string result)
618 {
619 string query = string.Empty;
620
621 query += "SELECT * FROM userprofile WHERE ";
622 query += "useruuid = ?Id";
623
624 try
625 {
626 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
627 {
628 dbcon.Open();
629 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
630 {
631 cmd.Parameters.AddWithValue("?Id", props.UserId.ToString());
632
633 using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
634 {
635 if(reader.HasRows)
636 {
637 m_log.DebugFormat("[PROFILES_DATA]" +
638 ": Getting data for {0}.", props.UserId);
639 reader.Read();
640 props.WebUrl = (string)reader["profileURL"];
641 UUID.TryParse((string)reader["profileImage"], out props.ImageId);
642 props.AboutText = (string)reader["profileAboutText"];
643 UUID.TryParse((string)reader["profileFirstImage"], out props.FirstLifeImageId);
644 props.FirstLifeText = (string)reader["profileFirstText"];
645 UUID.TryParse((string)reader["profilePartner"], out props.PartnerId);
646 props.WantToMask = (int)reader["profileWantToMask"];
647 props.WantToText = (string)reader["profileWantToText"];
648 props.SkillsMask = (int)reader["profileSkillsMask"];
649 props.SkillsText = (string)reader["profileSkillsText"];
650 props.Language = (string)reader["profileLanguages"];
651 }
652 else
653 {
654 m_log.DebugFormat("[PROFILES_DATA]" +
655 ": No data for {0}", props.UserId);
656
657 props.WebUrl = string.Empty;
658 props.ImageId = UUID.Zero;
659 props.AboutText = string.Empty;
660 props.FirstLifeImageId = UUID.Zero;
661 props.FirstLifeText = string.Empty;
662 props.PartnerId = UUID.Zero;
663 props.WantToMask = 0;
664 props.WantToText = string.Empty;
665 props.SkillsMask = 0;
666 props.SkillsText = string.Empty;
667 props.Language = string.Empty;
668 props.PublishProfile = false;
669 props.PublishMature = false;
670
671 query = "INSERT INTO userprofile (";
672 query += "useruuid, ";
673 query += "profilePartner, ";
674 query += "profileAllowPublish, ";
675 query += "profileMaturePublish, ";
676 query += "profileURL, ";
677 query += "profileWantToMask, ";
678 query += "profileWantToText, ";
679 query += "profileSkillsMask, ";
680 query += "profileSkillsText, ";
681 query += "profileLanguages, ";
682 query += "profileImage, ";
683 query += "profileAboutText, ";
684 query += "profileFirstImage, ";
685 query += "profileFirstText) VALUES (";
686 query += "?userId, ";
687 query += "?profilePartner, ";
688 query += "?profileAllowPublish, ";
689 query += "?profileMaturePublish, ";
690 query += "?profileURL, ";
691 query += "?profileWantToMask, ";
692 query += "?profileWantToText, ";
693 query += "?profileSkillsMask, ";
694 query += "?profileSkillsText, ";
695 query += "?profileLanguages, ";
696 query += "?profileImage, ";
697 query += "?profileAboutText, ";
698 query += "?profileFirstImage, ";
699 query += "?profileFirstText)";
700
701 dbcon.Close();
702 dbcon.Open();
703
704 using (MySqlCommand put = new MySqlCommand(query, dbcon))
705 {
706 put.Parameters.AddWithValue("?userId", props.UserId.ToString());
707 put.Parameters.AddWithValue("?profilePartner", props.PartnerId.ToString());
708 put.Parameters.AddWithValue("?profileAllowPublish", props.PublishProfile);
709 put.Parameters.AddWithValue("?profileMaturePublish", props.PublishMature);
710 put.Parameters.AddWithValue("?profileURL", props.WebUrl);
711 put.Parameters.AddWithValue("?profileWantToMask", props.WantToMask);
712 put.Parameters.AddWithValue("?profileWantToText", props.WantToText);
713 put.Parameters.AddWithValue("?profileSkillsMask", props.SkillsMask);
714 put.Parameters.AddWithValue("?profileSkillsText", props.SkillsText);
715 put.Parameters.AddWithValue("?profileLanguages", props.Language);
716 put.Parameters.AddWithValue("?profileImage", props.ImageId.ToString());
717 put.Parameters.AddWithValue("?profileAboutText", props.AboutText);
718 put.Parameters.AddWithValue("?profileFirstImage", props.FirstLifeImageId.ToString());
719 put.Parameters.AddWithValue("?profileFirstText", props.FirstLifeText);
720
721 put.ExecuteNonQuery();
722 }
723 }
724 }
725 }
726 }
727 }
728 catch (Exception e)
729 {
730 m_log.DebugFormat("[PROFILES_DATA]" +
731 ": Requst properties exception {0}", e.Message);
732 result = e.Message;
733 return false;
734 }
735 return true;
736 }
737
738 public bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result)
739 {
740 string query = string.Empty;
741
742 query += "UPDATE userprofile SET ";
743 query += "profileURL=?profileURL, ";
744 query += "profileImage=?image, ";
745 query += "profileAboutText=?abouttext,";
746 query += "profileFirstImage=?firstlifeimage,";
747 query += "profileFirstText=?firstlifetext ";
748 query += "WHERE useruuid=?uuid";
749
750 try
751 {
752 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
753 {
754 dbcon.Open();
755 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
756 {
757 cmd.Parameters.AddWithValue("?profileURL", props.WebUrl);
758 cmd.Parameters.AddWithValue("?image", props.ImageId.ToString());
759 cmd.Parameters.AddWithValue("?abouttext", props.AboutText);
760 cmd.Parameters.AddWithValue("?firstlifeimage", props.FirstLifeImageId.ToString());
761 cmd.Parameters.AddWithValue("?firstlifetext", props.FirstLifeText);
762 cmd.Parameters.AddWithValue("?uuid", props.UserId.ToString());
763
764 cmd.ExecuteNonQuery();
765 }
766 }
767 }
768 catch (Exception e)
769 {
770 m_log.DebugFormat("[PROFILES_DATA]" +
771 ": AgentPropertiesUpdate exception {0}", e.Message);
772
773 return false;
774 }
775 return true;
776 }
777 #endregion Avatar Properties
778
779 #region Avatar Interests
780 public bool UpdateAvatarInterests(UserProfileProperties up, ref string result)
781 {
782 string query = string.Empty;
783
784 query += "UPDATE userprofile SET ";
785 query += "profileWantToMask=?WantMask, ";
786 query += "profileWantToText=?WantText,";
787 query += "profileSkillsMask=?SkillsMask,";
788 query += "profileSkillsText=?SkillsText, ";
789 query += "profileLanguages=?Languages ";
790 query += "WHERE useruuid=?uuid";
791
792 try
793 {
794 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
795 {
796 dbcon.Open();
797 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
798 {
799 cmd.Parameters.AddWithValue("?WantMask", up.WantToMask);
800 cmd.Parameters.AddWithValue("?WantText", up.WantToText);
801 cmd.Parameters.AddWithValue("?SkillsMask", up.SkillsMask);
802 cmd.Parameters.AddWithValue("?SkillsText", up.SkillsText);
803 cmd.Parameters.AddWithValue("?Languages", up.Language);
804 cmd.Parameters.AddWithValue("?uuid", up.UserId.ToString());
805
806 cmd.ExecuteNonQuery();
807 }
808 }
809 }
810 catch (Exception e)
811 {
812 m_log.DebugFormat("[PROFILES_DATA]" +
813 ": AgentInterestsUpdate exception {0}", e.Message);
814 result = e.Message;
815 return false;
816 }
817 return true;
818 }
819 #endregion Avatar Interests
820
821 public OSDArray GetUserImageAssets(UUID avatarId)
822 {
823 OSDArray data = new OSDArray();
824 string query = "SELECT `snapshotuuid` FROM {0} WHERE `creatoruuid` = ?Id";
825
826 // Get classified image assets
827
828
829 try
830 {
831 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
832 {
833 dbcon.Open();
834
835 using (MySqlCommand cmd = new MySqlCommand(string.Format (query,"`classifieds`"), dbcon))
836 {
837 cmd.Parameters.AddWithValue("?Id", avatarId.ToString());
838
839 using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
840 {
841 if(reader.HasRows)
842 {
843 while (reader.Read())
844 {
845 data.Add(new OSDString((string)reader["snapshotuuid"].ToString ()));
846 }
847 }
848 }
849 }
850
851 dbcon.Close();
852 dbcon.Open();
853
854 using (MySqlCommand cmd = new MySqlCommand(string.Format (query,"`userpicks`"), dbcon))
855 {
856 cmd.Parameters.AddWithValue("?Id", avatarId.ToString());
857
858 using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
859 {
860 if(reader.HasRows)
861 {
862 while (reader.Read())
863 {
864 data.Add(new OSDString((string)reader["snapshotuuid"].ToString ()));
865 }
866 }
867 }
868 }
869
870 dbcon.Close();
871 dbcon.Open();
872
873 query = "SELECT `profileImage`, `profileFirstImage` FROM `userprofile` WHERE `useruuid` = ?Id";
874
875 using (MySqlCommand cmd = new MySqlCommand(string.Format (query,"`userpicks`"), dbcon))
876 {
877 cmd.Parameters.AddWithValue("?Id", avatarId.ToString());
878
879 using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
880 {
881 if(reader.HasRows)
882 {
883 while (reader.Read())
884 {
885 data.Add(new OSDString((string)reader["profileImage"].ToString ()));
886 data.Add(new OSDString((string)reader["profileFirstImage"].ToString ()));
887 }
888 }
889 }
890 }
891 }
892 }
893 catch (Exception e)
894 {
895 m_log.DebugFormat("[PROFILES_DATA]" +
896 ": GetAvatarNotes exception {0}", e.Message);
897 }
898 return data;
899 }
900
901 #region User Preferences
902 public OSDArray GetUserPreferences(UUID avatarId)
903 {
904 string query = string.Empty;
905
906 query += "SELECT imviaemail,visible,email FROM ";
907 query += "usersettings WHERE ";
908 query += "useruuid = ?Id";
909
910 OSDArray data = new OSDArray();
911
912 try
913 {
914 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
915 {
916 dbcon.Open();
917 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
918 {
919 cmd.Parameters.AddWithValue("?Id", avatarId.ToString());
920
921 using (MySqlDataReader reader = cmd.ExecuteReader())
922 {
923 if(reader.HasRows)
924 {
925 reader.Read();
926 OSDMap record = new OSDMap();
927
928 record.Add("imviaemail",OSD.FromString((string)reader["imviaemail"]));
929 record.Add("visible",OSD.FromString((string)reader["visible"]));
930 record.Add("email",OSD.FromString((string)reader["email"]));
931 data.Add(record);
932 }
933 else
934 {
935 dbcon.Close();
936 dbcon.Open();
937
938 query = "INSERT INTO usersettings VALUES ";
939 query += "(?uuid,'false','false', ?Email)";
940
941 using (MySqlCommand put = new MySqlCommand(query, dbcon))
942 {
943
944// put.Parameters.AddWithValue("?Email", pref.EMail);
945// put.Parameters.AddWithValue("?uuid", pref.UserId.ToString());
946
947 put.ExecuteNonQuery();
948 }
949 }
950 }
951 }
952 }
953 }
954 catch (Exception e)
955 {
956 m_log.DebugFormat("[PROFILES_DATA]" +
957 ": Get preferences exception {0}", e.Message);
958 }
959 return data;
960 }
961
962 public bool UpdateUserPreferences(bool emailIm, bool visible, UUID avatarId )
963 {
964 string query = string.Empty;
965
966 query += "UPDATE userpsettings SET ";
967 query += "imviaemail=?ImViaEmail, ";
968 query += "visible=?Visible,";
969 query += "WHERE useruuid=?uuid";
970
971 try
972 {
973 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
974 {
975 dbcon.Open();
976 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
977 {
978 cmd.Parameters.AddWithValue("?ImViaEmail", emailIm.ToString().ToLower ());
979 cmd.Parameters.AddWithValue("?WantText", visible.ToString().ToLower ());
980 cmd.Parameters.AddWithValue("?uuid", avatarId.ToString());
981
982 lock(Lock)
983 {
984 cmd.ExecuteNonQuery();
985 }
986 }
987 }
988 }
989 catch (Exception e)
990 {
991 m_log.DebugFormat("[PROFILES_DATA]" +
992 ": AgentInterestsUpdate exception {0}", e.Message);
993 return false;
994 }
995 return true;
996 }
997 #endregion User Preferences
998
999 #region Integration
1000 public bool GetUserAppData(ref UserAppData props, ref string result)
1001 {
1002 string query = string.Empty;
1003
1004 query += "SELECT * FROM `userdata` WHERE ";
1005 query += "UserId = ?Id AND ";
1006 query += "TagId = ?TagId";
1007
1008 try
1009 {
1010 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
1011 {
1012 dbcon.Open();
1013 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
1014 {
1015 cmd.Parameters.AddWithValue("?Id", props.UserId.ToString());
1016 cmd.Parameters.AddWithValue ("?TagId", props.TagId.ToString());
1017
1018 using (MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
1019 {
1020 if(reader.HasRows)
1021 {
1022 reader.Read();
1023 props.DataKey = (string)reader["DataKey"];
1024 props.DataVal = (string)reader["DataVal"];
1025 }
1026 else
1027 {
1028 query += "INSERT INTO userdata VALUES ( ";
1029 query += "?UserId,";
1030 query += "?TagId,";
1031 query += "?DataKey,";
1032 query += "?DataVal) ";
1033
1034 using (MySqlCommand put = new MySqlCommand(query, dbcon))
1035 {
1036 put.Parameters.AddWithValue("?Id", props.UserId.ToString());
1037 put.Parameters.AddWithValue("?TagId", props.TagId.ToString());
1038 put.Parameters.AddWithValue("?DataKey", props.DataKey.ToString());
1039 put.Parameters.AddWithValue("?DataVal", props.DataVal.ToString());
1040
1041 lock(Lock)
1042 {
1043 put.ExecuteNonQuery();
1044 }
1045 }
1046 }
1047 }
1048 }
1049 }
1050 }
1051 catch (Exception e)
1052 {
1053 m_log.DebugFormat("[PROFILES_DATA]" +
1054 ": Requst application data exception {0}", e.Message);
1055 result = e.Message;
1056 return false;
1057 }
1058 return true;
1059 }
1060
1061 public bool SetUserAppData(UserAppData props, ref string result)
1062 {
1063 string query = string.Empty;
1064
1065 query += "UPDATE userdata SET ";
1066 query += "TagId = ?TagId, ";
1067 query += "DataKey = ?DataKey, ";
1068 query += "DataVal = ?DataVal WHERE ";
1069 query += "UserId = ?UserId AND ";
1070 query += "TagId = ?TagId";
1071
1072 try
1073 {
1074 using (MySqlConnection dbcon = new MySqlConnection(ConnectionString))
1075 {
1076 dbcon.Open();
1077 using (MySqlCommand cmd = new MySqlCommand(query, dbcon))
1078 {
1079 cmd.Parameters.AddWithValue("?UserId", props.UserId.ToString());
1080 cmd.Parameters.AddWithValue("?TagId", props.TagId.ToString ());
1081 cmd.Parameters.AddWithValue("?DataKey", props.DataKey.ToString ());
1082 cmd.Parameters.AddWithValue("?DataVal", props.DataKey.ToString ());
1083
1084 lock(Lock)
1085 {
1086 cmd.ExecuteNonQuery();
1087 }
1088 }
1089 }
1090 }
1091 catch (Exception e)
1092 {
1093 m_log.DebugFormat("[PROFILES_DATA]" +
1094 ": SetUserData exception {0}", e.Message);
1095 return false;
1096 }
1097 return true;
1098 }
1099 #endregion Integration
1100 }
1101}
1102
diff --git a/OpenSim/Data/MySQL/MySQLXAssetData.cs b/OpenSim/Data/MySQL/MySQLXAssetData.cs
index 15ac921..5f1d2ee 100644
--- a/OpenSim/Data/MySQL/MySQLXAssetData.cs
+++ b/OpenSim/Data/MySQL/MySQLXAssetData.cs
@@ -199,6 +199,8 @@ namespace OpenSim.Data.MySQL
199 /// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks> 199 /// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks>
200 public void StoreAsset(AssetBase asset) 200 public void StoreAsset(AssetBase asset)
201 { 201 {
202// m_log.DebugFormat("[XASSETS DB]: Storing asset {0} {1}", asset.Name, asset.ID);
203
202 lock (m_dbLock) 204 lock (m_dbLock)
203 { 205 {
204 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 206 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
diff --git a/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs b/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
index 1146d92..f562300 100644
--- a/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/MySQL/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.6.*")] 64[assembly : AssemblyVersion("0.8.0.*")]
65 65
diff --git a/OpenSim/Data/MySQL/Resources/EstateStore.migrations b/OpenSim/Data/MySQL/Resources/EstateStore.migrations
index df82a2e..2d1c2b5 100644
--- a/OpenSim/Data/MySQL/Resources/EstateStore.migrations
+++ b/OpenSim/Data/MySQL/Resources/EstateStore.migrations
@@ -77,5 +77,11 @@ BEGIN;
77ALTER TABLE estate_settings AUTO_INCREMENT = 100; 77ALTER TABLE estate_settings AUTO_INCREMENT = 100;
78COMMIT; 78COMMIT;
79 79
80:VERSION 33 #---------------------
80 81
82BEGIN;
83ALTER TABLE estate_settings ADD COLUMN `AllowLandmark` tinyint(4) NOT NULL default '1';
84ALTER TABLE estate_settings ADD COLUMN `AllowParcelChanges` tinyint(4) NOT NULL default '1';
85ALTER TABLE estate_settings ADD COLUMN `AllowSetHome` tinyint(4) NOT NULL default '1';
86COMMIT;
81 87
diff --git a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations
index 55d82ec..5faf956 100644
--- a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations
+++ b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations
@@ -9,7 +9,7 @@ CREATE TABLE `Friends` (
9 `Offered` VARCHAR(32) NOT NULL DEFAULT 0, 9 `Offered` VARCHAR(32) NOT NULL DEFAULT 0,
10 PRIMARY KEY(`PrincipalID`, `Friend`), 10 PRIMARY KEY(`PrincipalID`, `Friend`),
11 KEY(`PrincipalID`) 11 KEY(`PrincipalID`)
12); 12) ENGINE=InnoDB;
13 13
14COMMIT; 14COMMIT;
15 15
diff --git a/OpenSim/Data/MySQL/Resources/HGTravelStore.migrations b/OpenSim/Data/MySQL/Resources/HGTravelStore.migrations
new file mode 100644
index 0000000..b4e4422
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/HGTravelStore.migrations
@@ -0,0 +1,18 @@
1:VERSION 1 # --------------------------
2
3BEGIN;
4
5CREATE TABLE `hg_traveling_data` (
6 `SessionID` VARCHAR(36) NOT NULL,
7 `UserID` VARCHAR(36) NOT NULL,
8 `GridExternalName` VARCHAR(255) NOT NULL DEFAULT '',
9 `ServiceToken` VARCHAR(255) NOT NULL DEFAULT '',
10 `ClientIPAddress` VARCHAR(16) NOT NULL DEFAULT '',
11 `MyIPAddress` VARCHAR(16) NOT NULL DEFAULT '',
12 `TMStamp` timestamp NOT NULL,
13 PRIMARY KEY (`SessionID`),
14 KEY (`UserID`)
15) ENGINE=InnoDB;
16
17COMMIT;
18
diff --git a/OpenSim/Data/MySQL/Resources/IM_Store.migrations b/OpenSim/Data/MySQL/Resources/IM_Store.migrations
index 7cfcd43..f73475e 100644
--- a/OpenSim/Data/MySQL/Resources/IM_Store.migrations
+++ b/OpenSim/Data/MySQL/Resources/IM_Store.migrations
@@ -21,4 +21,14 @@ INSERT INTO `im_offline` SELECT * from `diva_im_offline`;
21DROP TABLE `diva_im_offline`; 21DROP TABLE `diva_im_offline`;
22DELETE FROM `migrations` WHERE name='diva_im_Store'; 22DELETE FROM `migrations` WHERE name='diva_im_Store';
23 23
24COMMIT; \ No newline at end of file 24COMMIT;
25
26:VERSION 3 # --------------------------
27
28BEGIN;
29
30ALTER TABLE `im_offline`
31 ADD `FromID` char(36) NOT NULL default '' AFTER `PrincipalID`,
32 ADD KEY `FromID` (`FromID`);
33
34COMMIT;
diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations
index bda1b6a..c2e3afe 100644
--- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations
+++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations
@@ -922,3 +922,20 @@ ALTER TABLE prims ADD COLUMN `Friction` double NOT NULL default '0.6';
922ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5'; 922ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5';
923 923
924COMMIT; 924COMMIT;
925
926:VERSION 48 #---------------- Keyframes
927
928BEGIN;
929
930ALTER TABLE prims ADD COLUMN `KeyframeMotion` blob;
931
932COMMIT;
933
934:VERSION 49 #--------------------- Save attachment info
935
936BEGIN;
937ALTER TABLE prims ADD COLUMN AttachedPosX double default 0;
938ALTER TABLE prims ADD COLUMN AttachedPosY double default 0;
939ALTER TABLE prims ADD COLUMN AttachedPosZ double default 0;
940ALTER TABLE primshapes ADD COLUMN LastAttachPoint int(4) not null default '0';
941COMMIT;
diff --git a/OpenSim/Data/MySQL/Resources/UserProfiles.migrations b/OpenSim/Data/MySQL/Resources/UserProfiles.migrations
new file mode 100644
index 0000000..c29f1ab
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/UserProfiles.migrations
@@ -0,0 +1,83 @@
1:VERSION 1 # -------------------------------
2
3begin;
4
5CREATE TABLE IF NOT EXISTS `classifieds` (
6 `classifieduuid` char(36) NOT NULL,
7 `creatoruuid` char(36) NOT NULL,
8 `creationdate` int(20) NOT NULL,
9 `expirationdate` int(20) NOT NULL,
10 `category` varchar(20) NOT NULL,
11 `name` varchar(255) NOT NULL,
12 `description` text NOT NULL,
13 `parceluuid` char(36) NOT NULL,
14 `parentestate` int(11) NOT NULL,
15 `snapshotuuid` char(36) NOT NULL,
16 `simname` varchar(255) NOT NULL,
17 `posglobal` varchar(255) NOT NULL,
18 `parcelname` varchar(255) NOT NULL,
19 `classifiedflags` int(8) NOT NULL,
20 `priceforlisting` int(5) NOT NULL,
21 PRIMARY KEY (`classifieduuid`)
22) ENGINE=InnoDB DEFAULT CHARSET=latin1;
23
24
25CREATE TABLE IF NOT EXISTS `usernotes` (
26 `useruuid` varchar(36) NOT NULL,
27 `targetuuid` varchar(36) NOT NULL,
28 `notes` text NOT NULL,
29 UNIQUE KEY `useruuid` (`useruuid`,`targetuuid`)
30) ENGINE=MyISAM DEFAULT CHARSET=latin1;
31
32
33CREATE TABLE IF NOT EXISTS `userpicks` (
34 `pickuuid` varchar(36) NOT NULL,
35 `creatoruuid` varchar(36) NOT NULL,
36 `toppick` enum('true','false') NOT NULL,
37 `parceluuid` varchar(36) NOT NULL,
38 `name` varchar(255) NOT NULL,
39 `description` text NOT NULL,
40 `snapshotuuid` varchar(36) NOT NULL,
41 `user` varchar(255) NOT NULL,
42 `originalname` varchar(255) NOT NULL,
43 `simname` varchar(255) NOT NULL,
44 `posglobal` varchar(255) NOT NULL,
45 `sortorder` int(2) NOT NULL,
46 `enabled` enum('true','false') NOT NULL,
47 PRIMARY KEY (`pickuuid`)
48) ENGINE=MyISAM DEFAULT CHARSET=latin1;
49
50
51CREATE TABLE IF NOT EXISTS `userprofile` (
52 `useruuid` varchar(36) NOT NULL,
53 `profilePartner` varchar(36) NOT NULL,
54 `profileAllowPublish` binary(1) NOT NULL,
55 `profileMaturePublish` binary(1) NOT NULL,
56 `profileURL` varchar(255) NOT NULL,
57 `profileWantToMask` int(3) NOT NULL,
58 `profileWantToText` text NOT NULL,
59 `profileSkillsMask` int(3) NOT NULL,
60 `profileSkillsText` text NOT NULL,
61 `profileLanguages` text NOT NULL,
62 `profileImage` varchar(36) NOT NULL,
63 `profileAboutText` text NOT NULL,
64 `profileFirstImage` varchar(36) NOT NULL,
65 `profileFirstText` text NOT NULL,
66 PRIMARY KEY (`useruuid`)
67) ENGINE=MyISAM DEFAULT CHARSET=latin1;
68
69commit;
70
71:VERSION 2 # -------------------------------
72
73begin;
74CREATE TABLE IF NOT EXISTS `userdata` (
75 `UserId` char(36) NOT NULL,
76 `TagId` varchar(64) NOT NULL,
77 `DataKey` varchar(255),
78 `DataVal` varchar(255),
79 PRIMARY KEY (`UserId`,`TagId`)
80) ENGINE=MyISAM DEFAULT CHARSET=latin1;
81
82commit;
83
diff --git a/OpenSim/Data/Null/NullEstateData.cs b/OpenSim/Data/Null/NullEstateData.cs
index d64136d..1df397d 100755
--- a/OpenSim/Data/Null/NullEstateData.cs
+++ b/OpenSim/Data/Null/NullEstateData.cs
@@ -42,6 +42,22 @@ namespace OpenSim.Data.Null
42 42
43// private string m_connectionString; 43// private string m_connectionString;
44 44
45 private Dictionary<uint, EstateSettings> m_knownEstates = new Dictionary<uint, EstateSettings>();
46 private EstateSettings m_estate = null;
47
48 private EstateSettings GetEstate()
49 {
50 if (m_estate == null)
51 {
52 // This fools the initialization caller into thinking an estate was fetched (a check in OpenSimBase).
53 // The estate info is pretty empty so don't try banning anyone.
54 m_estate = new EstateSettings();
55 m_estate.EstateID = 1;
56 m_estate.OnSave += StoreEstateSettings;
57 }
58 return m_estate;
59 }
60
45 protected virtual Assembly Assembly 61 protected virtual Assembly Assembly
46 { 62 {
47 get { return GetType().Assembly; } 63 get { return GetType().Assembly; }
@@ -68,21 +84,18 @@ namespace OpenSim.Data.Null
68 84
69 public EstateSettings LoadEstateSettings(UUID regionID, bool create) 85 public EstateSettings LoadEstateSettings(UUID regionID, bool create)
70 { 86 {
71 // This fools the initialization caller into thinking an estate was fetched (a check in OpenSimBase). 87 return GetEstate();
72 // The estate info is pretty empty so don't try banning anyone.
73 EstateSettings oneEstate = new EstateSettings();
74 oneEstate.EstateID = 1;
75 return oneEstate;
76 } 88 }
77 89
78 public void StoreEstateSettings(EstateSettings es) 90 public void StoreEstateSettings(EstateSettings es)
79 { 91 {
92 m_estate = es;
80 return; 93 return;
81 } 94 }
82 95
83 public EstateSettings LoadEstateSettings(int estateID) 96 public EstateSettings LoadEstateSettings(int estateID)
84 { 97 {
85 return new EstateSettings(); 98 return GetEstate();
86 } 99 }
87 100
88 public EstateSettings CreateNewEstate() 101 public EstateSettings CreateNewEstate()
@@ -93,13 +106,14 @@ namespace OpenSim.Data.Null
93 public List<EstateSettings> LoadEstateSettingsAll() 106 public List<EstateSettings> LoadEstateSettingsAll()
94 { 107 {
95 List<EstateSettings> allEstateSettings = new List<EstateSettings>(); 108 List<EstateSettings> allEstateSettings = new List<EstateSettings>();
96 allEstateSettings.Add(new EstateSettings()); 109 allEstateSettings.Add(GetEstate());
97 return allEstateSettings; 110 return allEstateSettings;
98 } 111 }
99 112
100 public List<int> GetEstatesAll() 113 public List<int> GetEstatesAll()
101 { 114 {
102 List<int> result = new List<int>(); 115 List<int> result = new List<int>();
116 result.Add((int)GetEstate().EstateID);
103 return result; 117 return result;
104 } 118 }
105 119
diff --git a/OpenSim/Data/Null/NullRegionData.cs b/OpenSim/Data/Null/NullRegionData.cs
index f707d98..d28cd99 100644
--- a/OpenSim/Data/Null/NullRegionData.cs
+++ b/OpenSim/Data/Null/NullRegionData.cs
@@ -239,6 +239,11 @@ namespace OpenSim.Data.Null
239 return Get((int)RegionFlags.DefaultRegion, scopeID); 239 return Get((int)RegionFlags.DefaultRegion, scopeID);
240 } 240 }
241 241
242 public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
243 {
244 return Get((int)RegionFlags.DefaultHGRegion, scopeID);
245 }
246
242 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y) 247 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
243 { 248 {
244 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID); 249 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
diff --git a/OpenSim/Data/Null/NullSimulationData.cs b/OpenSim/Data/Null/NullSimulationData.cs
index e7e5c41..15824a9 100644
--- a/OpenSim/Data/Null/NullSimulationData.cs
+++ b/OpenSim/Data/Null/NullSimulationData.cs
@@ -77,20 +77,34 @@ namespace OpenSim.Data.Null
77 } 77 }
78 78
79 #region Environment Settings 79 #region Environment Settings
80
81 private Dictionary<UUID, string> EnvironmentSettings = new Dictionary<UUID, string>();
82
80 public string LoadRegionEnvironmentSettings(UUID regionUUID) 83 public string LoadRegionEnvironmentSettings(UUID regionUUID)
81 { 84 {
82 //This connector doesn't support the Environment module yet 85 lock (EnvironmentSettings)
86 {
87 if (EnvironmentSettings.ContainsKey(regionUUID))
88 return EnvironmentSettings[regionUUID];
89 }
83 return string.Empty; 90 return string.Empty;
84 } 91 }
85 92
86 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings) 93 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
87 { 94 {
88 //This connector doesn't support the Environment module yet 95 lock (EnvironmentSettings)
96 {
97 EnvironmentSettings[regionUUID] = settings;
98 }
89 } 99 }
90 100
91 public void RemoveRegionEnvironmentSettings(UUID regionUUID) 101 public void RemoveRegionEnvironmentSettings(UUID regionUUID)
92 { 102 {
93 //This connector doesn't support the Environment module yet 103 lock (EnvironmentSettings)
104 {
105 if (EnvironmentSettings.ContainsKey(regionUUID))
106 EnvironmentSettings.Remove(regionUUID);
107 }
94 } 108 }
95 #endregion 109 #endregion
96 110
diff --git a/OpenSim/Data/Null/Properties/AssemblyInfo.cs b/OpenSim/Data/Null/Properties/AssemblyInfo.cs
index 1e02c31..28ef51a 100644
--- a/OpenSim/Data/Null/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/Null/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.6.*")] 64[assembly : AssemblyVersion("0.8.0.*")]
65 65
diff --git a/OpenSim/Data/PGSQL/PGSQLAssetData.cs b/OpenSim/Data/PGSQL/PGSQLAssetData.cs
new file mode 100644
index 0000000..7c5c01d
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLAssetData.cs
@@ -0,0 +1,296 @@
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.Data;
30using System.Reflection;
31using System.Collections.Generic;
32using OpenMetaverse;
33using log4net;
34using OpenSim.Framework;
35using Npgsql;
36using NpgsqlTypes;
37
38namespace OpenSim.Data.PGSQL
39{
40 /// <summary>
41 /// A PGSQL Interface for the Asset server
42 /// </summary>
43 public class PGSQLAssetData : AssetDataBase
44 {
45 private const string _migrationStore = "AssetStore";
46
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private long m_ticksToEpoch;
49 /// <summary>
50 /// Database manager
51 /// </summary>
52 private PGSQLManager m_database;
53 private string m_connectionString;
54
55 protected virtual Assembly Assembly
56 {
57 get { return GetType().Assembly; }
58 }
59
60 #region IPlugin Members
61
62 override public void Dispose() { }
63
64 /// <summary>
65 /// <para>Initialises asset interface</para>
66 /// </summary>
67 // [Obsolete("Cannot be default-initialized!")]
68 override public void Initialise()
69 {
70 m_log.Info("[PGSQLAssetData]: " + Name + " cannot be default-initialized!");
71 throw new PluginNotInitialisedException(Name);
72 }
73
74 /// <summary>
75 /// Initialises asset interface
76 /// </summary>
77 /// <para>
78 /// a string instead of file, if someone writes the support
79 /// </para>
80 /// <param name="connectionString">connect string</param>
81 override public void Initialise(string connectionString)
82 {
83 m_ticksToEpoch = new System.DateTime(1970, 1, 1).Ticks;
84
85 m_database = new PGSQLManager(connectionString);
86 m_connectionString = connectionString;
87
88 //New migration to check for DB changes
89 m_database.CheckMigration(_migrationStore);
90 }
91
92 /// <summary>
93 /// Database provider version.
94 /// </summary>
95 override public string Version
96 {
97 get { return m_database.getVersion(); }
98 }
99
100 /// <summary>
101 /// The name of this DB provider.
102 /// </summary>
103 override public string Name
104 {
105 get { return "PGSQL Asset storage engine"; }
106 }
107
108 #endregion
109
110 #region IAssetDataPlugin Members
111
112 /// <summary>
113 /// Fetch Asset from m_database
114 /// </summary>
115 /// <param name="assetID">the asset UUID</param>
116 /// <returns></returns>
117 override public AssetBase GetAsset(UUID assetID)
118 {
119 string sql = "SELECT * FROM assets WHERE id = :id";
120 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
121 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
122 {
123 cmd.Parameters.Add(m_database.CreateParameter("id", assetID));
124 conn.Open();
125 using (NpgsqlDataReader reader = cmd.ExecuteReader())
126 {
127 if (reader.Read())
128 {
129 AssetBase asset = new AssetBase(
130 DBGuid.FromDB(reader["id"]),
131 (string)reader["name"],
132 Convert.ToSByte(reader["assetType"]),
133 reader["creatorid"].ToString()
134 );
135 // Region Main
136 asset.Description = (string)reader["description"];
137 asset.Local = Convert.ToBoolean(reader["local"]);
138 asset.Temporary = Convert.ToBoolean(reader["temporary"]);
139 asset.Flags = (AssetFlags)(Convert.ToInt32(reader["asset_flags"]));
140 asset.Data = (byte[])reader["data"];
141 return asset;
142 }
143 return null; // throw new Exception("No rows to return");
144 }
145 }
146 }
147
148 /// <summary>
149 /// Create asset in m_database
150 /// </summary>
151 /// <param name="asset">the asset</param>
152 override public bool StoreAsset(AssetBase asset)
153 {
154
155 string sql =
156 @"UPDATE assets set name = :name, description = :description, " + "\"assetType\" " + @" = :assetType,
157 local = :local, temporary = :temporary, creatorid = :creatorid, data = :data
158 WHERE id=:id;
159
160 INSERT INTO assets
161 (id, name, description, " + "\"assetType\" " + @", local,
162 temporary, create_time, access_time, creatorid, asset_flags, data)
163 Select :id, :name, :description, :assetType, :local,
164 :temporary, :create_time, :access_time, :creatorid, :asset_flags, :data
165 Where not EXISTS(SELECT * FROM assets WHERE id=:id)
166 ";
167
168 string assetName = asset.Name;
169 if (asset.Name.Length > 64)
170 {
171 assetName = asset.Name.Substring(0, 64);
172 m_log.WarnFormat(
173 "[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
174 asset.Name, asset.ID, asset.Name.Length, assetName.Length);
175 }
176
177 string assetDescription = asset.Description;
178 if (asset.Description.Length > 64)
179 {
180 assetDescription = asset.Description.Substring(0, 64);
181 m_log.WarnFormat(
182 "[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
183 asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
184 }
185
186 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
187 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
188 {
189 int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000);
190 command.Parameters.Add(m_database.CreateParameter("id", asset.FullID));
191 command.Parameters.Add(m_database.CreateParameter("name", assetName));
192 command.Parameters.Add(m_database.CreateParameter("description", assetDescription));
193 command.Parameters.Add(m_database.CreateParameter("assetType", asset.Type));
194 command.Parameters.Add(m_database.CreateParameter("local", asset.Local));
195 command.Parameters.Add(m_database.CreateParameter("temporary", asset.Temporary));
196 command.Parameters.Add(m_database.CreateParameter("access_time", now));
197 command.Parameters.Add(m_database.CreateParameter("create_time", now));
198 command.Parameters.Add(m_database.CreateParameter("asset_flags", (int)asset.Flags));
199 command.Parameters.Add(m_database.CreateParameter("creatorid", asset.Metadata.CreatorID));
200 command.Parameters.Add(m_database.CreateParameter("data", asset.Data));
201 conn.Open();
202 try
203 {
204 command.ExecuteNonQuery();
205 }
206 catch(Exception e)
207 {
208 m_log.Error("[ASSET DB]: Error storing item :" + e.Message + " sql "+sql);
209 }
210 }
211 return true;
212 }
213
214
215// Commented out since currently unused - this probably should be called in GetAsset()
216// private void UpdateAccessTime(AssetBase asset)
217// {
218// using (AutoClosingSqlCommand cmd = m_database.Query("UPDATE assets SET access_time = :access_time WHERE id=:id"))
219// {
220// int now = (int)((System.DateTime.Now.Ticks - m_ticksToEpoch) / 10000000);
221// cmd.Parameters.AddWithValue(":id", asset.FullID.ToString());
222// cmd.Parameters.AddWithValue(":access_time", now);
223// try
224// {
225// cmd.ExecuteNonQuery();
226// }
227// catch (Exception e)
228// {
229// m_log.Error(e.ToString());
230// }
231// }
232// }
233
234 /// <summary>
235 /// Check if asset exist in m_database
236 /// </summary>
237 /// <param name="uuid"></param>
238 /// <returns>true if exist.</returns>
239 override public bool ExistsAsset(UUID uuid)
240 {
241 if (GetAsset(uuid) != null)
242 {
243 return true;
244 }
245 return false;
246 }
247
248 /// <summary>
249 /// Returns a list of AssetMetadata objects. The list is a subset of
250 /// the entire data set offset by <paramref name="start" /> containing
251 /// <paramref name="count" /> elements.
252 /// </summary>
253 /// <param name="start">The number of results to discard from the total data set.</param>
254 /// <param name="count">The number of rows the returned list should contain.</param>
255 /// <returns>A list of AssetMetadata objects.</returns>
256 public override List<AssetMetadata> FetchAssetMetadataSet(int start, int count)
257 {
258 List<AssetMetadata> retList = new List<AssetMetadata>(count);
259 string sql = @" SELECT id, name, description, " + "\"assetType\"" + @", temporary, creatorid
260 FROM assets
261 order by id
262 limit :stop
263 offset :start;";
264
265 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
266 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
267 {
268 cmd.Parameters.Add(m_database.CreateParameter("start", start));
269 cmd.Parameters.Add(m_database.CreateParameter("stop", start + count - 1));
270 conn.Open();
271 using (NpgsqlDataReader reader = cmd.ExecuteReader())
272 {
273 while (reader.Read())
274 {
275 AssetMetadata metadata = new AssetMetadata();
276 metadata.FullID = DBGuid.FromDB(reader["id"]);
277 metadata.Name = (string)reader["name"];
278 metadata.Description = (string)reader["description"];
279 metadata.Type = Convert.ToSByte(reader["assetType"]);
280 metadata.Temporary = Convert.ToBoolean(reader["temporary"]);
281 metadata.CreatorID = (string)reader["creatorid"];
282 retList.Add(metadata);
283 }
284 }
285 }
286
287 return retList;
288 }
289
290 public override bool Delete(string id)
291 {
292 return false;
293 }
294 #endregion
295 }
296}
diff --git a/OpenSim/Data/PGSQL/PGSQLAuthenticationData.cs b/OpenSim/Data/PGSQL/PGSQLAuthenticationData.cs
new file mode 100644
index 0000000..d174112
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLAuthenticationData.cs
@@ -0,0 +1,254 @@
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 OpenMetaverse;
32using OpenSim.Framework;
33using System.Reflection;
34using System.Text;
35using System.Data;
36using Npgsql;
37using NpgsqlTypes;
38
39namespace OpenSim.Data.PGSQL
40{
41 public class PGSQLAuthenticationData : IAuthenticationData
42 {
43 private string m_Realm;
44 private List<string> m_ColumnNames = null;
45 private int m_LastExpire = 0;
46 private string m_ConnectionString;
47 private PGSQLManager m_database;
48
49 protected virtual Assembly Assembly
50 {
51 get { return GetType().Assembly; }
52 }
53
54 public PGSQLAuthenticationData(string connectionString, string realm)
55 {
56 m_Realm = realm;
57 m_ConnectionString = connectionString;
58 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
59 {
60 conn.Open();
61 Migration m = new Migration(conn, GetType().Assembly, "AuthStore");
62 m_database = new PGSQLManager(m_ConnectionString);
63 m.Update();
64 }
65 }
66
67 public AuthenticationData Get(UUID principalID)
68 {
69 AuthenticationData ret = new AuthenticationData();
70 ret.Data = new Dictionary<string, object>();
71
72 string sql = string.Format("select * from {0} where uuid = :principalID", m_Realm);
73
74 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
75 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
76 {
77 cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID));
78 conn.Open();
79 using (NpgsqlDataReader result = cmd.ExecuteReader())
80 {
81 if (result.Read())
82 {
83 ret.PrincipalID = principalID;
84
85 if (m_ColumnNames == null)
86 {
87 m_ColumnNames = new List<string>();
88
89 DataTable schemaTable = result.GetSchemaTable();
90 foreach (DataRow row in schemaTable.Rows)
91 m_ColumnNames.Add(row["ColumnName"].ToString());
92 }
93
94 foreach (string s in m_ColumnNames)
95 {
96 if (s == "UUID"||s == "uuid")
97 continue;
98
99 ret.Data[s] = result[s].ToString();
100 }
101 return ret;
102 }
103 }
104 }
105 return null;
106 }
107
108 public bool Store(AuthenticationData data)
109 {
110 if (data.Data.ContainsKey("UUID"))
111 data.Data.Remove("UUID");
112 if (data.Data.ContainsKey("uuid"))
113 data.Data.Remove("uuid");
114
115 /*
116 Dictionary<string, object> oAuth = new Dictionary<string, object>();
117
118 foreach (KeyValuePair<string, object> oDado in data.Data)
119 {
120 if (oDado.Key != oDado.Key.ToLower())
121 {
122 oAuth.Add(oDado.Key.ToLower(), oDado.Value);
123 }
124 }
125 foreach (KeyValuePair<string, object> oDado in data.Data)
126 {
127 if (!oAuth.ContainsKey(oDado.Key.ToLower())) {
128 oAuth.Add(oDado.Key.ToLower(), oDado.Value);
129 }
130 }
131 */
132 string[] fields = new List<string>(data.Data.Keys).ToArray();
133 StringBuilder updateBuilder = new StringBuilder();
134
135 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
136 using (NpgsqlCommand cmd = new NpgsqlCommand())
137 {
138 updateBuilder.AppendFormat("update {0} set ", m_Realm);
139
140 bool first = true;
141 foreach (string field in fields)
142 {
143 if (!first)
144 updateBuilder.Append(", ");
145 updateBuilder.AppendFormat("\"{0}\" = :{0}",field);
146
147 first = false;
148
149 cmd.Parameters.Add(m_database.CreateParameter("" + field, data.Data[field]));
150 }
151
152 updateBuilder.Append(" where uuid = :principalID");
153
154 cmd.CommandText = updateBuilder.ToString();
155 cmd.Connection = conn;
156 cmd.Parameters.Add(m_database.CreateParameter("principalID", data.PrincipalID));
157
158 conn.Open();
159 if (cmd.ExecuteNonQuery() < 1)
160 {
161 StringBuilder insertBuilder = new StringBuilder();
162
163 insertBuilder.AppendFormat("insert into {0} (uuid, \"", m_Realm);
164 insertBuilder.Append(String.Join("\", \"", fields));
165 insertBuilder.Append("\") values (:principalID, :");
166 insertBuilder.Append(String.Join(", :", fields));
167 insertBuilder.Append(")");
168
169 cmd.CommandText = insertBuilder.ToString();
170
171 if (cmd.ExecuteNonQuery() < 1)
172 {
173 return false;
174 }
175 }
176 }
177 return true;
178 }
179
180 public bool SetDataItem(UUID principalID, string item, string value)
181 {
182 string sql = string.Format("update {0} set {1} = :{1} where uuid = :UUID", m_Realm, item);
183 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
184 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
185 {
186 cmd.Parameters.Add(m_database.CreateParameter("" + item, value));
187 conn.Open();
188 if (cmd.ExecuteNonQuery() > 0)
189 return true;
190 }
191 return false;
192 }
193
194 public bool SetToken(UUID principalID, string token, int lifetime)
195 {
196 if (System.Environment.TickCount - m_LastExpire > 30000)
197 DoExpire();
198
199 string sql = "insert into tokens (uuid, token, validity) values (:principalID, :token, :lifetime)";
200 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
201 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
202 {
203 cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID));
204 cmd.Parameters.Add(m_database.CreateParameter("token", token));
205 cmd.Parameters.Add(m_database.CreateParameter("lifetime", DateTime.Now.AddMinutes(lifetime)));
206 conn.Open();
207
208 if (cmd.ExecuteNonQuery() > 0)
209 {
210 return true;
211 }
212 }
213 return false;
214 }
215
216 public bool CheckToken(UUID principalID, string token, int lifetime)
217 {
218 if (System.Environment.TickCount - m_LastExpire > 30000)
219 DoExpire();
220
221 DateTime validDate = DateTime.Now.AddMinutes(lifetime);
222 string sql = "update tokens set validity = :validDate where uuid = :principalID and token = :token and validity > (CURRENT_DATE + CURRENT_TIME)";
223
224 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
225 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
226 {
227 cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID));
228 cmd.Parameters.Add(m_database.CreateParameter("token", token));
229 cmd.Parameters.Add(m_database.CreateParameter("validDate", validDate));
230 conn.Open();
231
232 if (cmd.ExecuteNonQuery() > 0)
233 {
234 return true;
235 }
236 }
237 return false;
238 }
239
240 private void DoExpire()
241 {
242 DateTime currentDateTime = DateTime.Now;
243 string sql = "delete from tokens where validity < :currentDateTime";
244 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
245 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
246 {
247 conn.Open();
248 cmd.Parameters.Add(m_database.CreateParameter("currentDateTime", currentDateTime));
249 cmd.ExecuteNonQuery();
250 }
251 m_LastExpire = System.Environment.TickCount;
252 }
253 }
254}
diff --git a/OpenSim/Data/PGSQL/PGSQLAvatarData.cs b/OpenSim/Data/PGSQL/PGSQLAvatarData.cs
new file mode 100644
index 0000000..d9c4905
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLAvatarData.cs
@@ -0,0 +1,72 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35using Npgsql;
36using NpgsqlTypes;
37
38
39namespace OpenSim.Data.PGSQL
40{
41 /// <summary>
42 /// A PGSQL Interface for Avatar Storage
43 /// </summary>
44 public class PGSQLAvatarData : PGSQLGenericTableHandler<AvatarBaseData>,
45 IAvatarData
46 {
47// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 public PGSQLAvatarData(string connectionString, string realm) :
50 base(connectionString, realm, "Avatar")
51 {
52 }
53
54 public bool Delete(UUID principalID, string name)
55 {
56 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
57 using (NpgsqlCommand cmd = new NpgsqlCommand())
58 {
59
60 cmd.CommandText = String.Format("DELETE FROM {0} where \"PrincipalID\" = :PrincipalID and \"Name\" = :Name", m_Realm);
61 cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID));
62 cmd.Parameters.Add(m_database.CreateParameter("Name", name));
63 cmd.Connection = conn;
64 conn.Open();
65 if (cmd.ExecuteNonQuery() > 0)
66 return true;
67
68 return false;
69 }
70 }
71 }
72}
diff --git a/OpenSim/Data/PGSQL/PGSQLEstateData.cs b/OpenSim/Data/PGSQL/PGSQLEstateData.cs
new file mode 100644
index 0000000..5ad0eaa
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLEstateData.cs
@@ -0,0 +1,602 @@
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 OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces;
35using System.Data;
36using Npgsql;
37using NpgsqlTypes;
38
39namespace OpenSim.Data.PGSQL
40{
41 public class PGSQLEstateStore : IEstateDataStore
42 {
43 private const string _migrationStore = "EstateStore";
44
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 private PGSQLManager _Database;
48 private string m_connectionString;
49 private FieldInfo[] _Fields;
50 private Dictionary<string, FieldInfo> _FieldMap = new Dictionary<string, FieldInfo>();
51
52 #region Public methods
53
54 public PGSQLEstateStore()
55 {
56 }
57
58 public PGSQLEstateStore(string connectionString)
59 {
60 Initialise(connectionString);
61 }
62
63 protected virtual Assembly Assembly
64 {
65 get { return GetType().Assembly; }
66 }
67
68 /// <summary>
69 /// Initialises the estatedata class.
70 /// </summary>
71 /// <param name="connectionString">connectionString.</param>
72 public void Initialise(string connectionString)
73 {
74 if (!string.IsNullOrEmpty(connectionString))
75 {
76 m_connectionString = connectionString;
77 _Database = new PGSQLManager(connectionString);
78 }
79
80 //Migration settings
81 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
82 {
83 conn.Open();
84 Migration m = new Migration(conn, GetType().Assembly, "EstateStore");
85 m.Update();
86 }
87
88 //Interesting way to get parameters! Maybe implement that also with other types
89 Type t = typeof(EstateSettings);
90 _Fields = t.GetFields(BindingFlags.NonPublic |
91 BindingFlags.Instance |
92 BindingFlags.DeclaredOnly);
93
94 foreach (FieldInfo f in _Fields)
95 {
96 if (f.Name.Substring(0, 2) == "m_")
97 _FieldMap[f.Name.Substring(2)] = f;
98 }
99 }
100
101 /// <summary>
102 /// Loads the estate settings.
103 /// </summary>
104 /// <param name="regionID">region ID.</param>
105 /// <returns></returns>
106 public EstateSettings LoadEstateSettings(UUID regionID, bool create)
107 {
108 EstateSettings es = new EstateSettings();
109
110 string sql = "select estate_settings.\"" + String.Join("\",estate_settings.\"", FieldList) +
111 "\" from estate_map left join estate_settings on estate_map.\"EstateID\" = estate_settings.\"EstateID\" " +
112 " where estate_settings.\"EstateID\" is not null and \"RegionID\" = :RegionID";
113
114 bool insertEstate = false;
115 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
116 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
117 {
118 cmd.Parameters.Add(_Database.CreateParameter("RegionID", regionID));
119 conn.Open();
120 using (NpgsqlDataReader reader = cmd.ExecuteReader())
121 {
122 if (reader.Read())
123 {
124 foreach (string name in FieldList)
125 {
126 FieldInfo f = _FieldMap[name];
127 object v = reader[name];
128 if (f.FieldType == typeof(bool))
129 {
130 f.SetValue(es, v);
131 }
132 else if (f.FieldType == typeof(UUID))
133 {
134 UUID estUUID = UUID.Zero;
135
136 UUID.TryParse(v.ToString(), out estUUID);
137
138 f.SetValue(es, estUUID);
139 }
140 else if (f.FieldType == typeof(string))
141 {
142 f.SetValue(es, v.ToString());
143 }
144 else if (f.FieldType == typeof(UInt32))
145 {
146 f.SetValue(es, Convert.ToUInt32(v));
147 }
148 else if (f.FieldType == typeof(Single))
149 {
150 f.SetValue(es, Convert.ToSingle(v));
151 }
152 else
153 f.SetValue(es, v);
154 }
155 }
156 else
157 {
158 insertEstate = true;
159 }
160 }
161 }
162
163 if (insertEstate && create)
164 {
165 DoCreate(es);
166 LinkRegion(regionID, (int)es.EstateID);
167 }
168
169 LoadBanList(es);
170
171 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
172 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
173 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
174
175 //Set event
176 es.OnSave += StoreEstateSettings;
177 return es;
178 }
179
180 public EstateSettings CreateNewEstate()
181 {
182 EstateSettings es = new EstateSettings();
183 es.OnSave += StoreEstateSettings;
184
185 DoCreate(es);
186
187 LoadBanList(es);
188
189 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
190 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
191 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
192
193 return es;
194 }
195
196 private void DoCreate(EstateSettings es)
197 {
198 List<string> names = new List<string>(FieldList);
199
200 names.Remove("EstateID");
201
202 string sql = string.Format("insert into estate_settings (\"{0}\") values ( :{1} )", String.Join("\",\"", names.ToArray()), String.Join(", :", names.ToArray()));
203
204 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
205 using (NpgsqlCommand insertCommand = new NpgsqlCommand(sql, conn))
206 {
207 insertCommand.CommandText = sql;
208
209 foreach (string name in names)
210 {
211 insertCommand.Parameters.Add(_Database.CreateParameter("" + name, _FieldMap[name].GetValue(es)));
212 }
213 //NpgsqlParameter idParameter = new NpgsqlParameter("ID", SqlDbType.Int);
214 //idParameter.Direction = ParameterDirection.Output;
215 //insertCommand.Parameters.Add(idParameter);
216 conn.Open();
217
218 es.EstateID = 100;
219
220 if (insertCommand.ExecuteNonQuery() > 0)
221 {
222 insertCommand.CommandText = "Select cast(lastval() as int) as ID ;";
223
224 using (NpgsqlDataReader result = insertCommand.ExecuteReader())
225 {
226 if (result.Read())
227 {
228 es.EstateID = (uint)result.GetInt32(0);
229 }
230 }
231 }
232
233 }
234
235 //TODO check if this is needed??
236 es.Save();
237 }
238
239 /// <summary>
240 /// Stores the estate settings.
241 /// </summary>
242 /// <param name="es">estate settings</param>
243 public void StoreEstateSettings(EstateSettings es)
244 {
245 List<string> names = new List<string>(FieldList);
246
247 names.Remove("EstateID");
248
249 string sql = string.Format("UPDATE estate_settings SET ");
250 foreach (string name in names)
251 {
252 sql += "\"" + name + "\" = :" + name + ", ";
253 }
254 sql = sql.Remove(sql.LastIndexOf(","));
255 sql += " WHERE \"EstateID\" = :EstateID";
256
257 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
258 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
259 {
260 foreach (string name in names)
261 {
262 cmd.Parameters.Add(_Database.CreateParameter("" + name, _FieldMap[name].GetValue(es)));
263 }
264
265 cmd.Parameters.Add(_Database.CreateParameter("EstateID", es.EstateID));
266 conn.Open();
267 cmd.ExecuteNonQuery();
268 }
269
270 SaveBanList(es);
271 SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers);
272 SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess);
273 SaveUUIDList(es.EstateID, "estate_groups", es.EstateGroups);
274 }
275
276 #endregion
277
278 #region Private methods
279
280 private string[] FieldList
281 {
282 get { return new List<string>(_FieldMap.Keys).ToArray(); }
283 }
284
285 private void LoadBanList(EstateSettings es)
286 {
287 es.ClearBans();
288
289 string sql = "select \"bannedUUID\" from estateban where \"EstateID\" = :EstateID";
290
291 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
292 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
293 {
294 NpgsqlParameter idParameter = new NpgsqlParameter("EstateID", DbType.Int32);
295 idParameter.Value = es.EstateID;
296 cmd.Parameters.Add(idParameter);
297 conn.Open();
298 using (NpgsqlDataReader reader = cmd.ExecuteReader())
299 {
300 while (reader.Read())
301 {
302 EstateBan eb = new EstateBan();
303
304 eb.BannedUserID = new UUID((Guid)reader["bannedUUID"]); //uuid;
305 eb.BannedHostAddress = "0.0.0.0";
306 eb.BannedHostIPMask = "0.0.0.0";
307 es.AddBan(eb);
308 }
309 }
310 }
311 }
312
313 private UUID[] LoadUUIDList(uint estateID, string table)
314 {
315 List<UUID> uuids = new List<UUID>();
316
317 string sql = string.Format("select uuid from {0} where \"EstateID\" = :EstateID", table);
318
319 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
320 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
321 {
322 cmd.Parameters.Add(_Database.CreateParameter("EstateID", estateID));
323 conn.Open();
324 using (NpgsqlDataReader reader = cmd.ExecuteReader())
325 {
326 while (reader.Read())
327 {
328 uuids.Add(new UUID((Guid)reader["uuid"])); //uuid);
329 }
330 }
331 }
332
333 return uuids.ToArray();
334 }
335
336 private void SaveBanList(EstateSettings es)
337 {
338 //Delete first
339 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
340 {
341 conn.Open();
342 using (NpgsqlCommand cmd = conn.CreateCommand())
343 {
344 cmd.CommandText = "delete from estateban where \"EstateID\" = :EstateID";
345 cmd.Parameters.AddWithValue("EstateID", (int)es.EstateID);
346 cmd.ExecuteNonQuery();
347
348 //Insert after
349 cmd.CommandText = "insert into estateban (\"EstateID\", \"bannedUUID\",\"bannedIp\", \"bannedIpHostMask\", \"bannedNameMask\") values ( :EstateID, :bannedUUID, '','','' )";
350 cmd.Parameters.AddWithValue("bannedUUID", Guid.Empty);
351 foreach (EstateBan b in es.EstateBans)
352 {
353 cmd.Parameters["bannedUUID"].Value = b.BannedUserID.Guid;
354 cmd.ExecuteNonQuery();
355 }
356 }
357 }
358 }
359
360 private void SaveUUIDList(uint estateID, string table, UUID[] data)
361 {
362 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
363 {
364 conn.Open();
365 using (NpgsqlCommand cmd = conn.CreateCommand())
366 {
367 cmd.Parameters.AddWithValue("EstateID", (int)estateID);
368 cmd.CommandText = string.Format("delete from {0} where \"EstateID\" = :EstateID", table);
369 cmd.ExecuteNonQuery();
370
371 cmd.CommandText = string.Format("insert into {0} (\"EstateID\", uuid) values ( :EstateID, :uuid )", table);
372 cmd.Parameters.AddWithValue("uuid", Guid.Empty);
373 foreach (UUID uuid in data)
374 {
375 cmd.Parameters["uuid"].Value = uuid.Guid; //.ToString(); //TODO check if this works
376 cmd.ExecuteNonQuery();
377 }
378 }
379 }
380 }
381
382 public EstateSettings LoadEstateSettings(int estateID)
383 {
384 EstateSettings es = new EstateSettings();
385 string sql = "select estate_settings.\"" + String.Join("\",estate_settings.\"", FieldList) + "\" from estate_settings where \"EstateID\" = :EstateID";
386 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
387 {
388 conn.Open();
389 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
390 {
391 cmd.Parameters.AddWithValue("EstateID", (int)estateID);
392 using (NpgsqlDataReader reader = cmd.ExecuteReader())
393 {
394 if (reader.Read())
395 {
396 foreach (string name in FieldList)
397 {
398 FieldInfo f = _FieldMap[name];
399 object v = reader[name];
400 if (f.FieldType == typeof(bool))
401 {
402 f.SetValue(es, Convert.ToInt32(v) != 0);
403 }
404 else if (f.FieldType == typeof(UUID))
405 {
406 f.SetValue(es, new UUID((Guid)v)); // uuid);
407 }
408 else if (f.FieldType == typeof(string))
409 {
410 f.SetValue(es, v.ToString());
411 }
412 else if (f.FieldType == typeof(UInt32))
413 {
414 f.SetValue(es, Convert.ToUInt32(v));
415 }
416 else if (f.FieldType == typeof(Single))
417 {
418 f.SetValue(es, Convert.ToSingle(v));
419 }
420 else
421 f.SetValue(es, v);
422 }
423 }
424
425 }
426 }
427 }
428 LoadBanList(es);
429
430 es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
431 es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
432 es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
433
434 //Set event
435 es.OnSave += StoreEstateSettings;
436 return es;
437
438 }
439
440 public List<EstateSettings> LoadEstateSettingsAll()
441 {
442 List<EstateSettings> allEstateSettings = new List<EstateSettings>();
443
444 List<int> allEstateIds = GetEstatesAll();
445
446 foreach (int estateId in allEstateIds)
447 allEstateSettings.Add(LoadEstateSettings(estateId));
448
449 return allEstateSettings;
450 }
451
452 public List<int> GetEstates(string search)
453 {
454 List<int> result = new List<int>();
455 string sql = "select \"EstateID\" from estate_settings where lower(\"EstateName\") = lower(:EstateName)";
456 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
457 {
458 conn.Open();
459 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
460 {
461 cmd.Parameters.AddWithValue("EstateName", search);
462
463 using (IDataReader reader = cmd.ExecuteReader())
464 {
465 while (reader.Read())
466 {
467 result.Add(Convert.ToInt32(reader["EstateID"]));
468 }
469 reader.Close();
470 }
471 }
472 }
473
474 return result;
475 }
476
477 public List<int> GetEstatesAll()
478 {
479 List<int> result = new List<int>();
480 string sql = "select \"EstateID\" from estate_settings";
481 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
482 {
483 conn.Open();
484 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
485 {
486 using (IDataReader reader = cmd.ExecuteReader())
487 {
488 while (reader.Read())
489 {
490 result.Add(Convert.ToInt32(reader["EstateID"]));
491 }
492 reader.Close();
493 }
494 }
495 }
496
497 return result;
498 }
499
500 public List<int> GetEstatesByOwner(UUID ownerID)
501 {
502 List<int> result = new List<int>();
503 string sql = "select \"estateID\" from estate_settings where \"EstateOwner\" = :EstateOwner";
504 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
505 {
506 conn.Open();
507 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
508 {
509 cmd.Parameters.AddWithValue("EstateOwner", ownerID);
510
511 using (IDataReader reader = cmd.ExecuteReader())
512 {
513 while (reader.Read())
514 {
515 result.Add(Convert.ToInt32(reader["EstateID"]));
516 }
517 reader.Close();
518 }
519 }
520 }
521
522 return result;
523 }
524
525 public bool LinkRegion(UUID regionID, int estateID)
526 {
527 string deleteSQL = "delete from estate_map where \"RegionID\" = :RegionID";
528 string insertSQL = "insert into estate_map values (:RegionID, :EstateID)";
529 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
530 {
531 conn.Open();
532
533 NpgsqlTransaction transaction = conn.BeginTransaction();
534
535 try
536 {
537 using (NpgsqlCommand cmd = new NpgsqlCommand(deleteSQL, conn))
538 {
539 cmd.Transaction = transaction;
540 cmd.Parameters.AddWithValue("RegionID", regionID.Guid);
541
542 cmd.ExecuteNonQuery();
543 }
544
545 using (NpgsqlCommand cmd = new NpgsqlCommand(insertSQL, conn))
546 {
547 cmd.Transaction = transaction;
548 cmd.Parameters.AddWithValue("RegionID", regionID.Guid);
549 cmd.Parameters.AddWithValue("EstateID", estateID);
550
551 int ret = cmd.ExecuteNonQuery();
552
553 if (ret != 0)
554 transaction.Commit();
555 else
556 transaction.Rollback();
557
558 return (ret != 0);
559 }
560 }
561 catch (Exception ex)
562 {
563 m_log.Error("[REGION DB]: LinkRegion failed: " + ex.Message);
564 transaction.Rollback();
565 }
566 }
567 return false;
568 }
569
570 public List<UUID> GetRegions(int estateID)
571 {
572 List<UUID> result = new List<UUID>();
573 string sql = "select \"RegionID\" from estate_map where \"EstateID\" = :EstateID";
574 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
575 {
576 conn.Open();
577 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
578 {
579 cmd.Parameters.AddWithValue("EstateID", estateID);
580
581 using (IDataReader reader = cmd.ExecuteReader())
582 {
583 while (reader.Read())
584 {
585 result.Add(DBGuid.FromDB(reader["RegionID"]));
586 }
587 reader.Close();
588 }
589 }
590 }
591
592 return result;
593 }
594
595 public bool DeleteEstate(int estateID)
596 {
597 // TODO: Implementation!
598 return false;
599 }
600 #endregion
601 }
602}
diff --git a/OpenSim/Data/PGSQL/PGSQLFramework.cs b/OpenSim/Data/PGSQL/PGSQLFramework.cs
new file mode 100644
index 0000000..1028e4e
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLFramework.cs
@@ -0,0 +1,111 @@
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.Data;
32using System.Reflection;
33using OpenMetaverse;
34using OpenSim.Framework;
35using Npgsql;
36
37namespace OpenSim.Data.PGSQL
38{
39 /// <summary>
40 /// A database interface class to a user profile storage system
41 /// </summary>
42 public class PGSqlFramework
43 {
44 private static readonly log4net.ILog m_log =
45 log4net.LogManager.GetLogger(
46 System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
47
48 protected string m_connectionString;
49 protected object m_dbLock = new object();
50
51 protected PGSqlFramework(string connectionString)
52 {
53 m_connectionString = connectionString;
54 InitializeMonoSecurity();
55 }
56
57 public void InitializeMonoSecurity()
58 {
59 if (!Util.IsPlatformMono)
60 {
61
62 if (AppDomain.CurrentDomain.GetData("MonoSecurityPostgresAdded") == null)
63 {
64 AppDomain.CurrentDomain.SetData("MonoSecurityPostgresAdded", "true");
65
66 AppDomain currentDomain = AppDomain.CurrentDomain;
67 currentDomain.AssemblyResolve += new ResolveEventHandler(ResolveEventHandlerMonoSec);
68 }
69 }
70 }
71
72 private System.Reflection.Assembly ResolveEventHandlerMonoSec(object sender, ResolveEventArgs args)
73 {
74 Assembly MyAssembly = null;
75
76 if (args.Name.Substring(0, args.Name.IndexOf(",")) == "Mono.Security")
77 {
78 MyAssembly = Assembly.LoadFrom("lib/NET/Mono.Security.dll");
79 }
80
81 //Return the loaded assembly.
82 return MyAssembly;
83 }
84 //////////////////////////////////////////////////////////////
85 //
86 // All non queries are funneled through one connection
87 // to increase performance a little
88 //
89 protected int ExecuteNonQuery(NpgsqlCommand cmd)
90 {
91 lock (m_dbLock)
92 {
93 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
94 {
95 dbcon.Open();
96 cmd.Connection = dbcon;
97
98 try
99 {
100 return cmd.ExecuteNonQuery();
101 }
102 catch (Exception e)
103 {
104 m_log.Error(e.Message, e);
105 return 0;
106 }
107 }
108 }
109 }
110 }
111}
diff --git a/OpenSim/Data/PGSQL/PGSQLFriendsData.cs b/OpenSim/Data/PGSQL/PGSQLFriendsData.cs
new file mode 100644
index 0000000..4c1ee02
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLFriendsData.cs
@@ -0,0 +1,116 @@
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.Data;
32using OpenMetaverse;
33using OpenSim.Framework;
34using System.Reflection;
35using System.Text;
36using Npgsql;
37
38namespace OpenSim.Data.PGSQL
39{
40 public class PGSQLFriendsData : PGSQLGenericTableHandler<FriendsData>, IFriendsData
41 {
42 public PGSQLFriendsData(string connectionString, string realm)
43 : base(connectionString, realm, "FriendsStore")
44 {
45 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
46 {
47 conn.Open();
48 Migration m = new Migration(conn, GetType().Assembly, "FriendsStore");
49 m.Update();
50 }
51 }
52
53
54 public bool Delete(string principalID, string friend)
55 {
56 UUID princUUID = UUID.Zero;
57
58 bool ret = UUID.TryParse(principalID, out princUUID);
59
60 if (ret)
61 return Delete(princUUID, friend);
62 else
63 return false;
64 }
65
66 public bool Delete(UUID principalID, string friend)
67 {
68 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
69 using (NpgsqlCommand cmd = new NpgsqlCommand())
70 {
71 cmd.CommandText = String.Format("delete from {0} where \"PrincipalID\" = :PrincipalID and \"Friend\" = :Friend", m_Realm);
72 cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID.ToString()));
73 cmd.Parameters.Add(m_database.CreateParameter("Friend", friend));
74 cmd.Connection = conn;
75 conn.Open();
76 cmd.ExecuteNonQuery();
77
78 return true;
79 }
80 }
81
82 public FriendsData[] GetFriends(string principalID)
83 {
84 UUID princUUID = UUID.Zero;
85
86 bool ret = UUID.TryParse(principalID, out princUUID);
87
88 if (ret)
89 return GetFriends(princUUID);
90 else
91 return new FriendsData[0];
92 }
93
94 public FriendsData[] GetFriends(UUID principalID)
95 {
96 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
97 using (NpgsqlCommand cmd = new NpgsqlCommand())
98 {
99
100 cmd.CommandText = String.Format("select a.*,case when b.\"Flags\" is null then '-1' else b.\"Flags\" end as \"TheirFlags\" from {0} as a " +
101 " left join {0} as b on a.\"PrincipalID\" = b.\"Friend\" and a.\"Friend\" = b.\"PrincipalID\" " +
102 " where a.\"PrincipalID\" = :PrincipalID", m_Realm);
103 cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID.ToString()));
104 cmd.Connection = conn;
105 conn.Open();
106 return DoQuery(cmd);
107 }
108 }
109
110 public FriendsData[] GetFriends(Guid principalID)
111 {
112 return GetFriends(principalID);
113 }
114
115 }
116}
diff --git a/OpenSim/Data/PGSQL/PGSQLGenericTableHandler.cs b/OpenSim/Data/PGSQL/PGSQLGenericTableHandler.cs
new file mode 100644
index 0000000..2151568
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLGenericTableHandler.cs
@@ -0,0 +1,519 @@
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.Data;
31using System.Reflection;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
36using System.Text;
37using Npgsql;
38
39namespace OpenSim.Data.PGSQL
40{
41 public class PGSQLGenericTableHandler<T> : PGSqlFramework where T : class, new()
42 {
43 private static readonly ILog m_log =
44 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 protected string m_ConnectionString;
47 protected PGSQLManager m_database; //used for parameter type translation
48 protected Dictionary<string, FieldInfo> m_Fields =
49 new Dictionary<string, FieldInfo>();
50
51 protected Dictionary<string, string> m_FieldTypes = new Dictionary<string, string>();
52
53 protected List<string> m_ColumnNames = null;
54 protected string m_Realm;
55 protected FieldInfo m_DataField = null;
56
57 protected virtual Assembly Assembly
58 {
59 get { return GetType().Assembly; }
60 }
61
62 public PGSQLGenericTableHandler(string connectionString,
63 string realm, string storeName)
64 : base(connectionString)
65 {
66 m_Realm = realm;
67
68 m_ConnectionString = connectionString;
69
70 if (storeName != String.Empty)
71 {
72 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
73 {
74 conn.Open();
75 Migration m = new Migration(conn, GetType().Assembly, storeName);
76 m.Update();
77 }
78
79 }
80 m_database = new PGSQLManager(m_ConnectionString);
81
82 Type t = typeof(T);
83 FieldInfo[] fields = t.GetFields(BindingFlags.Public |
84 BindingFlags.Instance |
85 BindingFlags.DeclaredOnly);
86
87 LoadFieldTypes();
88
89 if (fields.Length == 0)
90 return;
91
92 foreach (FieldInfo f in fields)
93 {
94 if (f.Name != "Data")
95 m_Fields[f.Name] = f;
96 else
97 m_DataField = f;
98 }
99
100 }
101
102 private void LoadFieldTypes()
103 {
104 m_FieldTypes = new Dictionary<string, string>();
105
106 string query = string.Format(@"select column_name,data_type
107 from INFORMATION_SCHEMA.COLUMNS
108 where table_name = lower('{0}');
109
110 ", m_Realm);
111 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
112 using (NpgsqlCommand cmd = new NpgsqlCommand(query, conn))
113 {
114 conn.Open();
115 using (NpgsqlDataReader rdr = cmd.ExecuteReader())
116 {
117 while (rdr.Read())
118 {
119 // query produces 0 to many rows of single column, so always add the first item in each row
120 m_FieldTypes.Add((string)rdr[0], (string)rdr[1]);
121 }
122 }
123 }
124 }
125
126 private void CheckColumnNames(NpgsqlDataReader reader)
127 {
128 if (m_ColumnNames != null)
129 return;
130
131 m_ColumnNames = new List<string>();
132
133 DataTable schemaTable = reader.GetSchemaTable();
134
135 foreach (DataRow row in schemaTable.Rows)
136 {
137 if (row["ColumnName"] != null &&
138 (!m_Fields.ContainsKey(row["ColumnName"].ToString())))
139 m_ColumnNames.Add(row["ColumnName"].ToString());
140
141 }
142 }
143
144 // TODO GET CONSTRAINTS FROM POSTGRESQL
145 private List<string> GetConstraints()
146 {
147 List<string> constraints = new List<string>();
148 string query = string.Format(@"SELECT kcu.column_name
149 FROM information_schema.table_constraints tc
150 LEFT JOIN information_schema.key_column_usage kcu
151 ON tc.constraint_catalog = kcu.constraint_catalog
152 AND tc.constraint_schema = kcu.constraint_schema
153 AND tc.constraint_name = kcu.constraint_name
154
155 LEFT JOIN information_schema.referential_constraints rc
156 ON tc.constraint_catalog = rc.constraint_catalog
157 AND tc.constraint_schema = rc.constraint_schema
158 AND tc.constraint_name = rc.constraint_name
159
160 LEFT JOIN information_schema.constraint_column_usage ccu
161 ON rc.unique_constraint_catalog = ccu.constraint_catalog
162 AND rc.unique_constraint_schema = ccu.constraint_schema
163 AND rc.unique_constraint_name = ccu.constraint_name
164
165 where tc.table_name = lower('{0}')
166 and lower(tc.constraint_type) in ('primary key')
167 and kcu.column_name is not null
168 ;", m_Realm);
169
170 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
171 using (NpgsqlCommand cmd = new NpgsqlCommand(query, conn))
172 {
173 conn.Open();
174 using (NpgsqlDataReader rdr = cmd.ExecuteReader())
175 {
176 while (rdr.Read())
177 {
178 // query produces 0 to many rows of single column, so always add the first item in each row
179 constraints.Add((string)rdr[0]);
180 }
181 }
182 return constraints;
183 }
184 }
185
186 public virtual T[] Get(string field, string key)
187 {
188 return Get(new string[] { field }, new string[] { key });
189 }
190
191 public virtual T[] Get(string[] fields, string[] keys)
192 {
193 if (fields.Length != keys.Length)
194 return new T[0];
195
196 List<string> terms = new List<string>();
197
198 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
199 using (NpgsqlCommand cmd = new NpgsqlCommand())
200 {
201
202 for (int i = 0; i < fields.Length; i++)
203 {
204 if ( m_FieldTypes.ContainsKey(fields[i]) )
205 cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i], m_FieldTypes[fields[i]]));
206 else
207 cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
208
209 terms.Add(" \"" + fields[i] + "\" = :" + fields[i]);
210 }
211
212 string where = String.Join(" AND ", terms.ToArray());
213
214 string query = String.Format("SELECT * FROM {0} WHERE {1}",
215 m_Realm, where);
216
217 cmd.Connection = conn;
218 cmd.CommandText = query;
219 conn.Open();
220 return DoQuery(cmd);
221 }
222 }
223
224 protected T[] DoQuery(NpgsqlCommand cmd)
225 {
226 List<T> result = new List<T>();
227 if (cmd.Connection == null)
228 {
229 cmd.Connection = new NpgsqlConnection(m_connectionString);
230 }
231 if (cmd.Connection.State == ConnectionState.Closed)
232 {
233 cmd.Connection.Open();
234 }
235 using (NpgsqlDataReader reader = cmd.ExecuteReader())
236 {
237 if (reader == null)
238 return new T[0];
239
240 CheckColumnNames(reader);
241
242 while (reader.Read())
243 {
244 T row = new T();
245
246 foreach (string name in m_Fields.Keys)
247 {
248 if (m_Fields[name].GetValue(row) is bool)
249 {
250 int v = Convert.ToInt32(reader[name]);
251 m_Fields[name].SetValue(row, v != 0 ? true : false);
252 }
253 else if (m_Fields[name].GetValue(row) is UUID)
254 {
255 UUID uuid = UUID.Zero;
256
257 UUID.TryParse(reader[name].ToString(), out uuid);
258 m_Fields[name].SetValue(row, uuid);
259 }
260 else if (m_Fields[name].GetValue(row) is int)
261 {
262 int v = Convert.ToInt32(reader[name]);
263 m_Fields[name].SetValue(row, v);
264 }
265 else
266 {
267 m_Fields[name].SetValue(row, reader[name]);
268 }
269 }
270
271 if (m_DataField != null)
272 {
273 Dictionary<string, string> data =
274 new Dictionary<string, string>();
275
276 foreach (string col in m_ColumnNames)
277 {
278 data[col] = reader[col].ToString();
279
280 if (data[col] == null)
281 data[col] = String.Empty;
282 }
283
284 m_DataField.SetValue(row, data);
285 }
286
287 result.Add(row);
288 }
289 return result.ToArray();
290 }
291 }
292
293 public virtual T[] Get(string where)
294 {
295 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
296 using (NpgsqlCommand cmd = new NpgsqlCommand())
297 {
298
299 string query = String.Format("SELECT * FROM {0} WHERE {1}",
300 m_Realm, where);
301 cmd.Connection = conn;
302 cmd.CommandText = query;
303
304 //m_log.WarnFormat("[PGSQLGenericTable]: SELECT {0} WHERE {1}", m_Realm, where);
305
306 conn.Open();
307 return DoQuery(cmd);
308 }
309 }
310
311 public virtual bool Store(T row)
312 {
313 List<string> constraintFields = GetConstraints();
314 List<KeyValuePair<string, string>> constraints = new List<KeyValuePair<string, string>>();
315
316 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
317 using (NpgsqlCommand cmd = new NpgsqlCommand())
318 {
319
320 StringBuilder query = new StringBuilder();
321 List<String> names = new List<String>();
322 List<String> values = new List<String>();
323
324 foreach (FieldInfo fi in m_Fields.Values)
325 {
326 names.Add(fi.Name);
327 values.Add(":" + fi.Name);
328 // Temporarily return more information about what field is unexpectedly null for
329 // http://opensimulator.org/mantis/view.php?id=5403. This might be due to a bug in the
330 // InventoryTransferModule or we may be required to substitute a DBNull here.
331 if (fi.GetValue(row) == null)
332 throw new NullReferenceException(
333 string.Format(
334 "[PGSQL GENERIC TABLE HANDLER]: Trying to store field {0} for {1} which is unexpectedly null",
335 fi.Name, row));
336
337 if (constraintFields.Count > 0 && constraintFields.Contains(fi.Name))
338 {
339 constraints.Add(new KeyValuePair<string, string>(fi.Name, fi.GetValue(row).ToString() ));
340 }
341 if (m_FieldTypes.ContainsKey(fi.Name))
342 cmd.Parameters.Add(m_database.CreateParameter(fi.Name, fi.GetValue(row), m_FieldTypes[fi.Name]));
343 else
344 cmd.Parameters.Add(m_database.CreateParameter(fi.Name, fi.GetValue(row)));
345 }
346
347 if (m_DataField != null)
348 {
349 Dictionary<string, string> data =
350 (Dictionary<string, string>)m_DataField.GetValue(row);
351
352 foreach (KeyValuePair<string, string> kvp in data)
353 {
354 if (constraintFields.Count > 0 && constraintFields.Contains(kvp.Key))
355 {
356 constraints.Add(new KeyValuePair<string, string>(kvp.Key, kvp.Key));
357 }
358 names.Add(kvp.Key);
359 values.Add(":" + kvp.Key);
360
361 if (m_FieldTypes.ContainsKey(kvp.Key))
362 cmd.Parameters.Add(m_database.CreateParameter("" + kvp.Key, kvp.Value, m_FieldTypes[kvp.Key]));
363 else
364 cmd.Parameters.Add(m_database.CreateParameter("" + kvp.Key, kvp.Value));
365 }
366
367 }
368
369 query.AppendFormat("UPDATE {0} SET ", m_Realm);
370 int i = 0;
371 for (i = 0; i < names.Count - 1; i++)
372 {
373 query.AppendFormat("\"{0}\" = {1}, ", names[i], values[i]);
374 }
375 query.AppendFormat("\"{0}\" = {1} ", names[i], values[i]);
376 if (constraints.Count > 0)
377 {
378 List<string> terms = new List<string>();
379 for (int j = 0; j < constraints.Count; j++)
380 {
381 terms.Add(String.Format(" \"{0}\" = :{0}", constraints[j].Key));
382 }
383 string where = String.Join(" AND ", terms.ToArray());
384 query.AppendFormat(" WHERE {0} ", where);
385
386 }
387 cmd.Connection = conn;
388 cmd.CommandText = query.ToString();
389
390 conn.Open();
391 if (cmd.ExecuteNonQuery() > 0)
392 {
393 //m_log.WarnFormat("[PGSQLGenericTable]: Updating {0}", m_Realm);
394 return true;
395 }
396 else
397 {
398 // assume record has not yet been inserted
399
400 query = new StringBuilder();
401 query.AppendFormat("INSERT INTO {0} (\"", m_Realm);
402 query.Append(String.Join("\",\"", names.ToArray()));
403 query.Append("\") values (" + String.Join(",", values.ToArray()) + ")");
404 cmd.Connection = conn;
405 cmd.CommandText = query.ToString();
406
407 // m_log.WarnFormat("[PGSQLGenericTable]: Inserting into {0} sql {1}", m_Realm, cmd.CommandText);
408
409 if (conn.State != ConnectionState.Open)
410 conn.Open();
411 if (cmd.ExecuteNonQuery() > 0)
412 return true;
413 }
414
415 return false;
416 }
417 }
418
419 public virtual bool Delete(string field, string key)
420 {
421 return Delete(new string[] { field }, new string[] { key });
422 }
423
424 public virtual bool Delete(string[] fields, string[] keys)
425 {
426 if (fields.Length != keys.Length)
427 return false;
428
429 List<string> terms = new List<string>();
430
431 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
432 using (NpgsqlCommand cmd = new NpgsqlCommand())
433 {
434 for (int i = 0; i < fields.Length; i++)
435 {
436 if (m_FieldTypes.ContainsKey(fields[i]))
437 cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i], m_FieldTypes[fields[i]]));
438 else
439 cmd.Parameters.Add(m_database.CreateParameter(fields[i], keys[i]));
440
441 terms.Add(" \"" + fields[i] + "\" = :" + fields[i]);
442 }
443
444 string where = String.Join(" AND ", terms.ToArray());
445
446 string query = String.Format("DELETE FROM {0} WHERE {1}", m_Realm, where);
447
448 cmd.Connection = conn;
449 cmd.CommandText = query;
450 conn.Open();
451
452 if (cmd.ExecuteNonQuery() > 0)
453 {
454 //m_log.Warn("[PGSQLGenericTable]: " + deleteCommand);
455 return true;
456 }
457 return false;
458 }
459 }
460 public long GetCount(string field, string key)
461 {
462 return GetCount(new string[] { field }, new string[] { key });
463 }
464
465 public long GetCount(string[] fields, string[] keys)
466 {
467 if (fields.Length != keys.Length)
468 return 0;
469
470 List<string> terms = new List<string>();
471
472 using (NpgsqlCommand cmd = new NpgsqlCommand())
473 {
474 for (int i = 0; i < fields.Length; i++)
475 {
476 cmd.Parameters.AddWithValue(fields[i], keys[i]);
477 terms.Add("\"" + fields[i] + "\" = :" + fields[i]);
478 }
479
480 string where = String.Join(" and ", terms.ToArray());
481
482 string query = String.Format("select count(*) from {0} where {1}",
483 m_Realm, where);
484
485 cmd.CommandText = query;
486
487 Object result = DoQueryScalar(cmd);
488
489 return Convert.ToInt64(result);
490 }
491 }
492
493 public long GetCount(string where)
494 {
495 using (NpgsqlCommand cmd = new NpgsqlCommand())
496 {
497 string query = String.Format("select count(*) from {0} where {1}",
498 m_Realm, where);
499
500 cmd.CommandText = query;
501
502 object result = DoQueryScalar(cmd);
503
504 return Convert.ToInt64(result);
505 }
506 }
507
508 public object DoQueryScalar(NpgsqlCommand cmd)
509 {
510 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_ConnectionString))
511 {
512 dbcon.Open();
513 cmd.Connection = dbcon;
514
515 return cmd.ExecuteScalar();
516 }
517 }
518 }
519}
diff --git a/OpenSim/Data/PGSQL/PGSQLGridUserData.cs b/OpenSim/Data/PGSQL/PGSQLGridUserData.cs
new file mode 100644
index 0000000..89319f3
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLGridUserData.cs
@@ -0,0 +1,68 @@
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.Data;
31using System.Reflection;
32using System.Threading;
33using log4net;
34using OpenMetaverse;
35using OpenSim.Framework;
36
37namespace OpenSim.Data.PGSQL
38{
39 /// <summary>
40 /// A PGSQL Interface for Avatar Storage
41 /// </summary>
42 public class PGSQLGridUserData : PGSQLGenericTableHandler<GridUserData>,
43 IGridUserData
44 {
45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 public PGSQLGridUserData(string connectionString, string realm) :
48 base(connectionString, realm, "GridUserStore")
49 {
50 }
51
52 public new GridUserData Get(string userID)
53 {
54 GridUserData[] ret = Get("UserID", userID);
55
56 if (ret.Length == 0)
57 return null;
58
59 return ret[0];
60 }
61
62 public GridUserData[] GetAll(string userID)
63 {
64 return base.Get(String.Format("\"UserID\" LIKE '{0}%'", userID));
65 }
66
67 }
68}
diff --git a/OpenSim/Data/PGSQL/PGSQLGroupsData.cs b/OpenSim/Data/PGSQL/PGSQLGroupsData.cs
new file mode 100644
index 0000000..ed75b63
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLGroupsData.cs
@@ -0,0 +1,481 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using OpenSim.Framework;
33using OpenMetaverse;
34using Npgsql;
35
36namespace OpenSim.Data.PGSQL
37{
38 public class PGSQLGroupsData : IGroupsData
39 {
40 private PGSqlGroupsGroupsHandler m_Groups;
41 private PGSqlGroupsMembershipHandler m_Membership;
42 private PGSqlGroupsRolesHandler m_Roles;
43 private PGSqlGroupsRoleMembershipHandler m_RoleMembership;
44 private PGSqlGroupsInvitesHandler m_Invites;
45 private PGSqlGroupsNoticesHandler m_Notices;
46 private PGSqlGroupsPrincipalsHandler m_Principals;
47
48 public PGSQLGroupsData(string connectionString, string realm)
49 {
50 m_Groups = new PGSqlGroupsGroupsHandler(connectionString, realm + "_groups", realm + "_Store");
51 m_Membership = new PGSqlGroupsMembershipHandler(connectionString, realm + "_membership");
52 m_Roles = new PGSqlGroupsRolesHandler(connectionString, realm + "_roles");
53 m_RoleMembership = new PGSqlGroupsRoleMembershipHandler(connectionString, realm + "_rolemembership");
54 m_Invites = new PGSqlGroupsInvitesHandler(connectionString, realm + "_invites");
55 m_Notices = new PGSqlGroupsNoticesHandler(connectionString, realm + "_notices");
56 m_Principals = new PGSqlGroupsPrincipalsHandler(connectionString, realm + "_principals");
57 }
58
59 #region groups table
60 public bool StoreGroup(GroupData data)
61 {
62 return m_Groups.Store(data);
63 }
64
65 public GroupData RetrieveGroup(UUID groupID)
66 {
67 GroupData[] groups = m_Groups.Get("GroupID", groupID.ToString());
68 if (groups.Length > 0)
69 return groups[0];
70
71 return null;
72 }
73
74 public GroupData RetrieveGroup(string name)
75 {
76 GroupData[] groups = m_Groups.Get("Name", name);
77 if (groups.Length > 0)
78 return groups[0];
79
80 return null;
81 }
82
83 public GroupData[] RetrieveGroups(string pattern)
84 {
85 if (string.IsNullOrEmpty(pattern)) // True for where clause
86 pattern = " true ORDER BY lower(\"Name\") LIMIT 100";
87 else
88 pattern = string.Format(" lower(\"Name\") LIKE lower('%{0}%') ORDER BY lower(\"Name\") LIMIT 100", pattern);
89
90 return m_Groups.Get(pattern);
91 }
92
93 public bool DeleteGroup(UUID groupID)
94 {
95 return m_Groups.Delete("GroupID", groupID.ToString());
96 }
97
98 public int GroupsCount()
99 {
100 return (int)m_Groups.GetCount(" \"Location\" = \"\"");
101 }
102
103 #endregion
104
105 #region membership table
106 public MembershipData[] RetrieveMembers(UUID groupID)
107 {
108 return m_Membership.Get("GroupID", groupID.ToString());
109 }
110
111 public MembershipData RetrieveMember(UUID groupID, string pricipalID)
112 {
113 MembershipData[] m = m_Membership.Get(new string[] { "GroupID", "PrincipalID" },
114 new string[] { groupID.ToString(), pricipalID });
115 if (m != null && m.Length > 0)
116 return m[0];
117
118 return null;
119 }
120
121 public MembershipData[] RetrieveMemberships(string pricipalID)
122 {
123 return m_Membership.Get("PrincipalID", pricipalID.ToString());
124 }
125
126 public bool StoreMember(MembershipData data)
127 {
128 return m_Membership.Store(data);
129 }
130
131 public bool DeleteMember(UUID groupID, string pricipalID)
132 {
133 return m_Membership.Delete(new string[] { "GroupID", "PrincipalID" },
134 new string[] { groupID.ToString(), pricipalID });
135 }
136
137 public int MemberCount(UUID groupID)
138 {
139 return (int)m_Membership.GetCount("GroupID", groupID.ToString());
140 }
141 #endregion
142
143 #region roles table
144 public bool StoreRole(RoleData data)
145 {
146 return m_Roles.Store(data);
147 }
148
149 public RoleData RetrieveRole(UUID groupID, UUID roleID)
150 {
151 RoleData[] data = m_Roles.Get(new string[] { "GroupID", "RoleID" },
152 new string[] { groupID.ToString(), roleID.ToString() });
153
154 if (data != null && data.Length > 0)
155 return data[0];
156
157 return null;
158 }
159
160 public RoleData[] RetrieveRoles(UUID groupID)
161 {
162 //return m_Roles.RetrieveRoles(groupID);
163 return m_Roles.Get("GroupID", groupID.ToString());
164 }
165
166 public bool DeleteRole(UUID groupID, UUID roleID)
167 {
168 return m_Roles.Delete(new string[] { "GroupID", "RoleID" },
169 new string[] { groupID.ToString(), roleID.ToString() });
170 }
171
172 public int RoleCount(UUID groupID)
173 {
174 return (int)m_Roles.GetCount("GroupID", groupID.ToString());
175 }
176
177
178 #endregion
179
180 #region rolememberhip table
181 public RoleMembershipData[] RetrieveRolesMembers(UUID groupID)
182 {
183 RoleMembershipData[] data = m_RoleMembership.Get("GroupID", groupID.ToString());
184
185 return data;
186 }
187
188 public RoleMembershipData[] RetrieveRoleMembers(UUID groupID, UUID roleID)
189 {
190 RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "RoleID" },
191 new string[] { groupID.ToString(), roleID.ToString() });
192
193 return data;
194 }
195
196 public RoleMembershipData[] RetrieveMemberRoles(UUID groupID, string principalID)
197 {
198 RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "PrincipalID" },
199 new string[] { groupID.ToString(), principalID.ToString() });
200
201 return data;
202 }
203
204 public RoleMembershipData RetrieveRoleMember(UUID groupID, UUID roleID, string principalID)
205 {
206 RoleMembershipData[] data = m_RoleMembership.Get(new string[] { "GroupID", "RoleID", "PrincipalID" },
207 new string[] { groupID.ToString(), roleID.ToString(), principalID.ToString() });
208
209 if (data != null && data.Length > 0)
210 return data[0];
211
212 return null;
213 }
214
215 public int RoleMemberCount(UUID groupID, UUID roleID)
216 {
217 return (int)m_RoleMembership.GetCount(new string[] { "GroupID", "RoleID" },
218 new string[] { groupID.ToString(), roleID.ToString() });
219 }
220
221 public bool StoreRoleMember(RoleMembershipData data)
222 {
223 return m_RoleMembership.Store(data);
224 }
225
226 public bool DeleteRoleMember(RoleMembershipData data)
227 {
228 return m_RoleMembership.Delete(new string[] { "GroupID", "RoleID", "PrincipalID"},
229 new string[] { data.GroupID.ToString(), data.RoleID.ToString(), data.PrincipalID });
230 }
231
232 public bool DeleteMemberAllRoles(UUID groupID, string principalID)
233 {
234 return m_RoleMembership.Delete(new string[] { "GroupID", "PrincipalID" },
235 new string[] { groupID.ToString(), principalID });
236 }
237
238 #endregion
239
240 #region principals table
241 public bool StorePrincipal(PrincipalData data)
242 {
243 return m_Principals.Store(data);
244 }
245
246 public PrincipalData RetrievePrincipal(string principalID)
247 {
248 PrincipalData[] p = m_Principals.Get("PrincipalID", principalID);
249 if (p != null && p.Length > 0)
250 return p[0];
251
252 return null;
253 }
254
255 public bool DeletePrincipal(string principalID)
256 {
257 return m_Principals.Delete("PrincipalID", principalID);
258 }
259 #endregion
260
261 #region invites table
262
263 public bool StoreInvitation(InvitationData data)
264 {
265 return m_Invites.Store(data);
266 }
267
268 public InvitationData RetrieveInvitation(UUID inviteID)
269 {
270 InvitationData[] invites = m_Invites.Get("InviteID", inviteID.ToString());
271
272 if (invites != null && invites.Length > 0)
273 return invites[0];
274
275 return null;
276 }
277
278 public InvitationData RetrieveInvitation(UUID groupID, string principalID)
279 {
280 InvitationData[] invites = m_Invites.Get(new string[] { "GroupID", "PrincipalID" },
281 new string[] { groupID.ToString(), principalID });
282
283 if (invites != null && invites.Length > 0)
284 return invites[0];
285
286 return null;
287 }
288
289 public bool DeleteInvite(UUID inviteID)
290 {
291 return m_Invites.Delete("InviteID", inviteID.ToString());
292 }
293
294 public void DeleteOldInvites()
295 {
296 m_Invites.DeleteOld();
297 }
298
299 #endregion
300
301 #region notices table
302
303 public bool StoreNotice(NoticeData data)
304 {
305 return m_Notices.Store(data);
306 }
307
308 public NoticeData RetrieveNotice(UUID noticeID)
309 {
310 NoticeData[] notices = m_Notices.Get("NoticeID", noticeID.ToString());
311
312 if (notices != null && notices.Length > 0)
313 return notices[0];
314
315 return null;
316 }
317
318 public NoticeData[] RetrieveNotices(UUID groupID)
319 {
320 NoticeData[] notices = m_Notices.Get("GroupID", groupID.ToString());
321
322 return notices;
323 }
324
325 public bool DeleteNotice(UUID noticeID)
326 {
327 return m_Notices.Delete("NoticeID", noticeID.ToString());
328 }
329
330 public void DeleteOldNotices()
331 {
332 m_Notices.DeleteOld();
333 }
334
335 #endregion
336
337 #region combinations
338 public MembershipData RetrievePrincipalGroupMembership(string principalID, UUID groupID)
339 {
340 // TODO
341 return null;
342 }
343 public MembershipData[] RetrievePrincipalGroupMemberships(string principalID)
344 {
345 // TODO
346 return null;
347 }
348
349 #endregion
350 }
351
352 public class PGSqlGroupsGroupsHandler : PGSQLGenericTableHandler<GroupData>
353 {
354 protected override Assembly Assembly
355 {
356 // WARNING! Moving migrations to this assembly!!!
357 get { return GetType().Assembly; }
358 }
359
360 public PGSqlGroupsGroupsHandler(string connectionString, string realm, string store)
361 : base(connectionString, realm, store)
362 {
363 }
364
365 }
366
367 public class PGSqlGroupsMembershipHandler : PGSQLGenericTableHandler<MembershipData>
368 {
369 protected override Assembly Assembly
370 {
371 // WARNING! Moving migrations to this assembly!!!
372 get { return GetType().Assembly; }
373 }
374
375 public PGSqlGroupsMembershipHandler(string connectionString, string realm)
376 : base(connectionString, realm, string.Empty)
377 {
378 }
379
380 }
381
382 public class PGSqlGroupsRolesHandler : PGSQLGenericTableHandler<RoleData>
383 {
384 protected override Assembly Assembly
385 {
386 // WARNING! Moving migrations to this assembly!!!
387 get { return GetType().Assembly; }
388 }
389
390 public PGSqlGroupsRolesHandler(string connectionString, string realm)
391 : base(connectionString, realm, string.Empty)
392 {
393 }
394
395 }
396
397 public class PGSqlGroupsRoleMembershipHandler : PGSQLGenericTableHandler<RoleMembershipData>
398 {
399 protected override Assembly Assembly
400 {
401 // WARNING! Moving migrations to this assembly!!!
402 get { return GetType().Assembly; }
403 }
404
405 public PGSqlGroupsRoleMembershipHandler(string connectionString, string realm)
406 : base(connectionString, realm, string.Empty)
407 {
408 }
409
410 }
411
412 public class PGSqlGroupsInvitesHandler : PGSQLGenericTableHandler<InvitationData>
413 {
414 protected override Assembly Assembly
415 {
416 // WARNING! Moving migrations to this assembly!!!
417 get { return GetType().Assembly; }
418 }
419
420 public PGSqlGroupsInvitesHandler(string connectionString, string realm)
421 : base(connectionString, realm, string.Empty)
422 {
423 }
424
425 public void DeleteOld()
426 {
427 uint now = (uint)Util.UnixTimeSinceEpoch();
428
429 using (NpgsqlCommand cmd = new NpgsqlCommand())
430 {
431 cmd.CommandText = String.Format("delete from {0} where \"TMStamp\" < :tstamp", m_Realm);
432 cmd.Parameters.AddWithValue("tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
433
434 ExecuteNonQuery(cmd);
435 }
436
437 }
438 }
439
440 public class PGSqlGroupsNoticesHandler : PGSQLGenericTableHandler<NoticeData>
441 {
442 protected override Assembly Assembly
443 {
444 // WARNING! Moving migrations to this assembly!!!
445 get { return GetType().Assembly; }
446 }
447
448 public PGSqlGroupsNoticesHandler(string connectionString, string realm)
449 : base(connectionString, realm, string.Empty)
450 {
451 }
452
453 public void DeleteOld()
454 {
455 uint now = (uint)Util.UnixTimeSinceEpoch();
456
457 using (NpgsqlCommand cmd = new NpgsqlCommand())
458 {
459 cmd.CommandText = String.Format("delete from {0} where \"TMStamp\" < :tstamp", m_Realm);
460 cmd.Parameters.AddWithValue("tstamp", now - 14 * 24 * 60 * 60); // > 2 weeks old
461
462 ExecuteNonQuery(cmd);
463 }
464
465 }
466 }
467
468 public class PGSqlGroupsPrincipalsHandler : PGSQLGenericTableHandler<PrincipalData>
469 {
470 protected override Assembly Assembly
471 {
472 // WARNING! Moving migrations to this assembly!!!
473 get { return GetType().Assembly; }
474 }
475
476 public PGSqlGroupsPrincipalsHandler(string connectionString, string realm)
477 : base(connectionString, realm, string.Empty)
478 {
479 }
480 }
481}
diff --git a/OpenSim/Data/PGSQL/PGSQLHGTravelData.cs b/OpenSim/Data/PGSQL/PGSQLHGTravelData.cs
new file mode 100644
index 0000000..c71b15f
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLHGTravelData.cs
@@ -0,0 +1,80 @@
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.Data;
31using System.Reflection;
32using System.Threading;
33using log4net;
34using OpenMetaverse;
35using OpenSim.Framework;
36using Npgsql;
37
38namespace OpenSim.Data.PGSQL
39{
40 /// <summary>
41 /// A PGSQL Interface for user grid data
42 /// </summary>
43 public class PGSQLHGTravelData : PGSQLGenericTableHandler<HGTravelingData>, IHGTravelingData
44 {
45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 public PGSQLHGTravelData(string connectionString, string realm) : base(connectionString, realm, "HGTravelStore") { }
48
49 public HGTravelingData Get(UUID sessionID)
50 {
51 HGTravelingData[] ret = Get("SessionID", sessionID.ToString());
52
53 if (ret.Length == 0)
54 return null;
55
56 return ret[0];
57 }
58
59 public HGTravelingData[] GetSessions(UUID userID)
60 {
61 return base.Get("UserID", userID.ToString());
62 }
63
64 public bool Delete(UUID sessionID)
65 {
66 return Delete("SessionID", sessionID.ToString());
67 }
68
69 public void DeleteOld()
70 {
71 using (NpgsqlCommand cmd = new NpgsqlCommand())
72 {
73 cmd.CommandText = String.Format(@"delete from {0} where ""TMStamp"" < CURRENT_DATE - INTERVAL '2 day'", m_Realm);
74
75 ExecuteNonQuery(cmd);
76 }
77
78 }
79 }
80}
diff --git a/OpenSim/Data/PGSQL/PGSQLInventoryData.cs b/OpenSim/Data/PGSQL/PGSQLInventoryData.cs
new file mode 100644
index 0000000..c999433
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLInventoryData.cs
@@ -0,0 +1,831 @@
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.Data;
31using System.Reflection;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35using Npgsql;
36
37namespace OpenSim.Data.PGSQL
38{
39 /// <summary>
40 /// A PGSQL interface for the inventory server
41 /// </summary>
42 public class PGSQLInventoryData : IInventoryDataPlugin
43 {
44 private const string _migrationStore = "InventoryStore";
45
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 /// <summary>
49 /// The database manager
50 /// </summary>
51 private PGSQLManager database;
52 private string m_connectionString;
53
54 #region IPlugin members
55
56 [Obsolete("Cannot be default-initialized!")]
57 public void Initialise()
58 {
59 m_log.Info("[PGSQLInventoryData]: " + Name + " cannot be default-initialized!");
60 throw new PluginNotInitialisedException(Name);
61 }
62
63 /// <summary>
64 /// Loads and initialises the PGSQL inventory storage interface
65 /// </summary>
66 /// <param name="connectionString">connect string</param>
67 /// <remarks>use PGSQL_connection.ini</remarks>
68 public void Initialise(string connectionString)
69 {
70 m_connectionString = connectionString;
71 database = new PGSQLManager(connectionString);
72
73 //New migrations check of store
74 database.CheckMigration(_migrationStore);
75 }
76
77 /// <summary>
78 /// The name of this DB provider
79 /// </summary>
80 /// <returns>A string containing the name of the DB provider</returns>
81 public string Name
82 {
83 get { return "PGSQL Inventory Data Interface"; }
84 }
85
86 /// <summary>
87 /// Closes this DB provider
88 /// </summary>
89 public void Dispose()
90 {
91 database = null;
92 }
93
94 /// <summary>
95 /// Returns the version of this DB provider
96 /// </summary>
97 /// <returns>A string containing the DB provider</returns>
98 public string Version
99 {
100 get { return database.getVersion(); }
101 }
102
103 #endregion
104
105 #region Folder methods
106
107 /// <summary>
108 /// Returns a list of the root folders within a users inventory
109 /// </summary>
110 /// <param name="user">The user whos inventory is to be searched</param>
111 /// <returns>A list of folder objects</returns>
112 public List<InventoryFolderBase> getUserRootFolders(UUID user)
113 {
114 if (user == UUID.Zero)
115 return new List<InventoryFolderBase>();
116
117 return getInventoryFolders(UUID.Zero, user);
118 }
119
120 /// <summary>
121 /// see InventoryItemBase.getUserRootFolder
122 /// </summary>
123 /// <param name="user">the User UUID</param>
124 /// <returns></returns>
125 public InventoryFolderBase getUserRootFolder(UUID user)
126 {
127 List<InventoryFolderBase> items = getUserRootFolders(user);
128
129 InventoryFolderBase rootFolder = null;
130
131 // There should only ever be one root folder for a user. However, if there's more
132 // than one we'll simply use the first one rather than failing. It would be even
133 // nicer to print some message to this effect, but this feels like it's too low a
134 // to put such a message out, and it's too minor right now to spare the time to
135 // suitably refactor.
136 if (items.Count > 0)
137 {
138 rootFolder = items[0];
139 }
140
141 return rootFolder;
142 }
143
144 /// <summary>
145 /// Returns a list of folders in a users inventory contained within the specified folder
146 /// </summary>
147 /// <param name="parentID">The folder to search</param>
148 /// <returns>A list of inventory folders</returns>
149 public List<InventoryFolderBase> getInventoryFolders(UUID parentID)
150 {
151 return getInventoryFolders(parentID, UUID.Zero);
152 }
153
154 /// <summary>
155 /// Returns a specified inventory folder
156 /// </summary>
157 /// <param name="folderID">The folder to return</param>
158 /// <returns>A folder class</returns>
159 public InventoryFolderBase getInventoryFolder(UUID folderID)
160 {
161 string sql = "SELECT * FROM inventoryfolders WHERE \"folderID\" = :folderID";
162 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
163 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
164 {
165 cmd.Parameters.Add(database.CreateParameter("folderID", folderID));
166 conn.Open();
167 using (NpgsqlDataReader reader = cmd.ExecuteReader())
168 {
169 if (reader.Read())
170 {
171 return readInventoryFolder(reader);
172 }
173 }
174 }
175 m_log.InfoFormat("[INVENTORY DB] : Found no inventory folder with ID : {0}", folderID);
176 return null;
177 }
178
179 /// <summary>
180 /// Returns all child folders in the hierarchy from the parent folder and down.
181 /// Does not return the parent folder itself.
182 /// </summary>
183 /// <param name="parentID">The folder to get subfolders for</param>
184 /// <returns>A list of inventory folders</returns>
185 public List<InventoryFolderBase> getFolderHierarchy(UUID parentID)
186 {
187 //Note maybe change this to use a Dataset that loading in all folders of a user and then go throw it that way.
188 //Note this is changed so it opens only one connection to the database and not everytime it wants to get data.
189
190 /* NOTE: the implementation below is very inefficient (makes a separate request to get subfolders for
191 * every found folder, recursively). Inventory code for other DBs has been already rewritten to get ALL
192 * inventory for a specific user at once.
193 *
194 * Meanwhile, one little thing is corrected: getFolderHierarchy(UUID.Zero) doesn't make sense and should never
195 * be used, so check for that and return an empty list.
196 */
197
198 List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
199
200 if (parentID == UUID.Zero)
201 return folders;
202
203 string sql = "SELECT * FROM inventoryfolders WHERE \"parentFolderID\" = :parentID";
204 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
205 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
206 {
207 cmd.Parameters.Add(database.CreateParameter("parentID", parentID));
208 conn.Open();
209 folders.AddRange(getInventoryFolders(cmd));
210
211 List<InventoryFolderBase> tempFolders = new List<InventoryFolderBase>();
212
213 foreach (InventoryFolderBase folderBase in folders)
214 {
215 tempFolders.AddRange(getFolderHierarchy(folderBase.ID, cmd));
216 }
217 if (tempFolders.Count > 0)
218 {
219 folders.AddRange(tempFolders);
220 }
221 }
222 return folders;
223 }
224
225 /// <summary>
226 /// Creates a new inventory folder
227 /// </summary>
228 /// <param name="folder">Folder to create</param>
229 public void addInventoryFolder(InventoryFolderBase folder)
230 {
231 string sql = "INSERT INTO inventoryfolders (\"folderID\", \"agentID\", \"parentFolderID\", \"folderName\", type, version) " +
232 " VALUES (:folderID, :agentID, :parentFolderID, :folderName, :type, :version);";
233
234 string folderName = folder.Name;
235 if (folderName.Length > 64)
236 {
237 folderName = folderName.Substring(0, 64);
238 m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on add");
239 }
240 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
241 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
242 {
243 cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
244 cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner));
245 cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
246 cmd.Parameters.Add(database.CreateParameter("folderName", folderName));
247 cmd.Parameters.Add(database.CreateParameter("type", folder.Type));
248 cmd.Parameters.Add(database.CreateParameter("version", folder.Version));
249 conn.Open();
250 try
251 {
252 cmd.ExecuteNonQuery();
253 }
254 catch (Exception e)
255 {
256 m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
257 }
258 }
259 }
260
261 /// <summary>
262 /// Updates an inventory folder
263 /// </summary>
264 /// <param name="folder">Folder to update</param>
265 public void updateInventoryFolder(InventoryFolderBase folder)
266 {
267 string sql = @"UPDATE inventoryfolders SET ""agentID"" = :agentID,
268 ""parentFolderID"" = :parentFolderID,
269 ""folderName"" = :folderName,
270 type = :type,
271 version = :version
272 WHERE folderID = :folderID";
273
274 string folderName = folder.Name;
275 if (folderName.Length > 64)
276 {
277 folderName = folderName.Substring(0, 64);
278 m_log.Warn("[INVENTORY DB]: Name field truncated from " + folder.Name.Length.ToString() + " to " + folderName.Length + " characters on update");
279 }
280 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
281 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
282 {
283 cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
284 cmd.Parameters.Add(database.CreateParameter("agentID", folder.Owner));
285 cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
286 cmd.Parameters.Add(database.CreateParameter("folderName", folderName));
287 cmd.Parameters.Add(database.CreateParameter("type", folder.Type));
288 cmd.Parameters.Add(database.CreateParameter("version", folder.Version));
289 conn.Open();
290 try
291 {
292 cmd.ExecuteNonQuery();
293 }
294 catch (Exception e)
295 {
296 m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
297 }
298 }
299 }
300
301 /// <summary>
302 /// Updates an inventory folder
303 /// </summary>
304 /// <param name="folder">Folder to update</param>
305 public void moveInventoryFolder(InventoryFolderBase folder)
306 {
307 string sql = @"UPDATE inventoryfolders SET ""parentFolderID"" = :parentFolderID WHERE ""folderID"" = :folderID";
308 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
309 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
310 {
311 cmd.Parameters.Add(database.CreateParameter("parentFolderID", folder.ParentID));
312 cmd.Parameters.Add(database.CreateParameter("folderID", folder.ID));
313 conn.Open();
314 try
315 {
316 cmd.ExecuteNonQuery();
317 }
318 catch (Exception e)
319 {
320 m_log.ErrorFormat("[INVENTORY DB]: Error : {0}", e.Message);
321 }
322 }
323 }
324
325 /// <summary>
326 /// Delete an inventory folder
327 /// </summary>
328 /// <param name="folderID">Id of folder to delete</param>
329 public void deleteInventoryFolder(UUID folderID)
330 {
331 string sql = @"SELECT * FROM inventoryfolders WHERE ""parentFolderID"" = :parentID";
332
333 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
334 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
335 {
336 List<InventoryFolderBase> subFolders;
337 cmd.Parameters.Add(database.CreateParameter("parentID", UUID.Zero));
338 conn.Open();
339 subFolders = getFolderHierarchy(folderID, cmd);
340
341
342 //Delete all sub-folders
343 foreach (InventoryFolderBase f in subFolders)
344 {
345 DeleteOneFolder(f.ID, conn);
346 DeleteItemsInFolder(f.ID, conn);
347 }
348
349 //Delete the actual row
350 DeleteOneFolder(folderID, conn);
351 DeleteItemsInFolder(folderID, conn);
352 }
353 }
354
355 #endregion
356
357 #region Item Methods
358
359 /// <summary>
360 /// Returns a list of items in a specified folder
361 /// </summary>
362 /// <param name="folderID">The folder to search</param>
363 /// <returns>A list containing inventory items</returns>
364 public List<InventoryItemBase> getInventoryInFolder(UUID folderID)
365 {
366 string sql = @"SELECT * FROM inventoryitems WHERE ""parentFolderID"" = :parentFolderID";
367 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
368 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
369 {
370 cmd.Parameters.Add(database.CreateParameter("parentFolderID", folderID));
371 conn.Open();
372 List<InventoryItemBase> items = new List<InventoryItemBase>();
373
374 using (NpgsqlDataReader reader = cmd.ExecuteReader())
375 {
376 while (reader.Read())
377 {
378 items.Add(readInventoryItem(reader));
379 }
380 }
381 return items;
382 }
383 }
384
385 /// <summary>
386 /// Returns a specified inventory item
387 /// </summary>
388 /// <param name="itemID">The item ID</param>
389 /// <returns>An inventory item</returns>
390 public InventoryItemBase getInventoryItem(UUID itemID)
391 {
392 string sql = @"SELECT * FROM inventoryitems WHERE ""inventoryID"" = :inventoryID";
393 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
394 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
395 {
396 cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID));
397 conn.Open();
398 using (NpgsqlDataReader reader = cmd.ExecuteReader())
399 {
400 if (reader.Read())
401 {
402 return readInventoryItem(reader);
403 }
404 }
405 }
406
407 m_log.InfoFormat("[INVENTORY DB]: Found no inventory item with ID : {0}", itemID);
408 return null;
409 }
410
411 /// <summary>
412 /// Adds a specified item to the database
413 /// </summary>
414 /// <param name="item">The inventory item</param>
415 public void addInventoryItem(InventoryItemBase item)
416 {
417 if (getInventoryItem(item.ID) != null)
418 {
419 updateInventoryItem(item);
420 return;
421 }
422
423 string sql = @"INSERT INTO inventoryitems
424 (""inventoryID"", ""assetID"", ""assetType"", ""parentFolderID"", ""avatarID"", ""inventoryName"",
425 ""inventoryDescription"", ""inventoryNextPermissions"", ""inventoryCurrentPermissions"",
426 ""invType"", ""creatorID"", ""inventoryBasePermissions"", ""inventoryEveryOnePermissions"", ""inventoryGroupPermissions"",
427 ""salePrice"", ""SaleType"", ""creationDate"", ""groupID"", ""groupOwned"", flags)
428 VALUES
429 (:inventoryID, :assetID, :assetType, :parentFolderID, :avatarID, :inventoryName, :inventoryDescription,
430 :inventoryNextPermissions, :inventoryCurrentPermissions, :invType, :creatorID,
431 :inventoryBasePermissions, :inventoryEveryOnePermissions, :inventoryGroupPermissions, :SalePrice, :SaleType,
432 :creationDate, :groupID, :groupOwned, :flags)";
433
434 string itemName = item.Name;
435 if (item.Name.Length > 64)
436 {
437 itemName = item.Name.Substring(0, 64);
438 m_log.Warn("[INVENTORY DB]: Name field truncated from " + item.Name.Length.ToString() + " to " + itemName.Length.ToString() + " characters");
439 }
440
441 string itemDesc = item.Description;
442 if (item.Description.Length > 128)
443 {
444 itemDesc = item.Description.Substring(0, 128);
445 m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters");
446 }
447
448 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
449 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
450 {
451 command.Parameters.Add(database.CreateParameter("inventoryID", item.ID));
452 command.Parameters.Add(database.CreateParameter("assetID", item.AssetID));
453 command.Parameters.Add(database.CreateParameter("assetType", item.AssetType));
454 command.Parameters.Add(database.CreateParameter("parentFolderID", item.Folder));
455 command.Parameters.Add(database.CreateParameter("avatarID", item.Owner));
456 command.Parameters.Add(database.CreateParameter("inventoryName", itemName));
457 command.Parameters.Add(database.CreateParameter("inventoryDescription", itemDesc));
458 command.Parameters.Add(database.CreateParameter("inventoryNextPermissions", item.NextPermissions));
459 command.Parameters.Add(database.CreateParameter("inventoryCurrentPermissions", item.CurrentPermissions));
460 command.Parameters.Add(database.CreateParameter("invType", item.InvType));
461 command.Parameters.Add(database.CreateParameter("creatorID", item.CreatorId));
462 command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions));
463 command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions));
464 command.Parameters.Add(database.CreateParameter("inventoryGroupPermissions", item.GroupPermissions));
465 command.Parameters.Add(database.CreateParameter("SalePrice", item.SalePrice));
466 command.Parameters.Add(database.CreateParameter("SaleType", item.SaleType));
467 command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate));
468 command.Parameters.Add(database.CreateParameter("groupID", item.GroupID));
469 command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned));
470 command.Parameters.Add(database.CreateParameter("flags", item.Flags));
471 conn.Open();
472 try
473 {
474 command.ExecuteNonQuery();
475 }
476 catch (Exception e)
477 {
478 m_log.Error("[INVENTORY DB]: Error inserting item :" + e.Message);
479 }
480 }
481
482 sql = @"UPDATE inventoryfolders SET version = version + 1 WHERE ""folderID"" = @folderID";
483 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
484 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
485 {
486 command.Parameters.Add(database.CreateParameter("folderID", item.Folder.ToString()));
487 conn.Open();
488 try
489 {
490 command.ExecuteNonQuery();
491 }
492 catch (Exception e)
493 {
494 m_log.Error("[INVENTORY DB] Error updating inventory folder for new item :" + e.Message);
495 }
496 }
497 }
498
499 /// <summary>
500 /// Updates the specified inventory item
501 /// </summary>
502 /// <param name="item">Inventory item to update</param>
503 public void updateInventoryItem(InventoryItemBase item)
504 {
505 string sql = @"UPDATE inventoryitems SET ""assetID"" = :assetID,
506 ""assetType"" = :assetType,
507 ""parentFolderID"" = :parentFolderID,
508 ""avatarID"" = :avatarID,
509 ""inventoryName"" = :inventoryName,
510 ""inventoryDescription"" = :inventoryDescription,
511 ""inventoryNextPermissions"" = :inventoryNextPermissions,
512 ""inventoryCurrentPermissions"" = :inventoryCurrentPermissions,
513 ""invType"" = :invType,
514 ""creatorID"" = :creatorID,
515 ""inventoryBasePermissions"" = :inventoryBasePermissions,
516 ""inventoryEveryOnePermissions"" = :inventoryEveryOnePermissions,
517 ""inventoryGroupPermissions"" = :inventoryGroupPermissions,
518 ""salePrice"" = :SalePrice,
519 ""saleType"" = :SaleType,
520 ""creationDate"" = :creationDate,
521 ""groupID"" = :groupID,
522 ""groupOwned"" = :groupOwned,
523 flags = :flags
524 WHERE ""inventoryID"" = :inventoryID";
525
526 string itemName = item.Name;
527 if (item.Name.Length > 64)
528 {
529 itemName = item.Name.Substring(0, 64);
530 m_log.Warn("[INVENTORY DB]: Name field truncated from " + item.Name.Length.ToString() + " to " + itemName.Length.ToString() + " characters on update");
531 }
532
533 string itemDesc = item.Description;
534 if (item.Description.Length > 128)
535 {
536 itemDesc = item.Description.Substring(0, 128);
537 m_log.Warn("[INVENTORY DB]: Description field truncated from " + item.Description.Length.ToString() + " to " + itemDesc.Length.ToString() + " characters on update");
538 }
539
540 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
541 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
542 {
543 command.Parameters.Add(database.CreateParameter("inventoryID", item.ID));
544 command.Parameters.Add(database.CreateParameter("assetID", item.AssetID));
545 command.Parameters.Add(database.CreateParameter("assetType", item.AssetType));
546 command.Parameters.Add(database.CreateParameter("parentFolderID", item.Folder));
547 command.Parameters.Add(database.CreateParameter("avatarID", item.Owner));
548 command.Parameters.Add(database.CreateParameter("inventoryName", itemName));
549 command.Parameters.Add(database.CreateParameter("inventoryDescription", itemDesc));
550 command.Parameters.Add(database.CreateParameter("inventoryNextPermissions", item.NextPermissions));
551 command.Parameters.Add(database.CreateParameter("inventoryCurrentPermissions", item.CurrentPermissions));
552 command.Parameters.Add(database.CreateParameter("invType", item.InvType));
553 command.Parameters.Add(database.CreateParameter("creatorID", item.CreatorId));
554 command.Parameters.Add(database.CreateParameter("inventoryBasePermissions", item.BasePermissions));
555 command.Parameters.Add(database.CreateParameter("inventoryEveryOnePermissions", item.EveryOnePermissions));
556 command.Parameters.Add(database.CreateParameter("inventoryGroupPermissions", item.GroupPermissions));
557 command.Parameters.Add(database.CreateParameter("SalePrice", item.SalePrice));
558 command.Parameters.Add(database.CreateParameter("SaleType", item.SaleType));
559 command.Parameters.Add(database.CreateParameter("creationDate", item.CreationDate));
560 command.Parameters.Add(database.CreateParameter("groupID", item.GroupID));
561 command.Parameters.Add(database.CreateParameter("groupOwned", item.GroupOwned));
562 command.Parameters.Add(database.CreateParameter("flags", item.Flags));
563 conn.Open();
564 try
565 {
566 command.ExecuteNonQuery();
567 }
568 catch (Exception e)
569 {
570 m_log.Error("[INVENTORY DB]: Error updating item :" + e.Message);
571 }
572 }
573 }
574
575 // See IInventoryDataPlugin
576
577 /// <summary>
578 /// Delete an item in inventory database
579 /// </summary>
580 /// <param name="itemID">the item UUID</param>
581 public void deleteInventoryItem(UUID itemID)
582 {
583 string sql = @"DELETE FROM inventoryitems WHERE ""inventoryID""=:inventoryID";
584 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
585 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
586 {
587 cmd.Parameters.Add(database.CreateParameter("inventoryID", itemID));
588 try
589 {
590 conn.Open();
591 cmd.ExecuteNonQuery();
592 }
593 catch (Exception e)
594 {
595 m_log.Error("[INVENTORY DB]: Error deleting item :" + e.Message);
596 }
597 }
598 }
599
600 public InventoryItemBase queryInventoryItem(UUID itemID)
601 {
602 return getInventoryItem(itemID);
603 }
604
605 public InventoryFolderBase queryInventoryFolder(UUID folderID)
606 {
607 return getInventoryFolder(folderID);
608 }
609
610 /// <summary>
611 /// Returns all activated gesture-items in the inventory of the specified avatar.
612 /// </summary>
613 /// <param name="avatarID">The <see cref="UUID"/> of the avatar</param>
614 /// <returns>
615 /// The list of gestures (<see cref="InventoryItemBase"/>s)
616 /// </returns>
617 public List<InventoryItemBase> fetchActiveGestures(UUID avatarID)
618 {
619 string sql = @"SELECT * FROM inventoryitems WHERE ""avatarID"" = :uuid AND ""assetType"" = :assetType and flags = 1";
620 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
621 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
622 {
623 cmd.Parameters.Add(database.CreateParameter("uuid", avatarID));
624 cmd.Parameters.Add(database.CreateParameter("assetType", (int)AssetType.Gesture));
625 conn.Open();
626 using (NpgsqlDataReader reader = cmd.ExecuteReader())
627 {
628 List<InventoryItemBase> gestureList = new List<InventoryItemBase>();
629 while (reader.Read())
630 {
631 gestureList.Add(readInventoryItem(reader));
632 }
633 return gestureList;
634 }
635 }
636 }
637
638 #endregion
639
640 #region Private methods
641
642 /// <summary>
643 /// Delete an item in inventory database
644 /// </summary>
645 /// <param name="folderID">the item ID</param>
646 /// <param name="connection">connection to the database</param>
647 private void DeleteItemsInFolder(UUID folderID, NpgsqlConnection connection)
648 {
649 using (NpgsqlCommand command = new NpgsqlCommand(@"DELETE FROM inventoryitems WHERE ""folderID""=:folderID", connection))
650 {
651 command.Parameters.Add(database.CreateParameter("folderID", folderID));
652
653 try
654 {
655 command.ExecuteNonQuery();
656 }
657 catch (Exception e)
658 {
659 m_log.Error("[INVENTORY DB] Error deleting item :" + e.Message);
660 }
661 }
662 }
663
664 /// <summary>
665 /// Gets the folder hierarchy in a loop.
666 /// </summary>
667 /// <param name="parentID">parent ID.</param>
668 /// <param name="command">SQL command/connection to database</param>
669 /// <returns></returns>
670 private static List<InventoryFolderBase> getFolderHierarchy(UUID parentID, NpgsqlCommand command)
671 {
672 command.Parameters["parentID"].Value = parentID.Guid; //.ToString();
673
674 List<InventoryFolderBase> folders = getInventoryFolders(command);
675
676 if (folders.Count > 0)
677 {
678 List<InventoryFolderBase> tempFolders = new List<InventoryFolderBase>();
679
680 foreach (InventoryFolderBase folderBase in folders)
681 {
682 tempFolders.AddRange(getFolderHierarchy(folderBase.ID, command));
683 }
684
685 if (tempFolders.Count > 0)
686 {
687 folders.AddRange(tempFolders);
688 }
689 }
690 return folders;
691 }
692
693 /// <summary>
694 /// Gets the inventory folders.
695 /// </summary>
696 /// <param name="parentID">parentID, use UUID.Zero to get root</param>
697 /// <param name="user">user id, use UUID.Zero, if you want all folders from a parentID.</param>
698 /// <returns></returns>
699 private List<InventoryFolderBase> getInventoryFolders(UUID parentID, UUID user)
700 {
701 string sql = @"SELECT * FROM inventoryfolders WHERE ""parentFolderID"" = :parentID AND ""agentID"" = :uuid";
702 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
703 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
704 {
705 if (user == UUID.Zero)
706 {
707 command.Parameters.Add(database.CreateParameter("uuid", "%"));
708 }
709 else
710 {
711 command.Parameters.Add(database.CreateParameter("uuid", user));
712 }
713 command.Parameters.Add(database.CreateParameter("parentID", parentID));
714 conn.Open();
715 return getInventoryFolders(command);
716 }
717 }
718
719 /// <summary>
720 /// Gets the inventory folders.
721 /// </summary>
722 /// <param name="command">SQLcommand.</param>
723 /// <returns></returns>
724 private static List<InventoryFolderBase> getInventoryFolders(NpgsqlCommand command)
725 {
726 using (NpgsqlDataReader reader = command.ExecuteReader())
727 {
728
729 List<InventoryFolderBase> items = new List<InventoryFolderBase>();
730 while (reader.Read())
731 {
732 items.Add(readInventoryFolder(reader));
733 }
734 return items;
735 }
736 }
737
738 /// <summary>
739 /// Reads a list of inventory folders returned by a query.
740 /// </summary>
741 /// <param name="reader">A PGSQL Data Reader</param>
742 /// <returns>A List containing inventory folders</returns>
743 protected static InventoryFolderBase readInventoryFolder(NpgsqlDataReader reader)
744 {
745 try
746 {
747 InventoryFolderBase folder = new InventoryFolderBase();
748 folder.Owner = DBGuid.FromDB(reader["agentID"]);
749 folder.ParentID = DBGuid.FromDB(reader["parentFolderID"]);
750 folder.ID = DBGuid.FromDB(reader["folderID"]);
751 folder.Name = (string)reader["folderName"];
752 folder.Type = (short)reader["type"];
753 folder.Version = Convert.ToUInt16(reader["version"]);
754
755 return folder;
756 }
757 catch (Exception e)
758 {
759 m_log.Error("[INVENTORY DB] Error reading inventory folder :" + e.Message);
760 }
761
762 return null;
763 }
764
765 /// <summary>
766 /// Reads a one item from an SQL result
767 /// </summary>
768 /// <param name="reader">The SQL Result</param>
769 /// <returns>the item read</returns>
770 private static InventoryItemBase readInventoryItem(IDataRecord reader)
771 {
772 try
773 {
774 InventoryItemBase item = new InventoryItemBase();
775
776 item.ID = DBGuid.FromDB(reader["inventoryID"]);
777 item.AssetID = DBGuid.FromDB(reader["assetID"]);
778 item.AssetType = Convert.ToInt32(reader["assetType"].ToString());
779 item.Folder = DBGuid.FromDB(reader["parentFolderID"]);
780 item.Owner = DBGuid.FromDB(reader["avatarID"]);
781 item.Name = reader["inventoryName"].ToString();
782 item.Description = reader["inventoryDescription"].ToString();
783 item.NextPermissions = Convert.ToUInt32(reader["inventoryNextPermissions"]);
784 item.CurrentPermissions = Convert.ToUInt32(reader["inventoryCurrentPermissions"]);
785 item.InvType = Convert.ToInt32(reader["invType"].ToString());
786 item.CreatorId = reader["creatorID"].ToString();
787 item.BasePermissions = Convert.ToUInt32(reader["inventoryBasePermissions"]);
788 item.EveryOnePermissions = Convert.ToUInt32(reader["inventoryEveryOnePermissions"]);
789 item.GroupPermissions = Convert.ToUInt32(reader["inventoryGroupPermissions"]);
790 item.SalePrice = Convert.ToInt32(reader["salePrice"]);
791 item.SaleType = Convert.ToByte(reader["saleType"]);
792 item.CreationDate = Convert.ToInt32(reader["creationDate"]);
793 item.GroupID = DBGuid.FromDB(reader["groupID"]);
794 item.GroupOwned = Convert.ToBoolean(reader["groupOwned"]);
795 item.Flags = Convert.ToUInt32(reader["flags"]);
796
797 return item;
798 }
799 catch (NpgsqlException e)
800 {
801 m_log.Error("[INVENTORY DB]: Error reading inventory item :" + e.Message);
802 }
803
804 return null;
805 }
806
807 /// <summary>
808 /// Delete a folder in inventory databasae
809 /// </summary>
810 /// <param name="folderID">the folder UUID</param>
811 /// <param name="connection">connection to database</param>
812 private void DeleteOneFolder(UUID folderID, NpgsqlConnection connection)
813 {
814 try
815 {
816 using (NpgsqlCommand command = new NpgsqlCommand(@"DELETE FROM inventoryfolders WHERE ""folderID""=:folderID and type=-1", connection))
817 {
818 command.Parameters.Add(database.CreateParameter("folderID", folderID));
819
820 command.ExecuteNonQuery();
821 }
822 }
823 catch (NpgsqlException e)
824 {
825 m_log.Error("[INVENTORY DB]: Error deleting folder :" + e.Message);
826 }
827 }
828
829 #endregion
830 }
831}
diff --git a/OpenSim/Data/PGSQL/PGSQLManager.cs b/OpenSim/Data/PGSQL/PGSQLManager.cs
new file mode 100644
index 0000000..97f40b2
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLManager.cs
@@ -0,0 +1,350 @@
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.Data;
31using System.IO;
32using System.Reflection;
33using OpenSim.Framework;
34using log4net;
35using OpenMetaverse;
36using Npgsql;
37using NpgsqlTypes;
38
39namespace OpenSim.Data.PGSQL
40{
41 /// <summary>
42 /// A management class for the MS SQL Storage Engine
43 /// </summary>
44 public class PGSQLManager
45 {
46// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 /// <summary>
49 /// Connection string for ADO.net
50 /// </summary>
51 private readonly string connectionString;
52
53 /// <summary>
54 /// Initialize the manager and set the connectionstring
55 /// </summary>
56 /// <param name="connection"></param>
57 public PGSQLManager(string connection)
58 {
59 connectionString = connection;
60 InitializeMonoSecurity();
61 }
62
63 public void InitializeMonoSecurity()
64 {
65 if (!Util.IsPlatformMono)
66 {
67 if (AppDomain.CurrentDomain.GetData("MonoSecurityPostgresAdded") == null)
68 {
69 AppDomain.CurrentDomain.SetData("MonoSecurityPostgresAdded", "true");
70
71 AppDomain currentDomain = AppDomain.CurrentDomain;
72 currentDomain.AssemblyResolve += new ResolveEventHandler(ResolveEventHandlerMonoSec);
73 }
74 }
75 }
76
77 private System.Reflection.Assembly ResolveEventHandlerMonoSec(object sender, ResolveEventArgs args)
78 {
79 Assembly MyAssembly = null;
80
81 if (args.Name.Substring(0, args.Name.IndexOf(",")) == "Mono.Security")
82 {
83 MyAssembly = Assembly.LoadFrom("lib/NET/Mono.Security.dll");
84 }
85
86 //Return the loaded assembly.
87 return MyAssembly;
88 }
89
90 /// <summary>
91 /// Type conversion to a SQLDbType functions
92 /// </summary>
93 /// <param name="type"></param>
94 /// <returns></returns>
95 internal NpgsqlDbType DbtypeFromType(Type type)
96 {
97 if (type == typeof(string))
98 {
99 return NpgsqlDbType.Varchar;
100 }
101 if (type == typeof(double))
102 {
103 return NpgsqlDbType.Double;
104 }
105 if (type == typeof(Single))
106 {
107 return NpgsqlDbType.Double;
108 }
109 if (type == typeof(int))
110 {
111 return NpgsqlDbType.Integer;
112 }
113 if (type == typeof(bool))
114 {
115 return NpgsqlDbType.Boolean;
116 }
117 if (type == typeof(UUID))
118 {
119 return NpgsqlDbType.Uuid;
120 }
121 if (type == typeof(byte))
122 {
123 return NpgsqlDbType.Smallint;
124 }
125 if (type == typeof(sbyte))
126 {
127 return NpgsqlDbType.Integer;
128 }
129 if (type == typeof(Byte[]))
130 {
131 return NpgsqlDbType.Bytea;
132 }
133 if (type == typeof(uint) || type == typeof(ushort))
134 {
135 return NpgsqlDbType.Integer;
136 }
137 if (type == typeof(ulong))
138 {
139 return NpgsqlDbType.Bigint;
140 }
141 if (type == typeof(DateTime))
142 {
143 return NpgsqlDbType.Timestamp;
144 }
145
146 return NpgsqlDbType.Varchar;
147 }
148
149 internal NpgsqlDbType DbtypeFromString(Type type, string PGFieldType)
150 {
151 if (PGFieldType == "")
152 {
153 return DbtypeFromType(type);
154 }
155
156 if (PGFieldType == "character varying")
157 {
158 return NpgsqlDbType.Varchar;
159 }
160 if (PGFieldType == "double precision")
161 {
162 return NpgsqlDbType.Double;
163 }
164 if (PGFieldType == "integer")
165 {
166 return NpgsqlDbType.Integer;
167 }
168 if (PGFieldType == "smallint")
169 {
170 return NpgsqlDbType.Smallint;
171 }
172 if (PGFieldType == "boolean")
173 {
174 return NpgsqlDbType.Boolean;
175 }
176 if (PGFieldType == "uuid")
177 {
178 return NpgsqlDbType.Uuid;
179 }
180 if (PGFieldType == "bytea")
181 {
182 return NpgsqlDbType.Bytea;
183 }
184
185 return DbtypeFromType(type);
186 }
187
188 /// <summary>
189 /// Creates value for parameter.
190 /// </summary>
191 /// <param name="value">The value.</param>
192 /// <returns></returns>
193 private static object CreateParameterValue(object value)
194 {
195 Type valueType = value.GetType();
196
197 if (valueType == typeof(UUID)) //TODO check if this works
198 {
199 return ((UUID) value).Guid;
200 }
201 if (valueType == typeof(UUID))
202 {
203 return ((UUID)value).Guid;
204 }
205 if (valueType == typeof(bool))
206 {
207 return (bool)value;
208 }
209 if (valueType == typeof(Byte[]))
210 {
211 return value;
212 }
213 if (valueType == typeof(int))
214 {
215 return value;
216 }
217 return value;
218 }
219
220 /// <summary>
221 /// Create value for parameter based on PGSQL Schema
222 /// </summary>
223 /// <param name="value"></param>
224 /// <param name="PGFieldType"></param>
225 /// <returns></returns>
226 internal static object CreateParameterValue(object value, string PGFieldType)
227 {
228 if (PGFieldType == "uuid")
229 {
230 UUID uidout;
231 UUID.TryParse(value.ToString(), out uidout);
232 return uidout;
233 }
234 if (PGFieldType == "integer")
235 {
236 int intout;
237 int.TryParse(value.ToString(), out intout);
238 return intout;
239 }
240 if (PGFieldType == "boolean")
241 {
242 return (value.ToString() == "true");
243 }
244 if (PGFieldType == "timestamp with time zone")
245 {
246 return (DateTime)value;
247 }
248 if (PGFieldType == "timestamp without time zone")
249 {
250 return (DateTime)value;
251 }
252 return CreateParameterValue(value);
253 }
254
255 /// <summary>
256 /// Create a parameter for a command
257 /// </summary>
258 /// <param name="parameterName">Name of the parameter.</param>
259 /// <param name="parameterObject">parameter object.</param>
260 /// <returns></returns>
261 internal NpgsqlParameter CreateParameter(string parameterName, object parameterObject)
262 {
263 return CreateParameter(parameterName, parameterObject, false);
264 }
265
266 /// <summary>
267 /// Creates the parameter for a command.
268 /// </summary>
269 /// <param name="parameterName">Name of the parameter.</param>
270 /// <param name="parameterObject">parameter object.</param>
271 /// <param name="parameterOut">if set to <c>true</c> parameter is a output parameter</param>
272 /// <returns></returns>
273 internal NpgsqlParameter CreateParameter(string parameterName, object parameterObject, bool parameterOut)
274 {
275 //Tweak so we dont always have to add : sign
276 if (parameterName.StartsWith(":")) parameterName = parameterName.Replace(":","");
277
278 //HACK if object is null, it is turned into a string, there are no nullable type till now
279 if (parameterObject == null) parameterObject = "";
280
281 NpgsqlParameter parameter = new NpgsqlParameter(parameterName, DbtypeFromType(parameterObject.GetType()));
282
283 if (parameterOut)
284 {
285 parameter.Direction = ParameterDirection.Output;
286 }
287 else
288 {
289 parameter.Direction = ParameterDirection.Input;
290 parameter.Value = CreateParameterValue(parameterObject);
291 }
292
293 return parameter;
294 }
295
296 /// <summary>
297 /// Create a parameter with PGSQL schema type
298 /// </summary>
299 /// <param name="parameterName"></param>
300 /// <param name="parameterObject"></param>
301 /// <param name="PGFieldType"></param>
302 /// <returns></returns>
303 internal NpgsqlParameter CreateParameter(string parameterName, object parameterObject, string PGFieldType)
304 {
305 //Tweak so we dont always have to add : sign
306 if (parameterName.StartsWith(":")) parameterName = parameterName.Replace(":", "");
307
308 //HACK if object is null, it is turned into a string, there are no nullable type till now
309 if (parameterObject == null) parameterObject = "";
310
311 NpgsqlParameter parameter = new NpgsqlParameter(parameterName, DbtypeFromString(parameterObject.GetType(), PGFieldType));
312
313 parameter.Direction = ParameterDirection.Input;
314 parameter.Value = CreateParameterValue(parameterObject, PGFieldType);
315
316 return parameter;
317 }
318
319 /// <summary>
320 /// Checks if we need to do some migrations to the database
321 /// </summary>
322 /// <param name="migrationStore">migrationStore.</param>
323 public void CheckMigration(string migrationStore)
324 {
325 using (NpgsqlConnection connection = new NpgsqlConnection(connectionString))
326 {
327 connection.Open();
328 Assembly assem = GetType().Assembly;
329 PGSQLMigration migration = new PGSQLMigration(connection, assem, migrationStore);
330
331 migration.Update();
332 }
333 }
334
335 /// <summary>
336 /// Returns the version of this DB provider
337 /// </summary>
338 /// <returns>A string containing the DB provider</returns>
339 public string getVersion()
340 {
341 Module module = GetType().Module;
342 // string dllName = module.Assembly.ManifestModule.Name;
343 Version dllVersion = module.Assembly.GetName().Version;
344
345 return
346 string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build,
347 dllVersion.Revision);
348 }
349 }
350}
diff --git a/OpenSim/Data/PGSQL/PGSQLMigration.cs b/OpenSim/Data/PGSQL/PGSQLMigration.cs
new file mode 100644
index 0000000..709fde0
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLMigration.cs
@@ -0,0 +1,102 @@
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 Npgsql;
29using System;
30using System.Data;
31using System.Data.Common;
32using System.Reflection;
33
34namespace OpenSim.Data.PGSQL
35{
36 public class PGSQLMigration : Migration
37 {
38 public PGSQLMigration(NpgsqlConnection conn, Assembly assem, string type)
39 : base(conn, assem, type)
40 {
41 }
42
43 public PGSQLMigration(NpgsqlConnection conn, Assembly assem, string subtype, string type)
44 : base(conn, assem, subtype, type)
45 {
46 }
47
48 protected override int FindVersion(DbConnection conn, string type)
49 {
50 int version = 0;
51 NpgsqlConnection lcConn = (NpgsqlConnection)conn;
52
53 using (NpgsqlCommand cmd = lcConn.CreateCommand())
54 {
55 try
56 {
57 cmd.CommandText = "select version from migrations where name = '" + type + "' " +
58 " order by version desc limit 1"; //Must be
59 using (NpgsqlDataReader reader = cmd.ExecuteReader())
60 {
61 if (reader.Read())
62 {
63 version = Convert.ToInt32(reader["version"]);
64 }
65 reader.Close();
66 }
67 }
68 catch
69 {
70 // Return -1 to indicate table does not exist
71 return -1;
72 }
73 }
74 return version;
75 }
76
77 protected override void ExecuteScript(DbConnection conn, string[] script)
78 {
79 if (!(conn is NpgsqlConnection))
80 {
81 base.ExecuteScript(conn, script);
82 return;
83 }
84
85 foreach (string sql in script)
86 {
87 try
88 {
89 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, (NpgsqlConnection)conn))
90 {
91 cmd.ExecuteNonQuery();
92 }
93 }
94 catch (Exception)
95 {
96 throw new Exception(sql);
97
98 }
99 }
100 }
101 }
102}
diff --git a/OpenSim/Data/PGSQL/PGSQLOfflineIMData.cs b/OpenSim/Data/PGSQL/PGSQLOfflineIMData.cs
new file mode 100644
index 0000000..82e5ed8
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLOfflineIMData.cs
@@ -0,0 +1,56 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using OpenSim.Framework;
33using OpenMetaverse;
34using Npgsql;
35
36namespace OpenSim.Data.PGSQL
37{
38 public class PGSQLOfflineIMData : PGSQLGenericTableHandler<OfflineIMData>, IOfflineIMData
39 {
40 public PGSQLOfflineIMData(string connectionString, string realm)
41 : base(connectionString, realm, "IM_Store")
42 {
43 }
44
45 public void DeleteOld()
46 {
47 using (NpgsqlCommand cmd = new NpgsqlCommand())
48 {
49 cmd.CommandText = String.Format("delete from {0} where \"TMStamp\" < CURRENT_DATE - INTERVAL '2 week'", m_Realm);
50
51 ExecuteNonQuery(cmd);
52 }
53
54 }
55 }
56}
diff --git a/OpenSim/Data/PGSQL/PGSQLPresenceData.cs b/OpenSim/Data/PGSQL/PGSQLPresenceData.cs
new file mode 100644
index 0000000..666de07
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLPresenceData.cs
@@ -0,0 +1,115 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Data;
31using System.Reflection;
32using System.Threading;
33using log4net;
34using OpenMetaverse;
35using OpenSim.Framework;
36using Npgsql;
37
38namespace OpenSim.Data.PGSQL
39{
40 /// <summary>
41 /// A PGSQL Interface for the Presence Server
42 /// </summary>
43 public class PGSQLPresenceData : PGSQLGenericTableHandler<PresenceData>,
44 IPresenceData
45 {
46// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 public PGSQLPresenceData(string connectionString, string realm) :
49 base(connectionString, realm, "Presence")
50 {
51 }
52
53 public PresenceData Get(UUID sessionID)
54 {
55 PresenceData[] ret = Get("SessionID", sessionID.ToString());
56
57 if (ret.Length == 0)
58 return null;
59
60 return ret[0];
61 }
62
63 public void LogoutRegionAgents(UUID regionID)
64 {
65 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
66 using (NpgsqlCommand cmd = new NpgsqlCommand())
67 {
68
69 cmd.CommandText = String.Format(@"DELETE FROM {0} WHERE ""RegionID""=:RegionID", m_Realm);
70
71 cmd.Parameters.Add(m_database.CreateParameter("RegionID", regionID));
72 cmd.Connection = conn;
73 conn.Open();
74 cmd.ExecuteNonQuery();
75 }
76 }
77
78 public bool ReportAgent(UUID sessionID, UUID regionID)
79 {
80 PresenceData[] pd = Get("SessionID", sessionID.ToString());
81 if (pd.Length == 0)
82 return false;
83
84 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
85 using (NpgsqlCommand cmd = new NpgsqlCommand())
86 {
87
88 cmd.CommandText = String.Format(@"UPDATE {0} SET
89 ""RegionID"" = :RegionID
90 WHERE ""SessionID"" = :SessionID", m_Realm);
91
92 cmd.Parameters.Add(m_database.CreateParameter("SessionID", sessionID));
93 cmd.Parameters.Add(m_database.CreateParameter("RegionID", regionID));
94 cmd.Connection = conn;
95 conn.Open();
96 if (cmd.ExecuteNonQuery() == 0)
97 return false;
98 }
99 return true;
100 }
101
102 public bool VerifyAgent(UUID agentId, UUID secureSessionID)
103 {
104 PresenceData[] ret = Get("SecureSessionID", secureSessionID.ToString());
105
106 if (ret.Length == 0)
107 return false;
108
109 if(ret[0].UserID != agentId.ToString())
110 return false;
111
112 return true;
113 }
114 }
115}
diff --git a/OpenSim/Data/PGSQL/PGSQLRegionData.cs b/OpenSim/Data/PGSQL/PGSQLRegionData.cs
new file mode 100644
index 0000000..b3076f0
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLRegionData.cs
@@ -0,0 +1,392 @@
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.Data;
31using System.Drawing;
32using System.IO;
33using System.Reflection;
34using log4net;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using RegionFlags = OpenSim.Framework.RegionFlags;
40using Npgsql;
41
42namespace OpenSim.Data.PGSQL
43{
44 /// <summary>
45 /// A PGSQL Interface for the Region Server.
46 /// </summary>
47 public class PGSQLRegionData : IRegionData
48 {
49 private string m_Realm;
50 private List<string> m_ColumnNames = null;
51 private string m_ConnectionString;
52 private PGSQLManager m_database;
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
55 protected Dictionary<string, string> m_FieldTypes = new Dictionary<string, string>();
56
57 protected virtual Assembly Assembly
58 {
59 get { return GetType().Assembly; }
60 }
61
62 public PGSQLRegionData(string connectionString, string realm)
63 {
64 m_Realm = realm;
65 m_ConnectionString = connectionString;
66 m_database = new PGSQLManager(connectionString);
67
68 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
69 {
70 conn.Open();
71 Migration m = new Migration(conn, GetType().Assembly, "GridStore");
72 m.Update();
73 }
74 LoadFieldTypes();
75 }
76
77 private void LoadFieldTypes()
78 {
79 m_FieldTypes = new Dictionary<string, string>();
80
81 string query = string.Format(@"select column_name,data_type
82 from INFORMATION_SCHEMA.COLUMNS
83 where table_name = lower('{0}');
84
85 ", m_Realm);
86 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
87 using (NpgsqlCommand cmd = new NpgsqlCommand(query, conn))
88 {
89 conn.Open();
90 using (NpgsqlDataReader rdr = cmd.ExecuteReader())
91 {
92 while (rdr.Read())
93 {
94 // query produces 0 to many rows of single column, so always add the first item in each row
95 m_FieldTypes.Add((string)rdr[0], (string)rdr[1]);
96 }
97 }
98 }
99 }
100
101 public List<RegionData> Get(string regionName, UUID scopeID)
102 {
103 string sql = "select * from "+m_Realm+" where lower(\"regionName\") like lower(:regionName) ";
104 if (scopeID != UUID.Zero)
105 sql += " and \"ScopeID\" = :scopeID";
106 sql += " order by lower(\"regionName\")";
107
108 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
109 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
110 {
111 cmd.Parameters.Add(m_database.CreateParameter("regionName", regionName));
112 if (scopeID != UUID.Zero)
113 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
114 conn.Open();
115 return RunCommand(cmd);
116 }
117 }
118
119 public RegionData Get(int posX, int posY, UUID scopeID)
120 {
121 string sql = "select * from "+m_Realm+" where \"locX\" = :posX and \"locY\" = :posY";
122 if (scopeID != UUID.Zero)
123 sql += " and \"ScopeID\" = :scopeID";
124
125 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
126 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
127 {
128 cmd.Parameters.Add(m_database.CreateParameter("posX", posX));
129 cmd.Parameters.Add(m_database.CreateParameter("posY", posY));
130 if (scopeID != UUID.Zero)
131 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
132 conn.Open();
133 List<RegionData> ret = RunCommand(cmd);
134 if (ret.Count == 0)
135 return null;
136
137 return ret[0];
138 }
139 }
140
141 public RegionData Get(UUID regionID, UUID scopeID)
142 {
143 string sql = "select * from "+m_Realm+" where uuid = :regionID";
144 if (scopeID != UUID.Zero)
145 sql += " and \"ScopeID\" = :scopeID";
146 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
147 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
148 {
149 cmd.Parameters.Add(m_database.CreateParameter("regionID", regionID));
150 if (scopeID != UUID.Zero)
151 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
152 conn.Open();
153 List<RegionData> ret = RunCommand(cmd);
154 if (ret.Count == 0)
155 return null;
156
157 return ret[0];
158 }
159 }
160
161 public List<RegionData> Get(int startX, int startY, int endX, int endY, UUID scopeID)
162 {
163 string sql = "select * from "+m_Realm+" where \"locX\" between :startX and :endX and \"locY\" between :startY and :endY";
164 if (scopeID != UUID.Zero)
165 sql += " and \"ScopeID\" = :scopeID";
166
167 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
168 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
169 {
170 cmd.Parameters.Add(m_database.CreateParameter("startX", startX));
171 cmd.Parameters.Add(m_database.CreateParameter("startY", startY));
172 cmd.Parameters.Add(m_database.CreateParameter("endX", endX));
173 cmd.Parameters.Add(m_database.CreateParameter("endY", endY));
174 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
175 conn.Open();
176 return RunCommand(cmd);
177 }
178 }
179
180 public List<RegionData> RunCommand(NpgsqlCommand cmd)
181 {
182 List<RegionData> retList = new List<RegionData>();
183
184 NpgsqlDataReader result = cmd.ExecuteReader();
185
186 while (result.Read())
187 {
188 RegionData ret = new RegionData();
189 ret.Data = new Dictionary<string, object>();
190
191 UUID regionID;
192 UUID.TryParse(result["uuid"].ToString(), out regionID);
193 ret.RegionID = regionID;
194 UUID scope;
195 UUID.TryParse(result["ScopeID"].ToString(), out scope);
196 ret.ScopeID = scope;
197 ret.RegionName = result["regionName"].ToString();
198 ret.posX = Convert.ToInt32(result["locX"]);
199 ret.posY = Convert.ToInt32(result["locY"]);
200 ret.sizeX = Convert.ToInt32(result["sizeX"]);
201 ret.sizeY = Convert.ToInt32(result["sizeY"]);
202
203 if (m_ColumnNames == null)
204 {
205 m_ColumnNames = new List<string>();
206
207 DataTable schemaTable = result.GetSchemaTable();
208 foreach (DataRow row in schemaTable.Rows)
209 m_ColumnNames.Add(row["ColumnName"].ToString());
210 }
211
212 foreach (string s in m_ColumnNames)
213 {
214 if (s == "uuid")
215 continue;
216 if (s == "ScopeID")
217 continue;
218 if (s == "regionName")
219 continue;
220 if (s == "locX")
221 continue;
222 if (s == "locY")
223 continue;
224
225 ret.Data[s] = result[s].ToString();
226 }
227
228 retList.Add(ret);
229 }
230 return retList;
231 }
232
233 public bool Store(RegionData data)
234 {
235 if (data.Data.ContainsKey("uuid"))
236 data.Data.Remove("uuid");
237 if (data.Data.ContainsKey("ScopeID"))
238 data.Data.Remove("ScopeID");
239 if (data.Data.ContainsKey("regionName"))
240 data.Data.Remove("regionName");
241 if (data.Data.ContainsKey("posX"))
242 data.Data.Remove("posX");
243 if (data.Data.ContainsKey("posY"))
244 data.Data.Remove("posY");
245 if (data.Data.ContainsKey("sizeX"))
246 data.Data.Remove("sizeX");
247 if (data.Data.ContainsKey("sizeY"))
248 data.Data.Remove("sizeY");
249 if (data.Data.ContainsKey("locX"))
250 data.Data.Remove("locX");
251 if (data.Data.ContainsKey("locY"))
252 data.Data.Remove("locY");
253
254 string[] fields = new List<string>(data.Data.Keys).ToArray();
255
256 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
257 using (NpgsqlCommand cmd = new NpgsqlCommand())
258 {
259
260 string update = "update " + m_Realm + " set \"locX\"=:posX, \"locY\"=:posY, \"sizeX\"=:sizeX, \"sizeY\"=:sizeY ";
261
262 foreach (string field in fields)
263 {
264
265 update += ", ";
266 update += " \"" + field + "\" = :" + field;
267
268 if (m_FieldTypes.ContainsKey(field))
269 cmd.Parameters.Add(m_database.CreateParameter(field, data.Data[field], m_FieldTypes[field]));
270 else
271 cmd.Parameters.Add(m_database.CreateParameter(field, data.Data[field]));
272 }
273
274 update += " where uuid = :regionID";
275
276 if (data.ScopeID != UUID.Zero)
277 update += " and \"ScopeID\" = :scopeID";
278
279 cmd.CommandText = update;
280 cmd.Connection = conn;
281 cmd.Parameters.Add(m_database.CreateParameter("regionID", data.RegionID));
282 cmd.Parameters.Add(m_database.CreateParameter("regionName", data.RegionName));
283 cmd.Parameters.Add(m_database.CreateParameter("scopeID", data.ScopeID));
284 cmd.Parameters.Add(m_database.CreateParameter("posX", data.posX));
285 cmd.Parameters.Add(m_database.CreateParameter("posY", data.posY));
286 cmd.Parameters.Add(m_database.CreateParameter("sizeX", data.sizeX));
287 cmd.Parameters.Add(m_database.CreateParameter("sizeY", data.sizeY));
288 conn.Open();
289 try
290 {
291 if (cmd.ExecuteNonQuery() < 1)
292 {
293 string insert = "insert into " + m_Realm + " (uuid, \"ScopeID\", \"locX\", \"locY\", \"sizeX\", \"sizeY\", \"regionName\", \"" +
294 String.Join("\", \"", fields) +
295 "\") values (:regionID, :scopeID, :posX, :posY, :sizeX, :sizeY, :regionName, :" + String.Join(", :", fields) + ")";
296
297 cmd.CommandText = insert;
298
299 try
300 {
301 if (cmd.ExecuteNonQuery() < 1)
302 {
303 return false;
304 }
305 }
306 catch (Exception ex)
307 {
308 m_log.Warn("[PGSQL Grid]: Error inserting into Regions table: " + ex.Message + ", INSERT sql: " + insert);
309 }
310 }
311 }
312 catch (Exception ex)
313 {
314 m_log.Warn("[PGSQL Grid]: Error updating Regions table: " + ex.Message + ", UPDATE sql: " + update);
315 }
316 }
317
318 return true;
319 }
320
321 public bool SetDataItem(UUID regionID, string item, string value)
322 {
323 string sql = "update " + m_Realm +
324 " set \"" + item + "\" = :" + item + " where uuid = :UUID";
325
326 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
327 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
328 {
329 cmd.Parameters.Add(m_database.CreateParameter("" + item, value));
330 cmd.Parameters.Add(m_database.CreateParameter("UUID", regionID));
331 conn.Open();
332 if (cmd.ExecuteNonQuery() > 0)
333 return true;
334 }
335 return false;
336 }
337
338 public bool Delete(UUID regionID)
339 {
340 string sql = "delete from " + m_Realm +
341 " where uuid = :UUID";
342 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
343 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
344 {
345 cmd.Parameters.Add(m_database.CreateParameter("UUID", regionID));
346 conn.Open();
347 if (cmd.ExecuteNonQuery() > 0)
348 return true;
349 }
350 return false;
351 }
352
353 public List<RegionData> GetDefaultRegions(UUID scopeID)
354 {
355 return Get((int)RegionFlags.DefaultRegion, scopeID);
356 }
357
358 public List<RegionData> GetDefaultHypergridRegions(UUID scopeID)
359 {
360 return Get((int)RegionFlags.DefaultHGRegion, scopeID);
361 }
362
363 public List<RegionData> GetFallbackRegions(UUID scopeID, int x, int y)
364 {
365 List<RegionData> regions = Get((int)RegionFlags.FallbackRegion, scopeID);
366 RegionDataDistanceCompare distanceComparer = new RegionDataDistanceCompare(x, y);
367 regions.Sort(distanceComparer);
368
369 return regions;
370 }
371
372 public List<RegionData> GetHyperlinks(UUID scopeID)
373 {
374 return Get((int)RegionFlags.Hyperlink, scopeID);
375 }
376
377 private List<RegionData> Get(int regionFlags, UUID scopeID)
378 {
379 string sql = "SELECT * FROM " + m_Realm + " WHERE (\"flags\" & " + regionFlags.ToString() + ") <> 0";
380 if (scopeID != UUID.Zero)
381 sql += " AND \"ScopeID\" = :scopeID";
382
383 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
384 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
385 {
386 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
387 conn.Open();
388 return RunCommand(cmd);
389 }
390 }
391 }
392}
diff --git a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
new file mode 100644
index 0000000..3243635
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs
@@ -0,0 +1,2253 @@
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.Data;
31using System.Drawing;
32using System.IO;
33using System.Reflection;
34using log4net;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using Npgsql;
40
41namespace OpenSim.Data.PGSQL
42{
43 /// <summary>
44 /// A PGSQL Interface for the Region Server.
45 /// </summary>
46 public class PGSQLSimulationData : ISimulationDataStore
47 {
48 private const string _migrationStore = "RegionStore";
49
50 // private static FileSystemDataStore Instance = new FileSystemDataStore();
51 private static readonly ILog _Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 /// <summary>
54 /// The database manager
55 /// </summary>
56 private PGSQLManager _Database;
57 private string m_connectionString;
58 protected virtual Assembly Assembly
59 {
60 get { return GetType().Assembly; }
61 }
62
63 public PGSQLSimulationData()
64 {
65 }
66
67 public PGSQLSimulationData(string connectionString)
68 {
69 Initialise(connectionString);
70 }
71
72 /// <summary>
73 /// Initialises the region datastore
74 /// </summary>
75 /// <param name="connectionString">The connection string.</param>
76 public void Initialise(string connectionString)
77 {
78 m_connectionString = connectionString;
79 _Database = new PGSQLManager(connectionString);
80
81 using (NpgsqlConnection conn = new NpgsqlConnection(connectionString))
82 {
83 conn.Open();
84 //New Migration settings
85 Migration m = new Migration(conn, Assembly, "RegionStore");
86 m.Update();
87 }
88 }
89
90 /// <summary>
91 /// Dispose the database
92 /// </summary>
93 public void Dispose() { }
94
95 #region SceneObjectGroup region for loading and Store of the scene.
96
97 /// <summary>
98 /// Loads the objects present in the region.
99 /// </summary>
100 /// <param name="regionUUID">The region UUID.</param>
101 /// <returns></returns>
102 public List<SceneObjectGroup> LoadObjects(UUID regionUUID)
103 {
104 UUID lastGroupID = UUID.Zero;
105
106 Dictionary<UUID, SceneObjectPart> prims = new Dictionary<UUID, SceneObjectPart>();
107 Dictionary<UUID, SceneObjectGroup> objects = new Dictionary<UUID, SceneObjectGroup>();
108 SceneObjectGroup grp = null;
109
110 string sql = @"SELECT *,
111 CASE WHEN prims.""UUID"" = prims.""SceneGroupID"" THEN 0 ELSE 1 END as sort
112 FROM prims
113 LEFT JOIN primshapes ON prims.""UUID"" = primshapes.""UUID""
114 WHERE ""RegionUUID"" = :RegionUUID
115 ORDER BY ""SceneGroupID"" asc, sort asc, ""LinkNumber"" asc";
116
117 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
118 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
119 {
120 command.Parameters.Add(_Database.CreateParameter("regionUUID", regionUUID));
121 conn.Open();
122 using (NpgsqlDataReader reader = command.ExecuteReader())
123 {
124 while (reader.Read())
125 {
126 SceneObjectPart sceneObjectPart = BuildPrim(reader);
127 if (reader["Shape"] is DBNull)
128 sceneObjectPart.Shape = PrimitiveBaseShape.Default;
129 else
130 sceneObjectPart.Shape = BuildShape(reader);
131
132 prims[sceneObjectPart.UUID] = sceneObjectPart;
133
134 UUID groupID = new UUID((Guid)reader["SceneGroupID"]);
135
136 if (groupID != lastGroupID) // New SOG
137 {
138 if (grp != null)
139 objects[grp.UUID] = grp;
140
141 lastGroupID = groupID;
142
143 // There sometimes exist OpenSim bugs that 'orphan groups' so that none of the prims are
144 // recorded as the root prim (for which the UUID must equal the persisted group UUID). In
145 // this case, force the UUID to be the same as the group UUID so that at least these can be
146 // deleted (we need to change the UUID so that any other prims in the linkset can also be
147 // deleted).
148 if (sceneObjectPart.UUID != groupID && groupID != UUID.Zero)
149 {
150 _Log.WarnFormat(
151 "[REGION DB]: Found root prim {0} {1} at {2} where group was actually {3}. Forcing UUID to group UUID",
152 sceneObjectPart.Name, sceneObjectPart.UUID, sceneObjectPart.GroupPosition, groupID);
153
154 sceneObjectPart.UUID = groupID;
155 }
156
157 grp = new SceneObjectGroup(sceneObjectPart);
158 }
159 else
160 {
161 // Black magic to preserve link numbers
162 // Why is this needed, fix this in AddPart method.
163 int link = sceneObjectPart.LinkNum;
164
165 grp.AddPart(sceneObjectPart);
166
167 if (link != 0)
168 sceneObjectPart.LinkNum = link;
169 }
170 }
171 }
172 }
173
174 if (grp != null)
175 objects[grp.UUID] = grp;
176
177 // Instead of attempting to LoadItems on every prim,
178 // most of which probably have no items... get a
179 // list from DB of all prims which have items and
180 // LoadItems only on those
181 List<SceneObjectPart> primsWithInventory = new List<SceneObjectPart>();
182 string qry = "select distinct \"primID\" from primitems";
183 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
184 using (NpgsqlCommand command = new NpgsqlCommand(qry, conn))
185 {
186 conn.Open();
187 using (NpgsqlDataReader itemReader = command.ExecuteReader())
188 {
189 while (itemReader.Read())
190 {
191 if (!(itemReader["primID"] is DBNull))
192 {
193 UUID primID = new UUID(itemReader["primID"].ToString());
194 if (prims.ContainsKey(primID))
195 {
196 primsWithInventory.Add(prims[primID]);
197 }
198 }
199 }
200 }
201 }
202
203 LoadItems(primsWithInventory);
204
205 _Log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count);
206
207 return new List<SceneObjectGroup>(objects.Values);
208 }
209
210 /// <summary>
211 /// Load in the prim's persisted inventory.
212 /// </summary>
213 /// <param name="allPrims">all prims with inventory on a region</param>
214 private void LoadItems(List<SceneObjectPart> allPrimsWithInventory)
215 {
216 string sql = @"SELECT * FROM primitems WHERE ""primID"" = :PrimID";
217 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
218 using (NpgsqlCommand command = new NpgsqlCommand(sql, conn))
219 {
220 conn.Open();
221 foreach (SceneObjectPart objectPart in allPrimsWithInventory)
222 {
223 command.Parameters.Clear();
224 command.Parameters.Add(_Database.CreateParameter("PrimID", objectPart.UUID));
225
226 List<TaskInventoryItem> inventory = new List<TaskInventoryItem>();
227
228 using (NpgsqlDataReader reader = command.ExecuteReader())
229 {
230 while (reader.Read())
231 {
232 TaskInventoryItem item = BuildItem(reader);
233
234 item.ParentID = objectPart.UUID; // Values in database are
235 // often wrong
236 inventory.Add(item);
237 }
238 }
239
240 objectPart.Inventory.RestoreInventoryItems(inventory);
241 }
242 }
243 }
244
245 /// <summary>
246 /// Stores all object's details apart from inventory
247 /// </summary>
248 /// <param name="obj"></param>
249 /// <param name="regionUUID"></param>
250 public void StoreObject(SceneObjectGroup obj, UUID regionUUID)
251 {
252 uint flags = obj.RootPart.GetEffectiveObjectFlags();
253 // Eligibility check
254 //
255 if ((flags & (uint)PrimFlags.Temporary) != 0)
256 return;
257 if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0)
258 return;
259
260 //_Log.DebugFormat("[PGSQL]: Adding/Changing SceneObjectGroup: {0} to region: {1}, object has {2} prims.", obj.UUID, regionUUID, obj.Parts.Length);
261
262 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
263 {
264 conn.Open();
265 NpgsqlTransaction transaction = conn.BeginTransaction();
266
267 try
268 {
269 foreach (SceneObjectPart sceneObjectPart in obj.Parts)
270 {
271 //Update prim
272 using (NpgsqlCommand sqlCommand = conn.CreateCommand())
273 {
274 sqlCommand.Transaction = transaction;
275 try
276 {
277 StoreSceneObjectPrim(sceneObjectPart, sqlCommand, obj.UUID, regionUUID);
278 }
279 catch (NpgsqlException sqlEx)
280 {
281 _Log.ErrorFormat("[REGION DB]: Store SceneObjectPrim SQL error: {0} at line {1}", sqlEx.Message, sqlEx.Line);
282 throw;
283 }
284 }
285
286 //Update primshapes
287 using (NpgsqlCommand sqlCommand = conn.CreateCommand())
288 {
289 sqlCommand.Transaction = transaction;
290 try
291 {
292 StoreSceneObjectPrimShapes(sceneObjectPart, sqlCommand, obj.UUID, regionUUID);
293 }
294 catch (NpgsqlException sqlEx)
295 {
296 _Log.ErrorFormat("[REGION DB]: Store SceneObjectPrimShapes SQL error: {0} at line {1}", sqlEx.Message, sqlEx.Line);
297 throw;
298 }
299 }
300 }
301
302 transaction.Commit();
303 }
304 catch (Exception ex)
305 {
306 _Log.ErrorFormat("[REGION DB]: Store SceneObjectGroup error: {0}, Rolling back...", ex.Message);
307 try
308 {
309 transaction.Rollback();
310 }
311 catch (Exception ex2)
312 {
313 //Show error
314 _Log.InfoFormat("[REGION DB]: Rollback of SceneObjectGroup store transaction failed with error: {0}", ex2.Message);
315
316 }
317 }
318 }
319 }
320
321 /// <summary>
322 /// Stores the prim of the sceneobjectpart.
323 /// </summary>
324 /// <param name="sceneObjectPart">The sceneobjectpart or prim.</param>
325 /// <param name="sqlCommand">The SQL command with the transaction.</param>
326 /// <param name="sceneGroupID">The scenegroup UUID.</param>
327 /// <param name="regionUUID">The region UUID.</param>
328 private void StoreSceneObjectPrim(SceneObjectPart sceneObjectPart, NpgsqlCommand sqlCommand, UUID sceneGroupID, UUID regionUUID)
329 {
330 //Big query to update or insert a new prim.
331
332 string queryPrims = @"
333 UPDATE prims SET
334 ""CreationDate"" = :CreationDate, ""Name"" = :Name, ""Text"" = :Text, ""Description"" = :Description, ""SitName"" = :SitName,
335 ""TouchName"" = :TouchName, ""ObjectFlags"" = :ObjectFlags, ""OwnerMask"" = :OwnerMask, ""NextOwnerMask"" = :NextOwnerMask, ""GroupMask"" = :GroupMask,
336 ""EveryoneMask"" = :EveryoneMask, ""BaseMask"" = :BaseMask, ""PositionX"" = :PositionX, ""PositionY"" = :PositionY, ""PositionZ"" = :PositionZ,
337 ""GroupPositionX"" = :GroupPositionX, ""GroupPositionY"" = :GroupPositionY, ""GroupPositionZ"" = :GroupPositionZ, ""VelocityX"" = :VelocityX,
338 ""VelocityY"" = :VelocityY, ""VelocityZ"" = :VelocityZ, ""AngularVelocityX"" = :AngularVelocityX, ""AngularVelocityY"" = :AngularVelocityY,
339 ""AngularVelocityZ"" = :AngularVelocityZ, ""AccelerationX"" = :AccelerationX, ""AccelerationY"" = :AccelerationY,
340 ""AccelerationZ"" = :AccelerationZ, ""RotationX"" = :RotationX, ""RotationY"" = :RotationY, ""RotationZ"" = :RotationZ, ""RotationW"" = :RotationW,
341 ""SitTargetOffsetX"" = :SitTargetOffsetX, ""SitTargetOffsetY"" = :SitTargetOffsetY, ""SitTargetOffsetZ"" = :SitTargetOffsetZ,
342 ""SitTargetOrientW"" = :SitTargetOrientW, ""SitTargetOrientX"" = :SitTargetOrientX, ""SitTargetOrientY"" = :SitTargetOrientY,
343 ""SitTargetOrientZ"" = :SitTargetOrientZ, ""RegionUUID"" = :RegionUUID, ""CreatorID"" = :CreatorID, ""OwnerID"" = :OwnerID, ""GroupID"" = :GroupID,
344 ""LastOwnerID"" = :LastOwnerID, ""SceneGroupID"" = :SceneGroupID, ""PayPrice"" = :PayPrice, ""PayButton1"" = :PayButton1, ""PayButton2"" = :PayButton2,
345 ""PayButton3"" = :PayButton3, ""PayButton4"" = :PayButton4, ""LoopedSound"" = :LoopedSound, ""LoopedSoundGain"" = :LoopedSoundGain,
346 ""TextureAnimation"" = :TextureAnimation, ""OmegaX"" = :OmegaX, ""OmegaY"" = :OmegaY, ""OmegaZ"" = :OmegaZ, ""CameraEyeOffsetX"" = :CameraEyeOffsetX,
347 ""CameraEyeOffsetY"" = :CameraEyeOffsetY, ""CameraEyeOffsetZ"" = :CameraEyeOffsetZ, ""CameraAtOffsetX"" = :CameraAtOffsetX,
348 ""CameraAtOffsetY"" = :CameraAtOffsetY, ""CameraAtOffsetZ"" = :CameraAtOffsetZ, ""ForceMouselook"" = :ForceMouselook,
349 ""ScriptAccessPin"" = :ScriptAccessPin, ""AllowedDrop"" = :AllowedDrop, ""DieAtEdge"" = :DieAtEdge, ""SalePrice"" = :SalePrice,
350 ""SaleType"" = :SaleType, ""ColorR"" = :ColorR, ""ColorG"" = :ColorG, ""ColorB"" = :ColorB, ""ColorA"" = :ColorA, ""ParticleSystem"" = :ParticleSystem,
351 ""ClickAction"" = :ClickAction, ""Material"" = :Material, ""CollisionSound"" = :CollisionSound, ""CollisionSoundVolume"" = :CollisionSoundVolume, ""PassTouches"" = :PassTouches,
352 ""LinkNumber"" = :LinkNumber, ""MediaURL"" = :MediaURL, ""DynAttrs"" = :DynAttrs,
353 ""PhysicsShapeType"" = :PhysicsShapeType, ""Density"" = :Density, ""GravityModifier"" = :GravityModifier, ""Friction"" = :Friction, ""Restitution"" = :Restitution
354 WHERE ""UUID"" = :UUID ;
355
356 INSERT INTO
357 prims (
358 ""UUID"", ""CreationDate"", ""Name"", ""Text"", ""Description"", ""SitName"", ""TouchName"", ""ObjectFlags"", ""OwnerMask"", ""NextOwnerMask"", ""GroupMask"",
359 ""EveryoneMask"", ""BaseMask"", ""PositionX"", ""PositionY"", ""PositionZ"", ""GroupPositionX"", ""GroupPositionY"", ""GroupPositionZ"", ""VelocityX"",
360 ""VelocityY"", ""VelocityZ"", ""AngularVelocityX"", ""AngularVelocityY"", ""AngularVelocityZ"", ""AccelerationX"", ""AccelerationY"", ""AccelerationZ"",
361 ""RotationX"", ""RotationY"", ""RotationZ"", ""RotationW"", ""SitTargetOffsetX"", ""SitTargetOffsetY"", ""SitTargetOffsetZ"", ""SitTargetOrientW"",
362 ""SitTargetOrientX"", ""SitTargetOrientY"", ""SitTargetOrientZ"", ""RegionUUID"", ""CreatorID"", ""OwnerID"", ""GroupID"", ""LastOwnerID"", ""SceneGroupID"",
363 ""PayPrice"", ""PayButton1"", ""PayButton2"", ""PayButton3"", ""PayButton4"", ""LoopedSound"", ""LoopedSoundGain"", ""TextureAnimation"", ""OmegaX"",
364 ""OmegaY"", ""OmegaZ"", ""CameraEyeOffsetX"", ""CameraEyeOffsetY"", ""CameraEyeOffsetZ"", ""CameraAtOffsetX"", ""CameraAtOffsetY"", ""CameraAtOffsetZ"",
365 ""ForceMouselook"", ""ScriptAccessPin"", ""AllowedDrop"", ""DieAtEdge"", ""SalePrice"", ""SaleType"", ""ColorR"", ""ColorG"", ""ColorB"", ""ColorA"",
366 ""ParticleSystem"", ""ClickAction"", ""Material"", ""CollisionSound"", ""CollisionSoundVolume"", ""PassTouches"", ""LinkNumber"", ""MediaURL"", ""DynAttrs"",
367 ""PhysicsShapeType"", ""Density"", ""GravityModifier"", ""Friction"", ""Restitution""
368 ) Select
369 :UUID, :CreationDate, :Name, :Text, :Description, :SitName, :TouchName, :ObjectFlags, :OwnerMask, :NextOwnerMask, :GroupMask,
370 :EveryoneMask, :BaseMask, :PositionX, :PositionY, :PositionZ, :GroupPositionX, :GroupPositionY, :GroupPositionZ, :VelocityX,
371 :VelocityY, :VelocityZ, :AngularVelocityX, :AngularVelocityY, :AngularVelocityZ, :AccelerationX, :AccelerationY, :AccelerationZ,
372 :RotationX, :RotationY, :RotationZ, :RotationW, :SitTargetOffsetX, :SitTargetOffsetY, :SitTargetOffsetZ, :SitTargetOrientW,
373 :SitTargetOrientX, :SitTargetOrientY, :SitTargetOrientZ, :RegionUUID, :CreatorID, :OwnerID, :GroupID, :LastOwnerID, :SceneGroupID,
374 :PayPrice, :PayButton1, :PayButton2, :PayButton3, :PayButton4, :LoopedSound, :LoopedSoundGain, :TextureAnimation, :OmegaX,
375 :OmegaY, :OmegaZ, :CameraEyeOffsetX, :CameraEyeOffsetY, :CameraEyeOffsetZ, :CameraAtOffsetX, :CameraAtOffsetY, :CameraAtOffsetZ,
376 :ForceMouselook, :ScriptAccessPin, :AllowedDrop, :DieAtEdge, :SalePrice, :SaleType, :ColorR, :ColorG, :ColorB, :ColorA,
377 :ParticleSystem, :ClickAction, :Material, :CollisionSound, :CollisionSoundVolume, :PassTouches, :LinkNumber, :MediaURL, :DynAttrs,
378 :PhysicsShapeType, :Density, :GravityModifier, :Friction, :Restitution
379 where not EXISTS (SELECT ""UUID"" FROM prims WHERE ""UUID"" = :UUID);
380 ";
381
382 //Set commandtext.
383 sqlCommand.CommandText = queryPrims;
384 //Add parameters
385 sqlCommand.Parameters.AddRange(CreatePrimParameters(sceneObjectPart, sceneGroupID, regionUUID));
386
387 //Execute the query. If it fails then error is trapped in calling function
388 sqlCommand.ExecuteNonQuery();
389 }
390
391 /// <summary>
392 /// Stores the scene object prim shapes.
393 /// </summary>
394 /// <param name="sceneObjectPart">The sceneobjectpart containing prim shape.</param>
395 /// <param name="sqlCommand">The SQL command with the transaction.</param>
396 /// <param name="sceneGroupID">The scenegroup UUID.</param>
397 /// <param name="regionUUID">The region UUID.</param>
398 private void StoreSceneObjectPrimShapes(SceneObjectPart sceneObjectPart, NpgsqlCommand sqlCommand, UUID sceneGroupID, UUID regionUUID)
399 {
400 //Big query to or insert or update primshapes
401
402 string queryPrimShapes = @"
403 UPDATE primshapes SET
404 ""Shape"" = :Shape, ""ScaleX"" = :ScaleX, ""ScaleY"" = :ScaleY, ""ScaleZ"" = :ScaleZ, ""PCode"" = :PCode, ""PathBegin"" = :PathBegin,
405 ""PathEnd"" = :PathEnd, ""PathScaleX"" = :PathScaleX, ""PathScaleY"" = :PathScaleY, ""PathShearX"" = :PathShearX, ""PathShearY"" = :PathShearY,
406 ""PathSkew"" = :PathSkew, ""PathCurve"" = :PathCurve, ""PathRadiusOffset"" = :PathRadiusOffset, ""PathRevolutions"" = :PathRevolutions,
407 ""PathTaperX"" = :PathTaperX, ""PathTaperY"" = :PathTaperY, ""PathTwist"" = :PathTwist, ""PathTwistBegin"" = :PathTwistBegin,
408 ""ProfileBegin"" = :ProfileBegin, ""ProfileEnd"" = :ProfileEnd, ""ProfileCurve"" = :ProfileCurve, ""ProfileHollow"" = :ProfileHollow,
409 ""Texture"" = :Texture, ""ExtraParams"" = :ExtraParams, ""State"" = :State, ""Media"" = :Media
410 WHERE ""UUID"" = :UUID ;
411
412 INSERT INTO
413 primshapes (
414 ""UUID"", ""Shape"", ""ScaleX"", ""ScaleY"", ""ScaleZ"", ""PCode"", ""PathBegin"", ""PathEnd"", ""PathScaleX"", ""PathScaleY"", ""PathShearX"", ""PathShearY"",
415 ""PathSkew"", ""PathCurve"", ""PathRadiusOffset"", ""PathRevolutions"", ""PathTaperX"", ""PathTaperY"", ""PathTwist"", ""PathTwistBegin"", ""ProfileBegin"",
416 ""ProfileEnd"", ""ProfileCurve"", ""ProfileHollow"", ""Texture"", ""ExtraParams"", ""State"", ""Media""
417 )
418 Select
419 :UUID, :Shape, :ScaleX, :ScaleY, :ScaleZ, :PCode, :PathBegin, :PathEnd, :PathScaleX, :PathScaleY, :PathShearX, :PathShearY,
420 :PathSkew, :PathCurve, :PathRadiusOffset, :PathRevolutions, :PathTaperX, :PathTaperY, :PathTwist, :PathTwistBegin, :ProfileBegin,
421 :ProfileEnd, :ProfileCurve, :ProfileHollow, :Texture, :ExtraParams, :State, :Media
422 where not EXISTS (SELECT ""UUID"" FROM primshapes WHERE ""UUID"" = :UUID);
423 ";
424
425 //Set commandtext.
426 sqlCommand.CommandText = queryPrimShapes;
427
428 //Add parameters
429 sqlCommand.Parameters.AddRange(CreatePrimShapeParameters(sceneObjectPart, sceneGroupID, regionUUID));
430
431 //Execute the query. If it fails then error is trapped in calling function
432 sqlCommand.ExecuteNonQuery();
433
434 }
435
436 /// <summary>
437 /// Removes a object from the database.
438 /// Meaning removing it from tables Prims, PrimShapes and PrimItems
439 /// </summary>
440 /// <param name="objectID">id of scenegroup</param>
441 /// <param name="regionUUID">regionUUID (is this used anyway</param>
442 public void RemoveObject(UUID objectID, UUID regionUUID)
443 {
444 //_Log.InfoFormat("[PGSQL]: Removing obj: {0} from region: {1}", objectID, regionUUID);
445
446 //Remove from prims and primsitem table
447 string sqlPrims = @"DELETE FROM PRIMS WHERE ""SceneGroupID"" = :objectID";
448 string sqlPrimItems = @"DELETE FROM PRIMITEMS WHERE ""primID"" in (SELECT ""UUID"" FROM PRIMS WHERE ""SceneGroupID"" = :objectID)";
449 string sqlPrimShapes = @"DELETE FROM PRIMSHAPES WHERE ""UUID"" in (SELECT ""UUID"" FROM PRIMS WHERE ""SceneGroupID"" = :objectID)";
450
451 lock (_Database)
452 {
453 //Using the non transaction mode.
454 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
455 using (NpgsqlCommand cmd = new NpgsqlCommand())
456 {
457 cmd.Connection = conn;
458 cmd.CommandText = sqlPrimShapes;
459 conn.Open();
460 cmd.Parameters.Add(_Database.CreateParameter("objectID", objectID));
461 cmd.ExecuteNonQuery();
462
463 cmd.CommandText = sqlPrimItems;
464 cmd.ExecuteNonQuery();
465
466 cmd.CommandText = sqlPrims;
467 cmd.ExecuteNonQuery();
468 }
469 }
470 }
471
472 /// <summary>
473 /// Store the inventory of a prim. Warning deletes everything first and then adds all again.
474 /// </summary>
475 /// <param name="primID"></param>
476 /// <param name="items"></param>
477 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
478 {
479 //_Log.InfoFormat("[REGION DB: Persisting Prim Inventory with prim ID {0}", primID);
480
481 //Statement from PGSQL section!
482 // For now, we're just going to crudely remove all the previous inventory items
483 // no matter whether they have changed or not, and replace them with the current set.
484
485 //Delete everything from PrimID
486 //TODO add index on PrimID in DB, if not already exist
487
488 string sql = @"delete from primitems where ""primID"" = :primID";
489 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
490 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
491 {
492 cmd.Parameters.Add(_Database.CreateParameter("primID", primID));
493 conn.Open();
494 cmd.ExecuteNonQuery();
495 }
496
497 sql =
498 @"INSERT INTO primitems (
499 ""itemID"",""primID"",""assetID"",""parentFolderID"",""invType"",""assetType"",""name"",""description"",""creationDate"",""creatorID"",""ownerID"",""lastOwnerID"",""groupID"",
500 ""nextPermissions"",""currentPermissions"",""basePermissions"",""everyonePermissions"",""groupPermissions"",""flags"")
501 VALUES (:itemID,:primID,:assetID,:parentFolderID,:invType,:assetType,:name,:description,:creationDate,:creatorID,:ownerID,
502 :lastOwnerID,:groupID,:nextPermissions,:currentPermissions,:basePermissions,:everyonePermissions,:groupPermissions,:flags)";
503
504 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
505 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
506 {
507 conn.Open();
508 foreach (TaskInventoryItem taskItem in items)
509 {
510 cmd.Parameters.AddRange(CreatePrimInventoryParameters(taskItem));
511 cmd.ExecuteNonQuery();
512 cmd.Parameters.Clear();
513 }
514 }
515 }
516
517 #endregion
518
519 /// <summary>
520 /// Loads the terrain map.
521 /// </summary>
522 /// <param name="regionID">regionID.</param>
523 /// <returns></returns>
524 public double[,] LoadTerrain(UUID regionID)
525 {
526 double[,] terrain = new double[(int)Constants.RegionSize, (int)Constants.RegionSize];
527 terrain.Initialize();
528
529 string sql = @"select ""RegionUUID"", ""Revision"", ""Heightfield"" from terrain
530 where ""RegionUUID"" = :RegionUUID order by ""Revision"" desc limit 1; ";
531
532 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
533 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
534 {
535 // PGSqlParameter param = new PGSqlParameter();
536 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
537 conn.Open();
538 using (NpgsqlDataReader reader = cmd.ExecuteReader())
539 {
540 int rev;
541 if (reader.Read())
542 {
543 MemoryStream str = new MemoryStream((byte[])reader["Heightfield"]);
544 BinaryReader br = new BinaryReader(str);
545 for (int x = 0; x < (int)Constants.RegionSize; x++)
546 {
547 for (int y = 0; y < (int)Constants.RegionSize; y++)
548 {
549 terrain[x, y] = br.ReadDouble();
550 }
551 }
552 rev = (int)reader["Revision"];
553 }
554 else
555 {
556 _Log.Info("[REGION DB]: No terrain found for region");
557 return null;
558 }
559 _Log.Info("[REGION DB]: Loaded terrain revision r" + rev);
560 }
561 }
562
563 return terrain;
564 }
565
566 /// <summary>
567 /// Stores the terrain map to DB.
568 /// </summary>
569 /// <param name="terrain">terrain map data.</param>
570 /// <param name="regionID">regionID.</param>
571 public void StoreTerrain(double[,] terrain, UUID regionID)
572 {
573 int revision = Util.UnixTimeSinceEpoch();
574
575 //Delete old terrain map
576 string sql = @"delete from terrain where ""RegionUUID""=:RegionUUID";
577 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
578 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
579 {
580 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
581 conn.Open();
582 cmd.ExecuteNonQuery();
583 }
584
585 _Log.Info("[REGION DB]: Deleted terrain revision r " + revision);
586
587 sql = @"insert into terrain(""RegionUUID"", ""Revision"", ""Heightfield"") values(:RegionUUID, :Revision, :Heightfield)";
588
589 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
590 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
591 {
592 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionID));
593 cmd.Parameters.Add(_Database.CreateParameter("Revision", revision));
594 cmd.Parameters.Add(_Database.CreateParameter("Heightfield", serializeTerrain(terrain)));
595 conn.Open();
596 cmd.ExecuteNonQuery();
597 }
598
599 _Log.Info("[REGION DB]: Stored terrain revision r " + revision);
600 }
601
602 /// <summary>
603 /// Loads all the land objects of a region.
604 /// </summary>
605 /// <param name="regionUUID">The region UUID.</param>
606 /// <returns></returns>
607 public List<LandData> LoadLandObjects(UUID regionUUID)
608 {
609 List<LandData> LandDataForRegion = new List<LandData>();
610
611 string sql = @"select * from land where ""RegionUUID"" = :RegionUUID";
612
613 //Retrieve all land data from region
614 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
615 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
616 {
617 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", regionUUID));
618 conn.Open();
619 using (NpgsqlDataReader readerLandData = cmd.ExecuteReader())
620 {
621 while (readerLandData.Read())
622 {
623 LandDataForRegion.Add(BuildLandData(readerLandData));
624 }
625 }
626 }
627
628 //Retrieve all accesslist data for all landdata
629 foreach (LandData LandData in LandDataForRegion)
630 {
631 sql = @"select * from landaccesslist where ""LandUUID"" = :LandUUID";
632 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
633 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
634 {
635 cmd.Parameters.Add(_Database.CreateParameter("LandUUID", LandData.GlobalID));
636 conn.Open();
637 using (NpgsqlDataReader readerAccessList = cmd.ExecuteReader())
638 {
639 while (readerAccessList.Read())
640 {
641 LandData.ParcelAccessList.Add(BuildLandAccessData(readerAccessList));
642 }
643 }
644 }
645 }
646
647 //Return data
648 return LandDataForRegion;
649 }
650
651 /// <summary>
652 /// Stores land object with landaccess list.
653 /// </summary>
654 /// <param name="parcel">parcel data.</param>
655 public void StoreLandObject(ILandObject parcel)
656 {
657 //As this is only one record in land table I just delete all and then add a new record.
658 //As the delete landaccess is already in the pgsql code
659
660 //Delete old values
661 RemoveLandObject(parcel.LandData.GlobalID);
662
663 //Insert new values
664 string sql = @"INSERT INTO land
665 (""UUID"",""RegionUUID"",""LocalLandID"",""Bitmap"",""Name"",""Description"",""OwnerUUID"",""IsGroupOwned"",""Area"",""AuctionID"",""Category"",""ClaimDate"",""ClaimPrice"",
666 ""GroupUUID"",""SalePrice"",""LandStatus"",""LandFlags"",""LandingType"",""MediaAutoScale"",""MediaTextureUUID"",""MediaURL"",""MusicURL"",""PassHours"",""PassPrice"",
667 ""SnapshotUUID"",""UserLocationX"",""UserLocationY"",""UserLocationZ"",""UserLookAtX"",""UserLookAtY"",""UserLookAtZ"",""AuthbuyerID"",""OtherCleanTime"")
668 VALUES
669 (:UUID,:RegionUUID,:LocalLandID,:Bitmap,:Name,:Description,:OwnerUUID,:IsGroupOwned,:Area,:AuctionID,:Category,:ClaimDate,:ClaimPrice,
670 :GroupUUID,:SalePrice,:LandStatus,:LandFlags,:LandingType,:MediaAutoScale,:MediaTextureUUID,:MediaURL,:MusicURL,:PassHours,:PassPrice,
671 :SnapshotUUID,:UserLocationX,:UserLocationY,:UserLocationZ,:UserLookAtX,:UserLookAtY,:UserLookAtZ,:AuthbuyerID,:OtherCleanTime)";
672
673 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
674 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
675 {
676 cmd.Parameters.AddRange(CreateLandParameters(parcel.LandData, parcel.RegionUUID));
677 conn.Open();
678 cmd.ExecuteNonQuery();
679 }
680
681 sql = @"INSERT INTO landaccesslist (""LandUUID"",""AccessUUID"",""LandFlags"",""Expires"") VALUES (:LandUUID,:AccessUUID,:Flags,:Expires)";
682
683 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
684 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
685 {
686 conn.Open();
687 foreach (LandAccessEntry parcelAccessEntry in parcel.LandData.ParcelAccessList)
688 {
689 cmd.Parameters.AddRange(CreateLandAccessParameters(parcelAccessEntry, parcel.RegionUUID));
690
691 cmd.ExecuteNonQuery();
692 cmd.Parameters.Clear();
693 }
694 }
695 }
696
697 /// <summary>
698 /// Removes a land object from DB.
699 /// </summary>
700 /// <param name="globalID">UUID of landobject</param>
701 public void RemoveLandObject(UUID globalID)
702 {
703 string sql = @"delete from land where ""UUID""=:UUID";
704 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
705 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
706 {
707 cmd.Parameters.Add(_Database.CreateParameter("UUID", globalID));
708 conn.Open();
709 cmd.ExecuteNonQuery();
710 }
711 sql = @"delete from landaccesslist where ""LandUUID""=:UUID";
712 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
713 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
714 {
715 cmd.Parameters.Add(_Database.CreateParameter("UUID", globalID));
716 conn.Open();
717 cmd.ExecuteNonQuery();
718 }
719 }
720 public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID)
721 {
722 RegionLightShareData nWP = new RegionLightShareData();
723 nWP.OnSave += StoreRegionWindlightSettings;
724
725 string sql = @"select * from regionwindlight where ""region_id"" = :regionID";
726
727 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
728 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
729 {
730 cmd.Parameters.Add(_Database.CreateParameter("regionID", regionUUID.ToString() ));
731 conn.Open();
732 using (NpgsqlDataReader result = cmd.ExecuteReader())
733 {
734 if (!result.Read())
735 {
736 //No result, so store our default windlight profile and return it
737 nWP.regionID = regionUUID;
738 StoreRegionWindlightSettings(nWP);
739 return nWP;
740 }
741 else
742 {
743 nWP.regionID = DBGuid.FromDB(result["region_id"]);
744 nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]);
745 nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]);
746 nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]);
747 nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]);
748 nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]);
749 nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]);
750 nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]);
751 nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]);
752 nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]);
753 nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]);
754 nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]);
755 nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]);
756 nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]);
757 nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]);
758 nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]);
759 nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]);
760 nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]);
761 UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture);
762 nWP.horizon.X = Convert.ToSingle(result["horizon_r"]);
763 nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]);
764 nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]);
765 nWP.horizon.W = Convert.ToSingle(result["horizon_i"]);
766 nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]);
767 nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]);
768 nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]);
769 nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]);
770 nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]);
771 nWP.hazeDensity = Convert.ToSingle(result["haze_density"]);
772 nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]);
773 nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]);
774 nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]);
775 nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]);
776 nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]);
777 nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]);
778 nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]);
779 nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]);
780 nWP.ambient.X = Convert.ToSingle(result["ambient_r"]);
781 nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]);
782 nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]);
783 nWP.ambient.W = Convert.ToSingle(result["ambient_i"]);
784 nWP.eastAngle = Convert.ToSingle(result["east_angle"]);
785 nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]);
786 nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]);
787 nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]);
788 nWP.starBrightness = Convert.ToSingle(result["star_brightness"]);
789 nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]);
790 nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]);
791 nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]);
792 nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]);
793 nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]);
794 nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]);
795 nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]);
796 nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]);
797 nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]);
798 nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]);
799 nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]);
800 nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]);
801 nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]);
802 nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]);
803 nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]);
804 nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]);
805 nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]);
806 nWP.valid = true;
807 }
808 }
809 }
810 return nWP;
811 }
812
813 public void RemoveRegionWindlightSettings(UUID regionID)
814 {
815 string sql = @"delete from regionwindlight where ""region_id"" = :region_id";
816 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
817 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
818 {
819 conn.Open();
820 cmd.Parameters.Add(_Database.CreateParameter("region_id", regionID.ToString()));
821 cmd.ExecuteNonQuery();
822 }
823 }
824
825 public void StoreRegionWindlightSettings(RegionLightShareData wl)
826 {
827 string sql = @"select region_id from regionwindlight where ""region_id"" = :region_id limit 1;";
828 bool exists = false;
829 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
830 {
831 conn.Open();
832 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
833 {
834 cmd.Parameters.Add(_Database.CreateParameter("region_id", wl.regionID.ToString() ));
835 NpgsqlDataReader dr = cmd.ExecuteReader();
836 exists = dr.Read();
837 }
838 }
839 if (exists)
840 {
841 RemoveRegionWindlightSettings(wl.regionID);
842 }
843
844 // sql insert
845 sql = @"INSERT INTO regionwindlight
846 (region_id
847 ,water_color_r
848 ,water_color_g
849 ,water_color_b
850 ,water_fog_density_exponent
851 ,underwater_fog_modifier
852 ,reflection_wavelet_scale_1
853 ,reflection_wavelet_scale_2
854 ,reflection_wavelet_scale_3
855 ,fresnel_scale
856 ,fresnel_offset
857 ,refract_scale_above
858 ,refract_scale_below
859 ,blur_multiplier
860 ,big_wave_direction_x
861 ,big_wave_direction_y
862 ,little_wave_direction_x
863 ,little_wave_direction_y
864 ,normal_map_texture
865 ,horizon_r
866 ,horizon_g
867 ,horizon_b
868 ,horizon_i
869 ,haze_horizon
870 ,blue_density_r
871 ,blue_density_g
872 ,blue_density_b
873 ,blue_density_i
874 ,haze_density
875 ,density_multiplier
876 ,distance_multiplier
877 ,max_altitude
878 ,sun_moon_color_r
879 ,sun_moon_color_g
880 ,sun_moon_color_b
881 ,sun_moon_color_i
882 ,sun_moon_position
883 ,ambient_r
884 ,ambient_g
885 ,ambient_b
886 ,ambient_i
887 ,east_angle
888 ,sun_glow_focus
889 ,sun_glow_size
890 ,scene_gamma
891 ,star_brightness
892 ,cloud_color_r
893 ,cloud_color_g
894 ,cloud_color_b
895 ,cloud_color_i
896 ,cloud_x
897 ,cloud_y
898 ,cloud_density
899 ,cloud_coverage
900 ,cloud_scale
901 ,cloud_detail_x
902 ,cloud_detail_y
903 ,cloud_detail_density
904 ,cloud_scroll_x
905 ,cloud_scroll_x_lock
906 ,cloud_scroll_y
907 ,cloud_scroll_y_lock
908 ,draw_classic_clouds)
909 VALUES
910 (:region_id
911 ,:water_color_r
912 ,:water_color_g
913 ,:water_color_b
914 ,:water_fog_density_exponent
915 ,:underwater_fog_modifier
916 ,:reflection_wavelet_scale_1
917 ,:reflection_wavelet_scale_2
918 ,:reflection_wavelet_scale_3
919 ,:fresnel_scale
920 ,:fresnel_offset
921 ,:refract_scale_above
922 ,:refract_scale_below
923 ,:blur_multiplier
924 ,:big_wave_direction_x
925 ,:big_wave_direction_y
926 ,:little_wave_direction_x
927 ,:little_wave_direction_y
928 ,:normal_map_texture
929 ,:horizon_r
930 ,:horizon_g
931 ,:horizon_b
932 ,:horizon_i
933 ,:haze_horizon
934 ,:blue_density_r
935 ,:blue_density_g
936 ,:blue_density_b
937 ,:blue_density_i
938 ,:haze_density
939 ,:density_multiplier
940 ,:distance_multiplier
941 ,:max_altitude
942 ,:sun_moon_color_r
943 ,:sun_moon_color_g
944 ,:sun_moon_color_b
945 ,:sun_moon_color_i
946 ,:sun_moon_position
947 ,:ambient_r
948 ,:ambient_g
949 ,:ambient_b
950 ,:ambient_i
951 ,:east_angle
952 ,:sun_glow_focus
953 ,:sun_glow_size
954 ,:scene_gamma
955 ,:star_brightness
956 ,:cloud_color_r
957 ,:cloud_color_g
958 ,:cloud_color_b
959 ,:cloud_color_i
960 ,:cloud_x
961 ,:cloud_y
962 ,:cloud_density
963 ,:cloud_coverage
964 ,:cloud_scale
965 ,:cloud_detail_x
966 ,:cloud_detail_y
967 ,:cloud_detail_density
968 ,:cloud_scroll_x
969 ,:cloud_scroll_x_lock
970 ,:cloud_scroll_y
971 ,:cloud_scroll_y_lock
972 ,:draw_classic_clouds);";
973
974 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
975 {
976 conn.Open();
977 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
978 {
979 cmd.Parameters.Add(_Database.CreateParameter("region_id", wl.regionID.ToString()));
980 cmd.Parameters.Add(_Database.CreateParameter("water_color_r", wl.waterColor.X));
981 cmd.Parameters.Add(_Database.CreateParameter("water_color_g", wl.waterColor.Y));
982 cmd.Parameters.Add(_Database.CreateParameter("water_color_b", wl.waterColor.Z));
983 cmd.Parameters.Add(_Database.CreateParameter("water_fog_density_exponent", wl.waterFogDensityExponent));
984 cmd.Parameters.Add(_Database.CreateParameter("underwater_fog_modifier", wl.underwaterFogModifier));
985 cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X));
986 cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y));
987 cmd.Parameters.Add(_Database.CreateParameter("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z));
988 cmd.Parameters.Add(_Database.CreateParameter("fresnel_scale", wl.fresnelScale));
989 cmd.Parameters.Add(_Database.CreateParameter("fresnel_offset", wl.fresnelOffset));
990 cmd.Parameters.Add(_Database.CreateParameter("refract_scale_above", wl.refractScaleAbove));
991 cmd.Parameters.Add(_Database.CreateParameter("refract_scale_below", wl.refractScaleBelow));
992 cmd.Parameters.Add(_Database.CreateParameter("blur_multiplier", wl.blurMultiplier));
993 cmd.Parameters.Add(_Database.CreateParameter("big_wave_direction_x", wl.bigWaveDirection.X));
994 cmd.Parameters.Add(_Database.CreateParameter("big_wave_direction_y", wl.bigWaveDirection.Y));
995 cmd.Parameters.Add(_Database.CreateParameter("little_wave_direction_x", wl.littleWaveDirection.X));
996 cmd.Parameters.Add(_Database.CreateParameter("little_wave_direction_y", wl.littleWaveDirection.Y));
997 cmd.Parameters.Add(_Database.CreateParameter("normal_map_texture", wl.normalMapTexture.ToString()));
998 cmd.Parameters.Add(_Database.CreateParameter("horizon_r", wl.horizon.X));
999 cmd.Parameters.Add(_Database.CreateParameter("horizon_g", wl.horizon.Y));
1000 cmd.Parameters.Add(_Database.CreateParameter("horizon_b", wl.horizon.Z));
1001 cmd.Parameters.Add(_Database.CreateParameter("horizon_i", wl.horizon.W));
1002 cmd.Parameters.Add(_Database.CreateParameter("haze_horizon", wl.hazeHorizon));
1003 cmd.Parameters.Add(_Database.CreateParameter("blue_density_r", wl.blueDensity.X));
1004 cmd.Parameters.Add(_Database.CreateParameter("blue_density_g", wl.blueDensity.Y));
1005 cmd.Parameters.Add(_Database.CreateParameter("blue_density_b", wl.blueDensity.Z));
1006 cmd.Parameters.Add(_Database.CreateParameter("blue_density_i", wl.blueDensity.W));
1007 cmd.Parameters.Add(_Database.CreateParameter("haze_density", wl.hazeDensity));
1008 cmd.Parameters.Add(_Database.CreateParameter("density_multiplier", wl.densityMultiplier));
1009 cmd.Parameters.Add(_Database.CreateParameter("distance_multiplier", wl.distanceMultiplier));
1010 cmd.Parameters.Add(_Database.CreateParameter("max_altitude", wl.maxAltitude));
1011 cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_r", wl.sunMoonColor.X));
1012 cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_g", wl.sunMoonColor.Y));
1013 cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_b", wl.sunMoonColor.Z));
1014 cmd.Parameters.Add(_Database.CreateParameter("sun_moon_color_i", wl.sunMoonColor.W));
1015 cmd.Parameters.Add(_Database.CreateParameter("sun_moon_position", wl.sunMoonPosition));
1016 cmd.Parameters.Add(_Database.CreateParameter("ambient_r", wl.ambient.X));
1017 cmd.Parameters.Add(_Database.CreateParameter("ambient_g", wl.ambient.Y));
1018 cmd.Parameters.Add(_Database.CreateParameter("ambient_b", wl.ambient.Z));
1019 cmd.Parameters.Add(_Database.CreateParameter("ambient_i", wl.ambient.W));
1020 cmd.Parameters.Add(_Database.CreateParameter("east_angle", wl.eastAngle));
1021 cmd.Parameters.Add(_Database.CreateParameter("sun_glow_focus", wl.sunGlowFocus));
1022 cmd.Parameters.Add(_Database.CreateParameter("sun_glow_size", wl.sunGlowSize));
1023 cmd.Parameters.Add(_Database.CreateParameter("scene_gamma", wl.sceneGamma));
1024 cmd.Parameters.Add(_Database.CreateParameter("star_brightness", wl.starBrightness));
1025 cmd.Parameters.Add(_Database.CreateParameter("cloud_color_r", wl.cloudColor.X));
1026 cmd.Parameters.Add(_Database.CreateParameter("cloud_color_g", wl.cloudColor.Y));
1027 cmd.Parameters.Add(_Database.CreateParameter("cloud_color_b", wl.cloudColor.Z));
1028 cmd.Parameters.Add(_Database.CreateParameter("cloud_color_i", wl.cloudColor.W));
1029 cmd.Parameters.Add(_Database.CreateParameter("cloud_x", wl.cloudXYDensity.X));
1030 cmd.Parameters.Add(_Database.CreateParameter("cloud_y", wl.cloudXYDensity.Y));
1031 cmd.Parameters.Add(_Database.CreateParameter("cloud_density", wl.cloudXYDensity.Z));
1032 cmd.Parameters.Add(_Database.CreateParameter("cloud_coverage", wl.cloudCoverage));
1033 cmd.Parameters.Add(_Database.CreateParameter("cloud_scale", wl.cloudScale));
1034 cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_x", wl.cloudDetailXYDensity.X));
1035 cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_y", wl.cloudDetailXYDensity.Y));
1036 cmd.Parameters.Add(_Database.CreateParameter("cloud_detail_density", wl.cloudDetailXYDensity.Z));
1037 cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_x", wl.cloudScrollX));
1038 cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_x_lock", wl.cloudScrollXLock));
1039 cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_y", wl.cloudScrollY));
1040 cmd.Parameters.Add(_Database.CreateParameter("cloud_scroll_y_lock", wl.cloudScrollYLock));
1041 cmd.Parameters.Add(_Database.CreateParameter("draw_classic_clouds", wl.drawClassicClouds));
1042
1043 cmd.ExecuteNonQuery();
1044 }
1045 }
1046 #region update
1047 // }
1048 // else
1049 // {
1050 // // sql update
1051 // sql = @"UPDATE [OpenSim].[dbo].[regionwindlight]
1052 // SET [region_id] = @region_id
1053 // ,[water_color_r] = @water_color_r
1054 // ,[water_color_g] = @water_color_g
1055 // ,[water_color_b] = @water_color_b
1056 // ,[water_fog_density_exponent] = @water_fog_density_exponent
1057 // ,[underwater_fog_modifier] = @underwater_fog_modifier
1058 // ,[reflection_wavelet_scale_1] = @reflection_wavelet_scale_1
1059 // ,[reflection_wavelet_scale_2] = @reflection_wavelet_scale_2
1060 // ,[reflection_wavelet_scale_3] = @reflection_wavelet_scale_3
1061 // ,[fresnel_scale] = @fresnel_scale
1062 // ,[fresnel_offset] = @fresnel_offset
1063 // ,[refract_scale_above] = @refract_scale_above
1064 // ,[refract_scale_below] = @refract_scale_below
1065 // ,[blur_multiplier] = @blur_multiplier
1066 // ,[big_wave_direction_x] = @big_wave_direction_x
1067 // ,[big_wave_direction_y] = @big_wave_direction_y
1068 // ,[little_wave_direction_x] = @little_wave_direction_x
1069 // ,[little_wave_direction_y] = @little_wave_direction_y
1070 // ,[normal_map_texture] = @normal_map_texture
1071 // ,[horizon_r] = @horizon_r
1072 // ,[horizon_g] = @horizon_g
1073 // ,[horizon_b] = @horizon_b
1074 // ,[horizon_i] = @horizon_i
1075 // ,[haze_horizon] = @haze_horizon
1076 // ,[blue_density_r] = @blue_density_r
1077 // ,[blue_density_g] = @blue_density_g
1078 // ,[blue_density_b] = @blue_density_b
1079 // ,[blue_density_i] = @blue_density_i
1080 // ,[haze_density] = @haze_density
1081 // ,[density_multiplier] = @density_multiplier
1082 // ,[distance_multiplier] = @distance_multiplier
1083 // ,[max_altitude] = @max_altitude
1084 // ,[sun_moon_color_r] = @sun_moon_color_r
1085 // ,[sun_moon_color_g] = @sun_moon_color_g
1086 // ,[sun_moon_color_b] = @sun_moon_color_b
1087 // ,[sun_moon_color_i] = @sun_moon_color_i
1088 // ,[sun_moon_position] = @sun_moon_position
1089 // ,[ambient_r] = @ambient_r
1090 // ,[ambient_g] = @ambient_g
1091 // ,[ambient_b] = @ambient_b
1092 // ,[ambient_i] = @ambient_i
1093 // ,[east_angle] = @east_angle
1094 // ,[sun_glow_focus] = @sun_glow_focus
1095 // ,[sun_glow_size] = @sun_glow_size
1096 // ,[scene_gamma] = @scene_gamma
1097 // ,[star_brightness] = @star_brightness
1098 // ,[cloud_color_r] = @cloud_color_r
1099 // ,[cloud_color_g] = @cloud_color_g
1100 // ,[cloud_color_b] = @cloud_color_b
1101 // ,[cloud_color_i] = @cloud_color_i
1102 // ,[cloud_x] = @cloud_x
1103 // ,[cloud_y] = @cloud_y
1104 // ,[cloud_density] = @cloud_density
1105 // ,[cloud_coverage] = @cloud_coverage
1106 // ,[cloud_scale] = @cloud_scale
1107 // ,[cloud_detail_x] = @cloud_detail_x
1108 // ,[cloud_detail_y] = @cloud_detail_y
1109 // ,[cloud_detail_density] = @cloud_detail_density
1110 // ,[cloud_scroll_x] = @cloud_scroll_x
1111 // ,[cloud_scroll_x_lock] = @cloud_scroll_x_lock
1112 // ,[cloud_scroll_y] = @cloud_scroll_y
1113 // ,[cloud_scroll_y_lock] = @cloud_scroll_y_lock
1114 // ,[draw_classic_clouds] = @draw_classic_clouds
1115 // WHERE region_id = @region_id";
1116 // using (SqlConnection conn = new SqlConnection(m_connectionString))
1117 // {
1118 // conn.Open();
1119 // using (SqlCommand cmd = new SqlCommand(sql, conn))
1120 // {
1121 // cmd.Parameters.AddWithValue("region_id", wl.regionID);
1122 // cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X);
1123 // cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y);
1124 // cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z);
1125 // cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent);
1126 // cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier);
1127 // cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X);
1128 // cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y);
1129 // cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z);
1130 // cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale);
1131 // cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset);
1132 // cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove);
1133 // cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow);
1134 // cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier);
1135 // cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X);
1136 // cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y);
1137 // cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X);
1138 // cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y);
1139 // cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture);
1140 // cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X);
1141 // cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y);
1142 // cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z);
1143 // cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W);
1144 // cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon);
1145 // cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X);
1146 // cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y);
1147 // cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z);
1148 // cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W);
1149 // cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity);
1150 // cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier);
1151 // cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier);
1152 // cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude);
1153 // cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X);
1154 // cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y);
1155 // cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z);
1156 // cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W);
1157 // cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition);
1158 // cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X);
1159 // cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y);
1160 // cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z);
1161 // cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W);
1162 // cmd.Parameters.AddWithValue("east_angle", wl.eastAngle);
1163 // cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus);
1164 // cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize);
1165 // cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma);
1166 // cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness);
1167 // cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X);
1168 // cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y);
1169 // cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z);
1170 // cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W);
1171 // cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X);
1172 // cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y);
1173 // cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z);
1174 // cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage);
1175 // cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale);
1176 // cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X);
1177 // cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y);
1178 // cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z);
1179 // cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX);
1180 // cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock);
1181 // cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY);
1182 // cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock);
1183 // cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds);
1184
1185 // cmd.ExecuteNonQuery();
1186 // }
1187 // }
1188 // }
1189 #endregion
1190 }
1191
1192 #region Environment Settings
1193 public string LoadRegionEnvironmentSettings(UUID regionUUID)
1194 {
1195 string sql = "select * from regionenvironment where region_id = :region_id";
1196 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1197 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1198 {
1199 cmd.Parameters.Add(_Database.CreateParameter("region_id", regionUUID));
1200 conn.Open();
1201 using (NpgsqlDataReader result = cmd.ExecuteReader())
1202 {
1203 if (!result.Read())
1204 {
1205 return String.Empty;
1206 }
1207 else
1208 {
1209 return Convert.ToString(result["llsd_settings"]);
1210 }
1211 }
1212 }
1213 }
1214
1215 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
1216 {
1217 {
1218 string sql = "DELETE FROM regionenvironment WHERE region_id = :region_id ;";
1219
1220 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1221 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1222 {
1223 cmd.Parameters.Add(_Database.CreateParameter("region_id", regionUUID));
1224 conn.Open();
1225 cmd.ExecuteNonQuery();
1226 }
1227
1228 sql = "INSERT INTO regionenvironment (region_id, llsd_settings) VALUES (:region_id, :llsd_settings) ;";
1229
1230 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1231 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1232 {
1233 cmd.Parameters.Add(_Database.CreateParameter("region_id", regionUUID));
1234 cmd.Parameters.Add(_Database.CreateParameter("llsd_settings", settings));
1235
1236 conn.Open();
1237 cmd.ExecuteNonQuery();
1238 }
1239 }
1240 }
1241
1242 public void RemoveRegionEnvironmentSettings(UUID regionUUID)
1243 {
1244 string sql = "delete from regionenvironment where region_id = :region_id ;";
1245 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1246 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1247 {
1248 cmd.Parameters.Add(_Database.CreateParameter("region_id", regionUUID));
1249
1250 conn.Open();
1251 cmd.ExecuteNonQuery();
1252 }
1253 }
1254 #endregion
1255
1256 /// <summary>
1257 /// Loads the settings of a region.
1258 /// </summary>
1259 /// <param name="regionUUID">The region UUID.</param>
1260 /// <returns></returns>
1261 public RegionSettings LoadRegionSettings(UUID regionUUID)
1262 {
1263 string sql = @"select * from regionsettings where ""regionUUID"" = :regionUUID";
1264 RegionSettings regionSettings;
1265 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1266 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1267 {
1268 cmd.Parameters.Add(_Database.CreateParameter("regionUUID", regionUUID));
1269 conn.Open();
1270 using (NpgsqlDataReader reader = cmd.ExecuteReader())
1271 {
1272 if (reader.Read())
1273 {
1274 regionSettings = BuildRegionSettings(reader);
1275 regionSettings.OnSave += StoreRegionSettings;
1276
1277 return regionSettings;
1278 }
1279 }
1280 }
1281
1282 //If we reach this point then there are new region settings for that region
1283 regionSettings = new RegionSettings();
1284 regionSettings.RegionUUID = regionUUID;
1285 regionSettings.OnSave += StoreRegionSettings;
1286
1287 //Store new values
1288 StoreNewRegionSettings(regionSettings);
1289
1290 LoadSpawnPoints(regionSettings);
1291
1292 return regionSettings;
1293 }
1294
1295 /// <summary>
1296 /// Store region settings, need to check if the check is really necesary. If we can make something for creating new region.
1297 /// </summary>
1298 /// <param name="regionSettings">region settings.</param>
1299 public void StoreRegionSettings(RegionSettings regionSettings)
1300 {
1301 //Little check if regionUUID already exist in DB
1302 string regionUUID;
1303 string sql = @"SELECT ""regionUUID"" FROM regionsettings WHERE ""regionUUID"" = :regionUUID";
1304 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1305 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1306 {
1307 cmd.Parameters.Add(_Database.CreateParameter("regionUUID", regionSettings.RegionUUID));
1308 conn.Open();
1309 regionUUID = cmd.ExecuteScalar().ToString();
1310 }
1311
1312 if (string.IsNullOrEmpty(regionUUID))
1313 {
1314 StoreNewRegionSettings(regionSettings);
1315 }
1316 else
1317 {
1318 //This method only updates region settings!!! First call LoadRegionSettings to create new region settings in DB
1319 sql =
1320 @"UPDATE regionsettings SET block_terraform = :block_terraform ,block_fly = :block_fly ,allow_damage = :allow_damage
1321,restrict_pushing = :restrict_pushing ,allow_land_resell = :allow_land_resell ,allow_land_join_divide = :allow_land_join_divide
1322,block_show_in_search = :block_show_in_search ,agent_limit = :agent_limit ,object_bonus = :object_bonus ,maturity = :maturity
1323,disable_scripts = :disable_scripts ,disable_collisions = :disable_collisions ,disable_physics = :disable_physics
1324,terrain_texture_1 = :terrain_texture_1 ,terrain_texture_2 = :terrain_texture_2 ,terrain_texture_3 = :terrain_texture_3
1325,terrain_texture_4 = :terrain_texture_4 ,elevation_1_nw = :elevation_1_nw ,elevation_2_nw = :elevation_2_nw
1326,elevation_1_ne = :elevation_1_ne ,elevation_2_ne = :elevation_2_ne ,elevation_1_se = :elevation_1_se ,elevation_2_se = :elevation_2_se
1327,elevation_1_sw = :elevation_1_sw ,elevation_2_sw = :elevation_2_sw ,water_height = :water_height ,terrain_raise_limit = :terrain_raise_limit
1328,terrain_lower_limit = :terrain_lower_limit ,use_estate_sun = :use_estate_sun ,fixed_sun = :fixed_sun ,sun_position = :sun_position
1329,covenant = :covenant ,covenant_datetime = :covenant_datetime, sunvectorx = :sunvectorx, sunvectory = :sunvectory, sunvectorz = :sunvectorz,
1330""Sandbox"" = :Sandbox, loaded_creation_datetime = :loaded_creation_datetime, loaded_creation_id = :loaded_creation_id, ""map_tile_ID"" = :TerrainImageID,
1331""TelehubObject"" = :telehubobject, ""parcel_tile_ID"" = :ParcelImageID
1332 WHERE ""regionUUID"" = :regionUUID";
1333
1334 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1335 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1336 {
1337 cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings));
1338 conn.Open();
1339 cmd.ExecuteNonQuery();
1340 }
1341 }
1342 SaveSpawnPoints(regionSettings);
1343 }
1344
1345 public void Shutdown()
1346 {
1347 //Not used??
1348 }
1349
1350 #region Private Methods
1351
1352 /// <summary>
1353 /// Serializes the terrain data for storage in DB.
1354 /// </summary>
1355 /// <param name="val">terrain data</param>
1356 /// <returns></returns>
1357 private static Array serializeTerrain(double[,] val)
1358 {
1359 MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) * sizeof(double));
1360 BinaryWriter bw = new BinaryWriter(str);
1361
1362 // TODO: COMPATIBILITY - Add byte-order conversions
1363 for (int x = 0; x < (int)Constants.RegionSize; x++)
1364 for (int y = 0; y < (int)Constants.RegionSize; y++)
1365 {
1366 double height = val[x, y];
1367 if (height == 0.0)
1368 height = double.Epsilon;
1369
1370 bw.Write(height);
1371 }
1372
1373 return str.ToArray();
1374 }
1375
1376 /// <summary>
1377 /// Stores new regionsettings.
1378 /// </summary>
1379 /// <param name="regionSettings">The region settings.</param>
1380 private void StoreNewRegionSettings(RegionSettings regionSettings)
1381 {
1382 string sql = @"INSERT INTO regionsettings
1383 (""regionUUID"",block_terraform,block_fly,allow_damage,restrict_pushing,allow_land_resell,allow_land_join_divide,
1384 block_show_in_search,agent_limit,object_bonus,maturity,disable_scripts,disable_collisions,disable_physics,
1385 terrain_texture_1,terrain_texture_2,terrain_texture_3,terrain_texture_4,elevation_1_nw,elevation_2_nw,elevation_1_ne,
1386 elevation_2_ne,elevation_1_se,elevation_2_se,elevation_1_sw,elevation_2_sw,water_height,terrain_raise_limit,
1387 terrain_lower_limit,use_estate_sun,fixed_sun,sun_position,covenant,covenant_datetime,sunvectorx, sunvectory, sunvectorz,
1388 ""Sandbox"", loaded_creation_datetime, loaded_creation_id
1389 )
1390 VALUES
1391 (:regionUUID,:block_terraform,:block_fly,:allow_damage,:restrict_pushing,:allow_land_resell,:allow_land_join_divide,
1392 :block_show_in_search,:agent_limit,:object_bonus,:maturity,:disable_scripts,:disable_collisions,:disable_physics,
1393 :terrain_texture_1,:terrain_texture_2,:terrain_texture_3,:terrain_texture_4,:elevation_1_nw,:elevation_2_nw,:elevation_1_ne,
1394 :elevation_2_ne,:elevation_1_se,:elevation_2_se,:elevation_1_sw,:elevation_2_sw,:water_height,:terrain_raise_limit,
1395 :terrain_lower_limit,:use_estate_sun,:fixed_sun,:sun_position,:covenant, :covenant_datetime, :sunvectorx,:sunvectory,
1396 :sunvectorz, :Sandbox, :loaded_creation_datetime, :loaded_creation_id )";
1397
1398 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
1399 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
1400 {
1401 cmd.Parameters.AddRange(CreateRegionSettingParameters(regionSettings));
1402 conn.Open();
1403 cmd.ExecuteNonQuery();
1404 }
1405 }
1406
1407 #region Private DataRecord conversion methods
1408
1409 /// <summary>
1410 /// Builds the region settings from a datarecod.
1411 /// </summary>
1412 /// <param name="row">datarecord with regionsettings.</param>
1413 /// <returns></returns>
1414 private static RegionSettings BuildRegionSettings(IDataRecord row)
1415 {
1416 //TODO change this is some more generic code so we doesnt have to change it every time a new field is added?
1417 RegionSettings newSettings = new RegionSettings();
1418
1419 newSettings.RegionUUID = new UUID((Guid)row["regionUUID"]);
1420 newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]);
1421 newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]);
1422 newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]);
1423 newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]);
1424 newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]);
1425 newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]);
1426 newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]);
1427 newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]);
1428 newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]);
1429 newSettings.Maturity = Convert.ToInt32(row["maturity"]);
1430 newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]);
1431 newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]);
1432 newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]);
1433 newSettings.TerrainTexture1 = new UUID((Guid)row["terrain_texture_1"]);
1434 newSettings.TerrainTexture2 = new UUID((Guid)row["terrain_texture_2"]);
1435 newSettings.TerrainTexture3 = new UUID((Guid)row["terrain_texture_3"]);
1436 newSettings.TerrainTexture4 = new UUID((Guid)row["terrain_texture_4"]);
1437 newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]);
1438 newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]);
1439 newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]);
1440 newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]);
1441 newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]);
1442 newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]);
1443 newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]);
1444 newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]);
1445 newSettings.WaterHeight = Convert.ToDouble(row["water_height"]);
1446 newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]);
1447 newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]);
1448 newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]);
1449 newSettings.Sandbox = Convert.ToBoolean(row["Sandbox"]);
1450 newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]);
1451 newSettings.SunPosition = Convert.ToDouble(row["sun_position"]);
1452 newSettings.SunVector = new Vector3(
1453 Convert.ToSingle(row["sunvectorx"]),
1454 Convert.ToSingle(row["sunvectory"]),
1455 Convert.ToSingle(row["sunvectorz"])
1456 );
1457 newSettings.Covenant = new UUID((Guid)row["covenant"]);
1458 newSettings.CovenantChangedDateTime = Convert.ToInt32(row["covenant_datetime"]);
1459 newSettings.LoadedCreationDateTime = Convert.ToInt32(row["loaded_creation_datetime"]);
1460
1461 if (row["loaded_creation_id"] is DBNull)
1462 newSettings.LoadedCreationID = "";
1463 else
1464 newSettings.LoadedCreationID = (String)row["loaded_creation_id"];
1465
1466 newSettings.TerrainImageID = new UUID((string)row["map_tile_ID"]);
1467 newSettings.ParcelImageID = new UUID((Guid)row["parcel_tile_ID"]);
1468 newSettings.TelehubObject = new UUID((Guid)row["TelehubObject"]);
1469
1470 return newSettings;
1471 }
1472
1473 /// <summary>
1474 /// Builds the land data from a datarecord.
1475 /// </summary>
1476 /// <param name="row">datarecord with land data</param>
1477 /// <returns></returns>
1478 private static LandData BuildLandData(IDataRecord row)
1479 {
1480 LandData newData = new LandData();
1481
1482 newData.GlobalID = new UUID((Guid)row["UUID"]);
1483 newData.LocalID = Convert.ToInt32(row["LocalLandID"]);
1484
1485 // Bitmap is a byte[512]
1486 newData.Bitmap = (Byte[])row["Bitmap"];
1487
1488 newData.Name = (string)row["Name"];
1489 newData.Description = (string)row["Description"];
1490 newData.OwnerID = new UUID((Guid)row["OwnerUUID"]);
1491 newData.IsGroupOwned = Convert.ToBoolean(row["IsGroupOwned"]);
1492 newData.Area = Convert.ToInt32(row["Area"]);
1493 newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented
1494 newData.Category = (ParcelCategory)Convert.ToInt32(row["Category"]);
1495 //Enum libsecondlife.Parcel.ParcelCategory
1496 newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]);
1497 newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]);
1498 newData.GroupID = new UUID((Guid)row["GroupUUID"]);
1499 newData.SalePrice = Convert.ToInt32(row["SalePrice"]);
1500 newData.Status = (ParcelStatus)Convert.ToInt32(row["LandStatus"]);
1501 //Enum. libsecondlife.Parcel.ParcelStatus
1502 newData.Flags = Convert.ToUInt32(row["LandFlags"]);
1503 newData.LandingType = Convert.ToByte(row["LandingType"]);
1504 newData.MediaAutoScale = Convert.ToByte(row["MediaAutoScale"]);
1505 newData.MediaID = new UUID((Guid)row["MediaTextureUUID"]);
1506 newData.MediaURL = (string)row["MediaURL"];
1507 newData.MusicURL = (string)row["MusicURL"];
1508 newData.PassHours = Convert.ToSingle(row["PassHours"]);
1509 newData.PassPrice = Convert.ToInt32(row["PassPrice"]);
1510
1511 // UUID authedbuyer;
1512 // UUID snapshotID;
1513 //
1514 // if (UUID.TryParse((string)row["AuthBuyerID"], out authedbuyer))
1515 // newData.AuthBuyerID = authedbuyer;
1516 //
1517 // if (UUID.TryParse((string)row["SnapshotUUID"], out snapshotID))
1518 // newData.SnapshotID = snapshotID;
1519 newData.AuthBuyerID = new UUID((Guid)row["AuthBuyerID"]);
1520 newData.SnapshotID = new UUID((Guid)row["SnapshotUUID"]);
1521
1522 newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]);
1523
1524 try
1525 {
1526 newData.UserLocation =
1527 new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]),
1528 Convert.ToSingle(row["UserLocationZ"]));
1529 newData.UserLookAt =
1530 new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]),
1531 Convert.ToSingle(row["UserLookAtZ"]));
1532 }
1533 catch (InvalidCastException)
1534 {
1535 newData.UserLocation = Vector3.Zero;
1536 newData.UserLookAt = Vector3.Zero;
1537 _Log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name);
1538 }
1539
1540 newData.ParcelAccessList = new List<LandAccessEntry>();
1541 newData.MediaDescription = (string)row["MediaDescription"];
1542 newData.MediaType = (string)row["MediaType"];
1543 newData.MediaWidth = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[0]);
1544 newData.MediaHeight = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[1]);
1545 newData.MediaLoop = Convert.ToBoolean(row["MediaLoop"]);
1546 newData.ObscureMusic = Convert.ToBoolean(row["ObscureMusic"]);
1547 newData.ObscureMedia = Convert.ToBoolean(row["ObscureMedia"]);
1548
1549 return newData;
1550 }
1551
1552 /// <summary>
1553 /// Builds the landaccess data from a data record.
1554 /// </summary>
1555 /// <param name="row">datarecord with landaccess data</param>
1556 /// <returns></returns>
1557 private static LandAccessEntry BuildLandAccessData(IDataRecord row)
1558 {
1559 LandAccessEntry entry = new LandAccessEntry();
1560 entry.AgentID = new UUID((Guid)row["AccessUUID"]);
1561 entry.Flags = (AccessList)Convert.ToInt32(row["Flags"]);
1562 entry.Expires = Convert.ToInt32(row["Expires"]);
1563 return entry;
1564 }
1565
1566 /// <summary>
1567 /// Builds the prim from a datarecord.
1568 /// </summary>
1569 /// <param name="primRow">datarecord</param>
1570 /// <returns></returns>
1571 private static SceneObjectPart BuildPrim(IDataRecord primRow)
1572 {
1573 SceneObjectPart prim = new SceneObjectPart();
1574
1575 prim.UUID = new UUID((Guid)primRow["UUID"]);
1576 // explicit conversion of integers is required, which sort
1577 // of sucks. No idea if there is a shortcut here or not.
1578 prim.CreationDate = Convert.ToInt32(primRow["CreationDate"]);
1579 prim.Name = (string)primRow["Name"];
1580 // various text fields
1581 prim.Text = (string)primRow["Text"];
1582 prim.Color = Color.FromArgb(Convert.ToInt32(primRow["ColorA"]),
1583 Convert.ToInt32(primRow["ColorR"]),
1584 Convert.ToInt32(primRow["ColorG"]),
1585 Convert.ToInt32(primRow["ColorB"]));
1586 prim.Description = (string)primRow["Description"];
1587 prim.SitName = (string)primRow["SitName"];
1588 prim.TouchName = (string)primRow["TouchName"];
1589 // permissions
1590 prim.Flags = (PrimFlags)Convert.ToUInt32(primRow["ObjectFlags"]);
1591 //prim.creatorID = new UUID((Guid)primRow["creatorID"]);
1592 prim.CreatorIdentification = (string)primRow["CreatorID"].ToString();
1593 prim.OwnerID = new UUID((Guid)primRow["OwnerID"]);
1594 prim.GroupID = new UUID((Guid)primRow["GroupID"]);
1595 prim.LastOwnerID = new UUID((Guid)primRow["LastOwnerID"]);
1596 prim.OwnerMask = Convert.ToUInt32(primRow["OwnerMask"]);
1597 prim.NextOwnerMask = Convert.ToUInt32(primRow["NextOwnerMask"]);
1598 prim.GroupMask = Convert.ToUInt32(primRow["GroupMask"]);
1599 prim.EveryoneMask = Convert.ToUInt32(primRow["EveryoneMask"]);
1600 prim.BaseMask = Convert.ToUInt32(primRow["BaseMask"]);
1601 // vectors
1602 prim.OffsetPosition = new Vector3(
1603 Convert.ToSingle(primRow["PositionX"]),
1604 Convert.ToSingle(primRow["PositionY"]),
1605 Convert.ToSingle(primRow["PositionZ"]));
1606
1607 prim.GroupPosition = new Vector3(
1608 Convert.ToSingle(primRow["GroupPositionX"]),
1609 Convert.ToSingle(primRow["GroupPositionY"]),
1610 Convert.ToSingle(primRow["GroupPositionZ"]));
1611
1612 prim.Velocity = new Vector3(
1613 Convert.ToSingle(primRow["VelocityX"]),
1614 Convert.ToSingle(primRow["VelocityY"]),
1615 Convert.ToSingle(primRow["VelocityZ"]));
1616
1617 prim.AngularVelocity = new Vector3(
1618 Convert.ToSingle(primRow["AngularVelocityX"]),
1619 Convert.ToSingle(primRow["AngularVelocityY"]),
1620 Convert.ToSingle(primRow["AngularVelocityZ"]));
1621
1622 prim.Acceleration = new Vector3(
1623 Convert.ToSingle(primRow["AccelerationX"]),
1624 Convert.ToSingle(primRow["AccelerationY"]),
1625 Convert.ToSingle(primRow["AccelerationZ"]));
1626
1627 // quaternions
1628 prim.RotationOffset = new Quaternion(
1629 Convert.ToSingle(primRow["RotationX"]),
1630 Convert.ToSingle(primRow["RotationY"]),
1631 Convert.ToSingle(primRow["RotationZ"]),
1632 Convert.ToSingle(primRow["RotationW"]));
1633
1634 prim.SitTargetPositionLL = new Vector3(
1635 Convert.ToSingle(primRow["SitTargetOffsetX"]),
1636 Convert.ToSingle(primRow["SitTargetOffsetY"]),
1637 Convert.ToSingle(primRow["SitTargetOffsetZ"]));
1638
1639 prim.SitTargetOrientationLL = new Quaternion(
1640 Convert.ToSingle(primRow["SitTargetOrientX"]),
1641 Convert.ToSingle(primRow["SitTargetOrientY"]),
1642 Convert.ToSingle(primRow["SitTargetOrientZ"]),
1643 Convert.ToSingle(primRow["SitTargetOrientW"]));
1644
1645 prim.PayPrice[0] = Convert.ToInt32(primRow["PayPrice"]);
1646 prim.PayPrice[1] = Convert.ToInt32(primRow["PayButton1"]);
1647 prim.PayPrice[2] = Convert.ToInt32(primRow["PayButton2"]);
1648 prim.PayPrice[3] = Convert.ToInt32(primRow["PayButton3"]);
1649 prim.PayPrice[4] = Convert.ToInt32(primRow["PayButton4"]);
1650
1651 prim.Sound = new UUID((Guid)primRow["LoopedSound"]);
1652 prim.SoundGain = Convert.ToSingle(primRow["LoopedSoundGain"]);
1653 prim.SoundFlags = 1; // If it's persisted at all, it's looped
1654
1655 if (!(primRow["TextureAnimation"] is DBNull))
1656 prim.TextureAnimation = (Byte[])primRow["TextureAnimation"];
1657 if (!(primRow["ParticleSystem"] is DBNull))
1658 prim.ParticleSystem = (Byte[])primRow["ParticleSystem"];
1659
1660 prim.AngularVelocity = new Vector3(
1661 Convert.ToSingle(primRow["OmegaX"]),
1662 Convert.ToSingle(primRow["OmegaY"]),
1663 Convert.ToSingle(primRow["OmegaZ"]));
1664
1665 prim.SetCameraEyeOffset(new Vector3(
1666 Convert.ToSingle(primRow["CameraEyeOffsetX"]),
1667 Convert.ToSingle(primRow["CameraEyeOffsetY"]),
1668 Convert.ToSingle(primRow["CameraEyeOffsetZ"])
1669 ));
1670
1671 prim.SetCameraAtOffset(new Vector3(
1672 Convert.ToSingle(primRow["CameraAtOffsetX"]),
1673 Convert.ToSingle(primRow["CameraAtOffsetY"]),
1674 Convert.ToSingle(primRow["CameraAtOffsetZ"])
1675 ));
1676
1677 if (Convert.ToInt16(primRow["ForceMouselook"]) != 0)
1678 prim.SetForceMouselook(true);
1679
1680 prim.ScriptAccessPin = Convert.ToInt32(primRow["ScriptAccessPin"]);
1681
1682 if (Convert.ToInt16(primRow["AllowedDrop"]) != 0)
1683 prim.AllowedDrop = true;
1684
1685 if (Convert.ToInt16(primRow["DieAtEdge"]) != 0)
1686 prim.DIE_AT_EDGE = true;
1687
1688 prim.SalePrice = Convert.ToInt32(primRow["SalePrice"]);
1689 prim.ObjectSaleType = Convert.ToByte(primRow["SaleType"]);
1690
1691 prim.Material = Convert.ToByte(primRow["Material"]);
1692
1693 if (!(primRow["ClickAction"] is DBNull))
1694 prim.ClickAction = Convert.ToByte(primRow["ClickAction"]);
1695
1696 prim.CollisionSound = new UUID((Guid)primRow["CollisionSound"]);
1697 prim.CollisionSoundVolume = Convert.ToSingle(primRow["CollisionSoundVolume"]);
1698
1699 prim.PassTouches = (bool)primRow["PassTouches"];
1700
1701 if (!(primRow["MediaURL"] is System.DBNull))
1702 prim.MediaUrl = (string)primRow["MediaURL"];
1703
1704 if (!(primRow["DynAttrs"] is System.DBNull) && (string)primRow["DynAttrs"] != "")
1705 prim.DynAttrs = DAMap.FromXml((string)primRow["DynAttrs"]);
1706 else
1707 prim.DynAttrs = new DAMap();
1708
1709 prim.PhysicsShapeType = Convert.ToByte(primRow["PhysicsShapeType"]);
1710 prim.Density = Convert.ToSingle(primRow["Density"]);
1711 prim.GravityModifier = Convert.ToSingle(primRow["GravityModifier"]);
1712 prim.Friction = Convert.ToSingle(primRow["Friction"]);
1713 prim.Restitution = Convert.ToSingle(primRow["Restitution"]);
1714
1715 return prim;
1716 }
1717
1718 /// <summary>
1719 /// Builds the prim shape from a datarecord.
1720 /// </summary>
1721 /// <param name="shapeRow">The row.</param>
1722 /// <returns></returns>
1723 private static PrimitiveBaseShape BuildShape(IDataRecord shapeRow)
1724 {
1725 PrimitiveBaseShape baseShape = new PrimitiveBaseShape();
1726
1727 baseShape.Scale = new Vector3(
1728 (float)Convert.ToDouble(shapeRow["ScaleX"]),
1729 (float)Convert.ToDouble(shapeRow["ScaleY"]),
1730 (float)Convert.ToDouble(shapeRow["ScaleZ"]));
1731
1732 // paths
1733 baseShape.PCode = Convert.ToByte(shapeRow["PCode"]);
1734 baseShape.PathBegin = Convert.ToUInt16(shapeRow["PathBegin"]);
1735 baseShape.PathEnd = Convert.ToUInt16(shapeRow["PathEnd"]);
1736 baseShape.PathScaleX = Convert.ToByte(shapeRow["PathScaleX"]);
1737 baseShape.PathScaleY = Convert.ToByte(shapeRow["PathScaleY"]);
1738 baseShape.PathShearX = Convert.ToByte(shapeRow["PathShearX"]);
1739 baseShape.PathShearY = Convert.ToByte(shapeRow["PathShearY"]);
1740 baseShape.PathSkew = Convert.ToSByte(shapeRow["PathSkew"]);
1741 baseShape.PathCurve = Convert.ToByte(shapeRow["PathCurve"]);
1742 baseShape.PathRadiusOffset = Convert.ToSByte(shapeRow["PathRadiusOffset"]);
1743 baseShape.PathRevolutions = Convert.ToByte(shapeRow["PathRevolutions"]);
1744 baseShape.PathTaperX = Convert.ToSByte(shapeRow["PathTaperX"]);
1745 baseShape.PathTaperY = Convert.ToSByte(shapeRow["PathTaperY"]);
1746 baseShape.PathTwist = Convert.ToSByte(shapeRow["PathTwist"]);
1747 baseShape.PathTwistBegin = Convert.ToSByte(shapeRow["PathTwistBegin"]);
1748 // profile
1749 baseShape.ProfileBegin = Convert.ToUInt16(shapeRow["ProfileBegin"]);
1750 baseShape.ProfileEnd = Convert.ToUInt16(shapeRow["ProfileEnd"]);
1751 baseShape.ProfileCurve = Convert.ToByte(shapeRow["ProfileCurve"]);
1752 baseShape.ProfileHollow = Convert.ToUInt16(shapeRow["ProfileHollow"]);
1753
1754 byte[] textureEntry = (byte[])shapeRow["Texture"];
1755 baseShape.TextureEntry = textureEntry;
1756
1757 baseShape.ExtraParams = (byte[])shapeRow["ExtraParams"];
1758
1759 try
1760 {
1761 baseShape.State = Convert.ToByte(shapeRow["State"]);
1762 }
1763 catch (InvalidCastException)
1764 {
1765 }
1766
1767 if (!(shapeRow["Media"] is System.DBNull))
1768 {
1769 baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]);
1770 }
1771
1772 return baseShape;
1773 }
1774
1775 /// <summary>
1776 /// Build a prim inventory item from the persisted data.
1777 /// </summary>
1778 /// <param name="inventoryRow"></param>
1779 /// <returns></returns>
1780 private static TaskInventoryItem BuildItem(IDataRecord inventoryRow)
1781 {
1782 TaskInventoryItem taskItem = new TaskInventoryItem();
1783
1784 taskItem.ItemID = new UUID((Guid)inventoryRow["itemID"]);
1785 taskItem.ParentPartID = new UUID((Guid)inventoryRow["primID"]);
1786 taskItem.AssetID = new UUID((Guid)inventoryRow["assetID"]);
1787 taskItem.ParentID = new UUID((Guid)inventoryRow["parentFolderID"]);
1788
1789 taskItem.InvType = Convert.ToInt32(inventoryRow["invType"]);
1790 taskItem.Type = Convert.ToInt32(inventoryRow["assetType"]);
1791
1792 taskItem.Name = (string)inventoryRow["name"];
1793 taskItem.Description = (string)inventoryRow["description"];
1794 taskItem.CreationDate = Convert.ToUInt32(inventoryRow["creationDate"]);
1795 //taskItem.creatorID = new UUID((Guid)inventoryRow["creatorID"]);
1796 taskItem.CreatorIdentification = (string)inventoryRow["creatorID"].ToString();
1797 taskItem.OwnerID = new UUID((Guid)inventoryRow["ownerID"]);
1798 taskItem.LastOwnerID = new UUID((Guid)inventoryRow["lastOwnerID"]);
1799 taskItem.GroupID = new UUID((Guid)inventoryRow["groupID"]);
1800
1801 taskItem.NextPermissions = Convert.ToUInt32(inventoryRow["nextPermissions"]);
1802 taskItem.CurrentPermissions = Convert.ToUInt32(inventoryRow["currentPermissions"]);
1803 taskItem.BasePermissions = Convert.ToUInt32(inventoryRow["basePermissions"]);
1804 taskItem.EveryonePermissions = Convert.ToUInt32(inventoryRow["everyonePermissions"]);
1805 taskItem.GroupPermissions = Convert.ToUInt32(inventoryRow["groupPermissions"]);
1806 taskItem.Flags = Convert.ToUInt32(inventoryRow["flags"]);
1807
1808 return taskItem;
1809 }
1810
1811 #endregion
1812
1813 #region Create parameters methods
1814
1815 /// <summary>
1816 /// Creates the prim inventory parameters.
1817 /// </summary>
1818 /// <param name="taskItem">item in inventory.</param>
1819 /// <returns></returns>
1820 private NpgsqlParameter[] CreatePrimInventoryParameters(TaskInventoryItem taskItem)
1821 {
1822 List<NpgsqlParameter> parameters = new List<NpgsqlParameter>();
1823
1824 parameters.Add(_Database.CreateParameter("itemID", taskItem.ItemID));
1825 parameters.Add(_Database.CreateParameter("primID", taskItem.ParentPartID));
1826 parameters.Add(_Database.CreateParameter("assetID", taskItem.AssetID));
1827 parameters.Add(_Database.CreateParameter("parentFolderID", taskItem.ParentID));
1828 parameters.Add(_Database.CreateParameter("invType", taskItem.InvType));
1829 parameters.Add(_Database.CreateParameter("assetType", taskItem.Type));
1830
1831 parameters.Add(_Database.CreateParameter("name", taskItem.Name));
1832 parameters.Add(_Database.CreateParameter("description", taskItem.Description));
1833 parameters.Add(_Database.CreateParameter("creationDate", taskItem.CreationDate));
1834 parameters.Add(_Database.CreateParameter("creatorID", taskItem.CreatorID));
1835 parameters.Add(_Database.CreateParameter("ownerID", taskItem.OwnerID));
1836 parameters.Add(_Database.CreateParameter("lastOwnerID", taskItem.LastOwnerID));
1837 parameters.Add(_Database.CreateParameter("groupID", taskItem.GroupID));
1838 parameters.Add(_Database.CreateParameter("nextPermissions", taskItem.NextPermissions));
1839 parameters.Add(_Database.CreateParameter("currentPermissions", taskItem.CurrentPermissions));
1840 parameters.Add(_Database.CreateParameter("basePermissions", taskItem.BasePermissions));
1841 parameters.Add(_Database.CreateParameter("everyonePermissions", taskItem.EveryonePermissions));
1842 parameters.Add(_Database.CreateParameter("groupPermissions", taskItem.GroupPermissions));
1843 parameters.Add(_Database.CreateParameter("flags", taskItem.Flags));
1844
1845 return parameters.ToArray();
1846 }
1847
1848 /// <summary>
1849 /// Creates the region setting parameters.
1850 /// </summary>
1851 /// <param name="settings">regionsettings.</param>
1852 /// <returns></returns>
1853 private NpgsqlParameter[] CreateRegionSettingParameters(RegionSettings settings)
1854 {
1855 List<NpgsqlParameter> parameters = new List<NpgsqlParameter>();
1856
1857 parameters.Add(_Database.CreateParameter("regionUUID", settings.RegionUUID));
1858 parameters.Add(_Database.CreateParameter("block_terraform", settings.BlockTerraform));
1859 parameters.Add(_Database.CreateParameter("block_fly", settings.BlockFly));
1860 parameters.Add(_Database.CreateParameter("allow_damage", settings.AllowDamage));
1861 parameters.Add(_Database.CreateParameter("restrict_pushing", settings.RestrictPushing));
1862 parameters.Add(_Database.CreateParameter("allow_land_resell", settings.AllowLandResell));
1863 parameters.Add(_Database.CreateParameter("allow_land_join_divide", settings.AllowLandJoinDivide));
1864 parameters.Add(_Database.CreateParameter("block_show_in_search", settings.BlockShowInSearch));
1865 parameters.Add(_Database.CreateParameter("agent_limit", settings.AgentLimit));
1866 parameters.Add(_Database.CreateParameter("object_bonus", settings.ObjectBonus));
1867 parameters.Add(_Database.CreateParameter("maturity", settings.Maturity));
1868 parameters.Add(_Database.CreateParameter("disable_scripts", settings.DisableScripts));
1869 parameters.Add(_Database.CreateParameter("disable_collisions", settings.DisableCollisions));
1870 parameters.Add(_Database.CreateParameter("disable_physics", settings.DisablePhysics));
1871 parameters.Add(_Database.CreateParameter("terrain_texture_1", settings.TerrainTexture1));
1872 parameters.Add(_Database.CreateParameter("terrain_texture_2", settings.TerrainTexture2));
1873 parameters.Add(_Database.CreateParameter("terrain_texture_3", settings.TerrainTexture3));
1874 parameters.Add(_Database.CreateParameter("terrain_texture_4", settings.TerrainTexture4));
1875 parameters.Add(_Database.CreateParameter("elevation_1_nw", settings.Elevation1NW));
1876 parameters.Add(_Database.CreateParameter("elevation_2_nw", settings.Elevation2NW));
1877 parameters.Add(_Database.CreateParameter("elevation_1_ne", settings.Elevation1NE));
1878 parameters.Add(_Database.CreateParameter("elevation_2_ne", settings.Elevation2NE));
1879 parameters.Add(_Database.CreateParameter("elevation_1_se", settings.Elevation1SE));
1880 parameters.Add(_Database.CreateParameter("elevation_2_se", settings.Elevation2SE));
1881 parameters.Add(_Database.CreateParameter("elevation_1_sw", settings.Elevation1SW));
1882 parameters.Add(_Database.CreateParameter("elevation_2_sw", settings.Elevation2SW));
1883 parameters.Add(_Database.CreateParameter("water_height", settings.WaterHeight));
1884 parameters.Add(_Database.CreateParameter("terrain_raise_limit", settings.TerrainRaiseLimit));
1885 parameters.Add(_Database.CreateParameter("terrain_lower_limit", settings.TerrainLowerLimit));
1886 parameters.Add(_Database.CreateParameter("use_estate_sun", settings.UseEstateSun));
1887 parameters.Add(_Database.CreateParameter("Sandbox", settings.Sandbox));
1888 parameters.Add(_Database.CreateParameter("fixed_sun", settings.FixedSun));
1889 parameters.Add(_Database.CreateParameter("sun_position", settings.SunPosition));
1890 parameters.Add(_Database.CreateParameter("sunvectorx", settings.SunVector.X));
1891 parameters.Add(_Database.CreateParameter("sunvectory", settings.SunVector.Y));
1892 parameters.Add(_Database.CreateParameter("sunvectorz", settings.SunVector.Z));
1893 parameters.Add(_Database.CreateParameter("covenant", settings.Covenant));
1894 parameters.Add(_Database.CreateParameter("covenant_datetime", settings.CovenantChangedDateTime));
1895 parameters.Add(_Database.CreateParameter("Loaded_Creation_DateTime", settings.LoadedCreationDateTime));
1896 parameters.Add(_Database.CreateParameter("Loaded_Creation_ID", settings.LoadedCreationID));
1897 parameters.Add(_Database.CreateParameter("TerrainImageID", settings.TerrainImageID));
1898 parameters.Add(_Database.CreateParameter("ParcelImageID", settings.ParcelImageID));
1899 parameters.Add(_Database.CreateParameter("TelehubObject", settings.TelehubObject));
1900
1901 return parameters.ToArray();
1902 }
1903
1904 /// <summary>
1905 /// Creates the land parameters.
1906 /// </summary>
1907 /// <param name="land">land parameters.</param>
1908 /// <param name="regionUUID">region UUID.</param>
1909 /// <returns></returns>
1910 private NpgsqlParameter[] CreateLandParameters(LandData land, UUID regionUUID)
1911 {
1912 List<NpgsqlParameter> parameters = new List<NpgsqlParameter>();
1913
1914 parameters.Add(_Database.CreateParameter("UUID", land.GlobalID));
1915 parameters.Add(_Database.CreateParameter("RegionUUID", regionUUID));
1916 parameters.Add(_Database.CreateParameter("LocalLandID", land.LocalID));
1917
1918 // Bitmap is a byte[512]
1919 parameters.Add(_Database.CreateParameter("Bitmap", land.Bitmap));
1920
1921 parameters.Add(_Database.CreateParameter("Name", land.Name));
1922 parameters.Add(_Database.CreateParameter("Description", land.Description));
1923 parameters.Add(_Database.CreateParameter("OwnerUUID", land.OwnerID));
1924 parameters.Add(_Database.CreateParameter("IsGroupOwned", land.IsGroupOwned));
1925 parameters.Add(_Database.CreateParameter("Area", land.Area));
1926 parameters.Add(_Database.CreateParameter("AuctionID", land.AuctionID)); //Unemplemented
1927 parameters.Add(_Database.CreateParameter("Category", (int)land.Category)); //Enum libsecondlife.Parcel.ParcelCategory
1928 parameters.Add(_Database.CreateParameter("ClaimDate", land.ClaimDate));
1929 parameters.Add(_Database.CreateParameter("ClaimPrice", land.ClaimPrice));
1930 parameters.Add(_Database.CreateParameter("GroupUUID", land.GroupID));
1931 parameters.Add(_Database.CreateParameter("SalePrice", land.SalePrice));
1932 parameters.Add(_Database.CreateParameter("LandStatus", (int)land.Status)); //Enum. libsecondlife.Parcel.ParcelStatus
1933 parameters.Add(_Database.CreateParameter("LandFlags", land.Flags));
1934 parameters.Add(_Database.CreateParameter("LandingType", Convert.ToInt32( land.LandingType) ));
1935 parameters.Add(_Database.CreateParameter("MediaAutoScale", Convert.ToInt32( land.MediaAutoScale )));
1936 parameters.Add(_Database.CreateParameter("MediaTextureUUID", land.MediaID));
1937 parameters.Add(_Database.CreateParameter("MediaURL", land.MediaURL));
1938 parameters.Add(_Database.CreateParameter("MusicURL", land.MusicURL));
1939 parameters.Add(_Database.CreateParameter("PassHours", land.PassHours));
1940 parameters.Add(_Database.CreateParameter("PassPrice", land.PassPrice));
1941 parameters.Add(_Database.CreateParameter("SnapshotUUID", land.SnapshotID));
1942 parameters.Add(_Database.CreateParameter("UserLocationX", land.UserLocation.X));
1943 parameters.Add(_Database.CreateParameter("UserLocationY", land.UserLocation.Y));
1944 parameters.Add(_Database.CreateParameter("UserLocationZ", land.UserLocation.Z));
1945 parameters.Add(_Database.CreateParameter("UserLookAtX", land.UserLookAt.X));
1946 parameters.Add(_Database.CreateParameter("UserLookAtY", land.UserLookAt.Y));
1947 parameters.Add(_Database.CreateParameter("UserLookAtZ", land.UserLookAt.Z));
1948 parameters.Add(_Database.CreateParameter("AuthBuyerID", land.AuthBuyerID));
1949 parameters.Add(_Database.CreateParameter("OtherCleanTime", land.OtherCleanTime));
1950
1951 return parameters.ToArray();
1952 }
1953
1954 /// <summary>
1955 /// Creates the land access parameters.
1956 /// </summary>
1957 /// <param name="parcelAccessEntry">parcel access entry.</param>
1958 /// <param name="parcelID">parcel ID.</param>
1959 /// <returns></returns>
1960 private NpgsqlParameter[] CreateLandAccessParameters(LandAccessEntry parcelAccessEntry, UUID parcelID)
1961 {
1962 List<NpgsqlParameter> parameters = new List<NpgsqlParameter>();
1963
1964 parameters.Add(_Database.CreateParameter("LandUUID", parcelID));
1965 parameters.Add(_Database.CreateParameter("AccessUUID", parcelAccessEntry.AgentID));
1966 parameters.Add(_Database.CreateParameter("Flags", parcelAccessEntry.Flags));
1967 parameters.Add(_Database.CreateParameter("Expires", parcelAccessEntry.Expires));
1968
1969 return parameters.ToArray();
1970 }
1971
1972 /// <summary>
1973 /// Creates the prim parameters for storing in DB.
1974 /// </summary>
1975 /// <param name="prim">Basic data of SceneObjectpart prim.</param>
1976 /// <param name="sceneGroupID">The scenegroup ID.</param>
1977 /// <param name="regionUUID">The region ID.</param>
1978 /// <returns></returns>
1979 private NpgsqlParameter[] CreatePrimParameters(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID)
1980 {
1981 List<NpgsqlParameter> parameters = new List<NpgsqlParameter>();
1982
1983 parameters.Add(_Database.CreateParameter("UUID", prim.UUID));
1984 parameters.Add(_Database.CreateParameter("RegionUUID", regionUUID));
1985 parameters.Add(_Database.CreateParameter("CreationDate", prim.CreationDate));
1986 parameters.Add(_Database.CreateParameter("Name", prim.Name));
1987 parameters.Add(_Database.CreateParameter("SceneGroupID", sceneGroupID));
1988 // the UUID of the root part for this SceneObjectGroup
1989 // various text fields
1990 parameters.Add(_Database.CreateParameter("Text", prim.Text));
1991 parameters.Add(_Database.CreateParameter("ColorR", prim.Color.R));
1992 parameters.Add(_Database.CreateParameter("ColorG", prim.Color.G));
1993 parameters.Add(_Database.CreateParameter("ColorB", prim.Color.B));
1994 parameters.Add(_Database.CreateParameter("ColorA", prim.Color.A));
1995 parameters.Add(_Database.CreateParameter("Description", prim.Description));
1996 parameters.Add(_Database.CreateParameter("SitName", prim.SitName));
1997 parameters.Add(_Database.CreateParameter("TouchName", prim.TouchName));
1998 // permissions
1999 parameters.Add(_Database.CreateParameter("ObjectFlags", (uint)prim.Flags));
2000 parameters.Add(_Database.CreateParameter("CreatorID", prim.CreatorID));
2001 parameters.Add(_Database.CreateParameter("OwnerID", prim.OwnerID));
2002 parameters.Add(_Database.CreateParameter("GroupID", prim.GroupID));
2003 parameters.Add(_Database.CreateParameter("LastOwnerID", prim.LastOwnerID));
2004 parameters.Add(_Database.CreateParameter("OwnerMask", prim.OwnerMask));
2005 parameters.Add(_Database.CreateParameter("NextOwnerMask", prim.NextOwnerMask));
2006 parameters.Add(_Database.CreateParameter("GroupMask", prim.GroupMask));
2007 parameters.Add(_Database.CreateParameter("EveryoneMask", prim.EveryoneMask));
2008 parameters.Add(_Database.CreateParameter("BaseMask", prim.BaseMask));
2009 // vectors
2010 parameters.Add(_Database.CreateParameter("PositionX", prim.OffsetPosition.X));
2011 parameters.Add(_Database.CreateParameter("PositionY", prim.OffsetPosition.Y));
2012 parameters.Add(_Database.CreateParameter("PositionZ", prim.OffsetPosition.Z));
2013 parameters.Add(_Database.CreateParameter("GroupPositionX", prim.GroupPosition.X));
2014 parameters.Add(_Database.CreateParameter("GroupPositionY", prim.GroupPosition.Y));
2015 parameters.Add(_Database.CreateParameter("GroupPositionZ", prim.GroupPosition.Z));
2016 parameters.Add(_Database.CreateParameter("VelocityX", prim.Velocity.X));
2017 parameters.Add(_Database.CreateParameter("VelocityY", prim.Velocity.Y));
2018 parameters.Add(_Database.CreateParameter("VelocityZ", prim.Velocity.Z));
2019 parameters.Add(_Database.CreateParameter("AngularVelocityX", prim.AngularVelocity.X));
2020 parameters.Add(_Database.CreateParameter("AngularVelocityY", prim.AngularVelocity.Y));
2021 parameters.Add(_Database.CreateParameter("AngularVelocityZ", prim.AngularVelocity.Z));
2022 parameters.Add(_Database.CreateParameter("AccelerationX", prim.Acceleration.X));
2023 parameters.Add(_Database.CreateParameter("AccelerationY", prim.Acceleration.Y));
2024 parameters.Add(_Database.CreateParameter("AccelerationZ", prim.Acceleration.Z));
2025 // quaternions
2026 parameters.Add(_Database.CreateParameter("RotationX", prim.RotationOffset.X));
2027 parameters.Add(_Database.CreateParameter("RotationY", prim.RotationOffset.Y));
2028 parameters.Add(_Database.CreateParameter("RotationZ", prim.RotationOffset.Z));
2029 parameters.Add(_Database.CreateParameter("RotationW", prim.RotationOffset.W));
2030
2031 // Sit target
2032 Vector3 sitTargetPos = prim.SitTargetPositionLL;
2033 parameters.Add(_Database.CreateParameter("SitTargetOffsetX", sitTargetPos.X));
2034 parameters.Add(_Database.CreateParameter("SitTargetOffsetY", sitTargetPos.Y));
2035 parameters.Add(_Database.CreateParameter("SitTargetOffsetZ", sitTargetPos.Z));
2036
2037 Quaternion sitTargetOrient = prim.SitTargetOrientationLL;
2038 parameters.Add(_Database.CreateParameter("SitTargetOrientW", sitTargetOrient.W));
2039 parameters.Add(_Database.CreateParameter("SitTargetOrientX", sitTargetOrient.X));
2040 parameters.Add(_Database.CreateParameter("SitTargetOrientY", sitTargetOrient.Y));
2041 parameters.Add(_Database.CreateParameter("SitTargetOrientZ", sitTargetOrient.Z));
2042
2043 parameters.Add(_Database.CreateParameter("PayPrice", prim.PayPrice[0]));
2044 parameters.Add(_Database.CreateParameter("PayButton1", prim.PayPrice[1]));
2045 parameters.Add(_Database.CreateParameter("PayButton2", prim.PayPrice[2]));
2046 parameters.Add(_Database.CreateParameter("PayButton3", prim.PayPrice[3]));
2047 parameters.Add(_Database.CreateParameter("PayButton4", prim.PayPrice[4]));
2048
2049 if ((prim.SoundFlags & 1) != 0) // Looped
2050 {
2051 parameters.Add(_Database.CreateParameter("LoopedSound", prim.Sound));
2052 parameters.Add(_Database.CreateParameter("LoopedSoundGain", prim.SoundGain));
2053 }
2054 else
2055 {
2056 parameters.Add(_Database.CreateParameter("LoopedSound", UUID.Zero));
2057 parameters.Add(_Database.CreateParameter("LoopedSoundGain", 0.0f));
2058 }
2059
2060 parameters.Add(_Database.CreateParameter("TextureAnimation", prim.TextureAnimation));
2061 parameters.Add(_Database.CreateParameter("ParticleSystem", prim.ParticleSystem));
2062
2063 parameters.Add(_Database.CreateParameter("OmegaX", prim.AngularVelocity.X));
2064 parameters.Add(_Database.CreateParameter("OmegaY", prim.AngularVelocity.Y));
2065 parameters.Add(_Database.CreateParameter("OmegaZ", prim.AngularVelocity.Z));
2066
2067 parameters.Add(_Database.CreateParameter("CameraEyeOffsetX", prim.GetCameraEyeOffset().X));
2068 parameters.Add(_Database.CreateParameter("CameraEyeOffsetY", prim.GetCameraEyeOffset().Y));
2069 parameters.Add(_Database.CreateParameter("CameraEyeOffsetZ", prim.GetCameraEyeOffset().Z));
2070
2071 parameters.Add(_Database.CreateParameter("CameraAtOffsetX", prim.GetCameraAtOffset().X));
2072 parameters.Add(_Database.CreateParameter("CameraAtOffsetY", prim.GetCameraAtOffset().Y));
2073 parameters.Add(_Database.CreateParameter("CameraAtOffsetZ", prim.GetCameraAtOffset().Z));
2074
2075 if (prim.GetForceMouselook())
2076 parameters.Add(_Database.CreateParameter("ForceMouselook", 1));
2077 else
2078 parameters.Add(_Database.CreateParameter("ForceMouselook", 0));
2079
2080 parameters.Add(_Database.CreateParameter("ScriptAccessPin", prim.ScriptAccessPin));
2081
2082 if (prim.AllowedDrop)
2083 parameters.Add(_Database.CreateParameter("AllowedDrop", 1));
2084 else
2085 parameters.Add(_Database.CreateParameter("AllowedDrop", 0));
2086
2087 if (prim.DIE_AT_EDGE)
2088 parameters.Add(_Database.CreateParameter("DieAtEdge", 1));
2089 else
2090 parameters.Add(_Database.CreateParameter("DieAtEdge", 0));
2091
2092 parameters.Add(_Database.CreateParameter("SalePrice", prim.SalePrice));
2093 parameters.Add(_Database.CreateParameter("SaleType", prim.ObjectSaleType));
2094
2095 byte clickAction = prim.ClickAction;
2096 parameters.Add(_Database.CreateParameter("ClickAction", clickAction));
2097
2098 parameters.Add(_Database.CreateParameter("Material", prim.Material));
2099
2100 parameters.Add(_Database.CreateParameter("CollisionSound", prim.CollisionSound));
2101 parameters.Add(_Database.CreateParameter("CollisionSoundVolume", prim.CollisionSoundVolume));
2102
2103 parameters.Add(_Database.CreateParameter("PassTouches", prim.PassTouches));
2104
2105 parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum));
2106 parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl));
2107
2108 if (prim.DynAttrs.CountNamespaces > 0)
2109 parameters.Add(_Database.CreateParameter("DynAttrs", prim.DynAttrs.ToXml()));
2110 else
2111 parameters.Add(_Database.CreateParameter("DynAttrs", null));
2112
2113 parameters.Add(_Database.CreateParameter("PhysicsShapeType", prim.PhysicsShapeType));
2114 parameters.Add(_Database.CreateParameter("Density", (double)prim.Density));
2115 parameters.Add(_Database.CreateParameter("GravityModifier", (double)prim.GravityModifier));
2116 parameters.Add(_Database.CreateParameter("Friction", (double)prim.Friction));
2117 parameters.Add(_Database.CreateParameter("Restitution", (double)prim.Restitution));
2118
2119 return parameters.ToArray();
2120 }
2121
2122 /// <summary>
2123 /// Creates the primshape parameters for stroing in DB.
2124 /// </summary>
2125 /// <param name="prim">Basic data of SceneObjectpart prim.</param>
2126 /// <param name="sceneGroupID">The scene group ID.</param>
2127 /// <param name="regionUUID">The region UUID.</param>
2128 /// <returns></returns>
2129 private NpgsqlParameter[] CreatePrimShapeParameters(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID)
2130 {
2131 List<NpgsqlParameter> parameters = new List<NpgsqlParameter>();
2132
2133 PrimitiveBaseShape s = prim.Shape;
2134 parameters.Add(_Database.CreateParameter("UUID", prim.UUID));
2135 // shape is an enum
2136 parameters.Add(_Database.CreateParameter("Shape", 0));
2137 // vectors
2138 parameters.Add(_Database.CreateParameter("ScaleX", s.Scale.X));
2139 parameters.Add(_Database.CreateParameter("ScaleY", s.Scale.Y));
2140 parameters.Add(_Database.CreateParameter("ScaleZ", s.Scale.Z));
2141 // paths
2142 parameters.Add(_Database.CreateParameter("PCode", s.PCode));
2143 parameters.Add(_Database.CreateParameter("PathBegin", s.PathBegin));
2144 parameters.Add(_Database.CreateParameter("PathEnd", s.PathEnd));
2145 parameters.Add(_Database.CreateParameter("PathScaleX", s.PathScaleX));
2146 parameters.Add(_Database.CreateParameter("PathScaleY", s.PathScaleY));
2147 parameters.Add(_Database.CreateParameter("PathShearX", s.PathShearX));
2148 parameters.Add(_Database.CreateParameter("PathShearY", s.PathShearY));
2149 parameters.Add(_Database.CreateParameter("PathSkew", s.PathSkew));
2150 parameters.Add(_Database.CreateParameter("PathCurve", s.PathCurve));
2151 parameters.Add(_Database.CreateParameter("PathRadiusOffset", s.PathRadiusOffset));
2152 parameters.Add(_Database.CreateParameter("PathRevolutions", s.PathRevolutions));
2153 parameters.Add(_Database.CreateParameter("PathTaperX", s.PathTaperX));
2154 parameters.Add(_Database.CreateParameter("PathTaperY", s.PathTaperY));
2155 parameters.Add(_Database.CreateParameter("PathTwist", s.PathTwist));
2156 parameters.Add(_Database.CreateParameter("PathTwistBegin", s.PathTwistBegin));
2157 // profile
2158 parameters.Add(_Database.CreateParameter("ProfileBegin", s.ProfileBegin));
2159 parameters.Add(_Database.CreateParameter("ProfileEnd", s.ProfileEnd));
2160 parameters.Add(_Database.CreateParameter("ProfileCurve", s.ProfileCurve));
2161 parameters.Add(_Database.CreateParameter("ProfileHollow", s.ProfileHollow));
2162 parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry));
2163 parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams));
2164 parameters.Add(_Database.CreateParameter("State", s.State));
2165
2166 if (null == s.Media)
2167 {
2168 parameters.Add(_Database.CreateParameter("Media", DBNull.Value));
2169 }
2170 else
2171 {
2172 parameters.Add(_Database.CreateParameter("Media", s.Media.ToXml()));
2173 }
2174
2175 return parameters.ToArray();
2176 }
2177
2178 #endregion
2179
2180 #endregion
2181
2182 private void LoadSpawnPoints(RegionSettings rs)
2183 {
2184 rs.ClearSpawnPoints();
2185
2186 string sql = @"SELECT ""Yaw"", ""Pitch"", ""Distance"" FROM spawn_points WHERE ""RegionUUID"" = :RegionUUID";
2187
2188 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
2189 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
2190 {
2191 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", rs.RegionUUID));
2192 conn.Open();
2193 using (NpgsqlDataReader reader = cmd.ExecuteReader())
2194 {
2195 if (reader.Read())
2196 {
2197 SpawnPoint sp = new SpawnPoint();
2198
2199 sp.Yaw = (float)reader["Yaw"];
2200 sp.Pitch = (float)reader["Pitch"];
2201 sp.Distance = (float)reader["Distance"];
2202
2203 rs.AddSpawnPoint(sp);
2204 }
2205 }
2206 }
2207 }
2208
2209 private void SaveSpawnPoints(RegionSettings rs)
2210 {
2211 string sql = @"DELETE FROM spawn_points WHERE ""RegionUUID"" = :RegionUUID";
2212 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
2213 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
2214 {
2215 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", rs.RegionUUID));
2216 conn.Open();
2217 cmd.ExecuteNonQuery();
2218 }
2219 foreach (SpawnPoint p in rs.SpawnPoints())
2220 {
2221 sql = @"INSERT INTO spawn_points (""RegionUUID"", ""Yaw"", ""Pitch"", ""Distance"") VALUES (:RegionUUID, :Yaw, :Pitch, :Distance)";
2222 using (NpgsqlConnection conn = new NpgsqlConnection(m_connectionString))
2223 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
2224 {
2225 cmd.Parameters.Add(_Database.CreateParameter("RegionUUID", rs.RegionUUID));
2226 cmd.Parameters.Add(_Database.CreateParameter("Yaw", p.Yaw));
2227 cmd.Parameters.Add(_Database.CreateParameter("Pitch", p.Pitch));
2228 cmd.Parameters.Add(_Database.CreateParameter("Distance", p.Distance));
2229 conn.Open();
2230 cmd.ExecuteNonQuery();
2231 }
2232 }
2233 }
2234
2235 public UUID[] GetObjectIDs(UUID regionID)
2236 {
2237 return new UUID[0];
2238 }
2239
2240 public void SaveExtra(UUID regionID, string name, string value)
2241 {
2242 }
2243
2244 public void RemoveExtra(UUID regionID, string name)
2245 {
2246 }
2247
2248 public Dictionary<string, string> GetExtra(UUID regionID)
2249 {
2250 return null;
2251 }
2252 }
2253}
diff --git a/OpenSim/Data/PGSQL/PGSQLUserAccountData.cs b/OpenSim/Data/PGSQL/PGSQLUserAccountData.cs
new file mode 100644
index 0000000..a5868fe
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLUserAccountData.cs
@@ -0,0 +1,330 @@
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.Data;
32using OpenMetaverse;
33using OpenSim.Framework;
34using System.Text;
35using Npgsql;
36using log4net;
37using System.Reflection;
38
39namespace OpenSim.Data.PGSQL
40{
41 public class PGSQLUserAccountData : PGSQLGenericTableHandler<UserAccountData>,IUserAccountData
42 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45
46 public PGSQLUserAccountData(string connectionString, string realm) :
47 base(connectionString, realm, "UserAccount")
48 {
49 }
50
51 /*
52 private string m_Realm;
53 private List<string> m_ColumnNames = null;
54 private PGSQLManager m_database;
55
56 public PGSQLUserAccountData(string connectionString, string realm) :
57 base(connectionString, realm, "UserAccount")
58 {
59 m_Realm = realm;
60 m_ConnectionString = connectionString;
61 m_database = new PGSQLManager(connectionString);
62
63 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
64 {
65 conn.Open();
66 Migration m = new Migration(conn, GetType().Assembly, "UserAccount");
67 m.Update();
68 }
69 }
70 */
71 /*
72 public List<UserAccountData> Query(UUID principalID, UUID scopeID, string query)
73 {
74 return null;
75 }
76 */
77 /*
78 public override UserAccountData[] Get(string[] fields, string[] keys)
79 {
80 UserAccountData[] retUA = base.Get(fields,keys);
81
82 if (retUA.Length > 0)
83 {
84 Dictionary<string, string> data = retUA[0].Data;
85 Dictionary<string, string> data2 = new Dictionary<string, string>();
86
87 foreach (KeyValuePair<string,string> chave in data)
88 {
89 string s2 = chave.Key;
90
91 data2[s2] = chave.Value;
92
93 if (!m_FieldTypes.ContainsKey(chave.Key))
94 {
95 string tipo = "";
96 m_FieldTypes.TryGetValue(chave.Key, out tipo);
97 m_FieldTypes.Add(s2, tipo);
98 }
99 }
100 foreach (KeyValuePair<string, string> chave in data2)
101 {
102 if (!retUA[0].Data.ContainsKey(chave.Key))
103 retUA[0].Data.Add(chave.Key, chave.Value);
104 }
105 }
106
107 return retUA;
108 }
109 */
110 /*
111 public UserAccountData Get(UUID principalID, UUID scopeID)
112 {
113 UserAccountData ret = new UserAccountData();
114 ret.Data = new Dictionary<string, string>();
115
116 string sql = string.Format(@"select * from {0} where ""PrincipalID"" = :principalID", m_Realm);
117 if (scopeID != UUID.Zero)
118 sql += @" and ""ScopeID"" = :scopeID";
119
120 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
121 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
122 {
123 cmd.Parameters.Add(m_database.CreateParameter("principalID", principalID));
124 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
125
126 conn.Open();
127 using (NpgsqlDataReader result = cmd.ExecuteReader())
128 {
129 if (result.Read())
130 {
131 ret.PrincipalID = principalID;
132 UUID scope;
133 UUID.TryParse(result["scopeid"].ToString(), out scope);
134 ret.ScopeID = scope;
135
136 if (m_ColumnNames == null)
137 {
138 m_ColumnNames = new List<string>();
139
140 DataTable schemaTable = result.GetSchemaTable();
141 foreach (DataRow row in schemaTable.Rows)
142 m_ColumnNames.Add(row["ColumnName"].ToString());
143 }
144
145 foreach (string s in m_ColumnNames)
146 {
147 string s2 = s;
148 if (s2 == "uuid")
149 continue;
150 if (s2 == "scopeid")
151 continue;
152
153 ret.Data[s] = result[s].ToString();
154 }
155 return ret;
156 }
157 }
158 }
159 return null;
160 }
161
162
163 public override bool Store(UserAccountData data)
164 {
165 if (data.Data.ContainsKey("PrincipalID"))
166 data.Data.Remove("PrincipalID");
167 if (data.Data.ContainsKey("ScopeID"))
168 data.Data.Remove("ScopeID");
169
170 string[] fields = new List<string>(data.Data.Keys).ToArray();
171
172 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
173 using (NpgsqlCommand cmd = new NpgsqlCommand())
174 {
175 m_log.DebugFormat("[USER]: Try to update user {0} {1}", data.FirstName, data.LastName);
176
177 StringBuilder updateBuilder = new StringBuilder();
178 updateBuilder.AppendFormat("update {0} set ", m_Realm);
179 bool first = true;
180 foreach (string field in fields)
181 {
182 if (!first)
183 updateBuilder.Append(", ");
184 updateBuilder.AppendFormat("\"{0}\" = :{0}", field);
185
186 first = false;
187 if (m_FieldTypes.ContainsKey(field))
188 cmd.Parameters.Add(m_database.CreateParameter("" + field, data.Data[field], m_FieldTypes[field]));
189 else
190 cmd.Parameters.Add(m_database.CreateParameter("" + field, data.Data[field]));
191 }
192
193 updateBuilder.Append(" where \"PrincipalID\" = :principalID");
194
195 if (data.ScopeID != UUID.Zero)
196 updateBuilder.Append(" and \"ScopeID\" = :scopeID");
197
198 cmd.CommandText = updateBuilder.ToString();
199 cmd.Connection = conn;
200 cmd.Parameters.Add(m_database.CreateParameter("principalID", data.PrincipalID));
201 cmd.Parameters.Add(m_database.CreateParameter("scopeID", data.ScopeID));
202
203 m_log.DebugFormat("[USER]: SQL update user {0} ", cmd.CommandText);
204
205 conn.Open();
206
207 m_log.DebugFormat("[USER]: CON opened update user {0} ", cmd.CommandText);
208
209 int conta = 0;
210 try
211 {
212 conta = cmd.ExecuteNonQuery();
213 }
214 catch (Exception e){
215 m_log.ErrorFormat("[USER]: ERROR opened update user {0} ", e.Message);
216 }
217
218
219 if (conta < 1)
220 {
221 m_log.DebugFormat("[USER]: Try to insert user {0} {1}", data.FirstName, data.LastName);
222
223 StringBuilder insertBuilder = new StringBuilder();
224 insertBuilder.AppendFormat(@"insert into {0} (""PrincipalID"", ""ScopeID"", ""FirstName"", ""LastName"", """, m_Realm);
225 insertBuilder.Append(String.Join(@""", """, fields));
226 insertBuilder.Append(@""") values (:principalID, :scopeID, :FirstName, :LastName, :");
227 insertBuilder.Append(String.Join(", :", fields));
228 insertBuilder.Append(");");
229
230 cmd.Parameters.Add(m_database.CreateParameter("FirstName", data.FirstName));
231 cmd.Parameters.Add(m_database.CreateParameter("LastName", data.LastName));
232
233 cmd.CommandText = insertBuilder.ToString();
234
235 if (cmd.ExecuteNonQuery() < 1)
236 {
237 return false;
238 }
239 }
240 else
241 m_log.DebugFormat("[USER]: User {0} {1} exists", data.FirstName, data.LastName);
242 }
243 return true;
244 }
245
246
247 public bool Store(UserAccountData data, UUID principalID, string token)
248 {
249 return false;
250 }
251
252
253 public bool SetDataItem(UUID principalID, string item, string value)
254 {
255 string sql = string.Format(@"update {0} set {1} = :{1} where ""UUID"" = :UUID", m_Realm, item);
256 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
257 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
258 {
259 if (m_FieldTypes.ContainsKey(item))
260 cmd.Parameters.Add(m_database.CreateParameter("" + item, value, m_FieldTypes[item]));
261 else
262 cmd.Parameters.Add(m_database.CreateParameter("" + item, value));
263
264 cmd.Parameters.Add(m_database.CreateParameter("UUID", principalID));
265 conn.Open();
266
267 if (cmd.ExecuteNonQuery() > 0)
268 return true;
269 }
270 return false;
271 }
272 */
273 /*
274 public UserAccountData[] Get(string[] keys, string[] vals)
275 {
276 return null;
277 }
278 */
279
280 public UserAccountData[] GetUsers(UUID scopeID, string query)
281 {
282 string[] words = query.Split(new char[] { ' ' });
283
284 for (int i = 0; i < words.Length; i++)
285 {
286 if (words[i].Length < 3)
287 {
288 if (i != words.Length - 1)
289 Array.Copy(words, i + 1, words, i, words.Length - i - 1);
290 Array.Resize(ref words, words.Length - 1);
291 }
292 }
293
294 if (words.Length == 0)
295 return new UserAccountData[0];
296
297 if (words.Length > 2)
298 return new UserAccountData[0];
299
300 string sql = "";
301
302 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
303 using (NpgsqlCommand cmd = new NpgsqlCommand())
304 {
305 if (words.Length == 1)
306 {
307 sql = String.Format(@"select * from {0} where (""ScopeID""=:ScopeID or ""ScopeID""='00000000-0000-0000-0000-000000000000') and (""FirstName"" ilike :search or ""LastName"" ilike :search)", m_Realm);
308 cmd.Parameters.Add(m_database.CreateParameter("scopeID", scopeID));
309 cmd.Parameters.Add(m_database.CreateParameter("search", "%" + words[0] + "%"));
310 }
311 else
312 {
313 sql = String.Format(@"select * from {0} where (""ScopeID""=:ScopeID or ""ScopeID""='00000000-0000-0000-0000-000000000000') and (""FirstName"" ilike :searchFirst or ""LastName"" ilike :searchLast)", m_Realm);
314 cmd.Parameters.Add(m_database.CreateParameter("searchFirst", "%" + words[0] + "%"));
315 cmd.Parameters.Add(m_database.CreateParameter("searchLast", "%" + words[1] + "%"));
316 cmd.Parameters.Add(m_database.CreateParameter("ScopeID", scopeID.ToString()));
317 }
318 cmd.Connection = conn;
319 cmd.CommandText = sql;
320 conn.Open();
321 return DoQuery(cmd);
322 }
323 }
324
325 public UserAccountData[] GetUsersWhere(UUID scopeID, string where)
326 {
327 return null;
328 }
329 }
330}
diff --git a/OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs b/OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs
new file mode 100644
index 0000000..f4e41b4
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs
@@ -0,0 +1,1073 @@
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.Data;
30using System.Reflection;
31using OpenSim.Data;
32using OpenSim.Framework;
33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
35using log4net;
36using Npgsql;
37
38namespace OpenSim.Data.PGSQL
39{
40 public class UserProfilesData: IProfilesData
41 {
42 static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 #region Properites
45 string ConnectionString
46 {
47 get; set;
48 }
49
50 protected object Lock
51 {
52 get; set;
53 }
54
55 protected virtual Assembly Assembly
56 {
57 get { return GetType().Assembly; }
58 }
59
60 #endregion Properties
61
62 #region class Member Functions
63 public UserProfilesData(string connectionString)
64 {
65 ConnectionString = connectionString;
66 Init();
67 }
68
69 void Init()
70 {
71 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
72 {
73 dbcon.Open();
74
75 Migration m = new Migration(dbcon, Assembly, "UserProfiles");
76 m.Update();
77 }
78 }
79 #endregion Member Functions
80
81 #region Classifieds Queries
82 /// <summary>
83 /// Gets the classified records.
84 /// </summary>
85 /// <returns>
86 /// Array of classified records
87 /// </returns>
88 /// <param name='creatorId'>
89 /// Creator identifier.
90 /// </param>
91 public OSDArray GetClassifiedRecords(UUID creatorId)
92 {
93 OSDArray data = new OSDArray();
94
95 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
96 {
97 string query = @"SELECT ""classifieduuid"", ""name"" FROM classifieds WHERE ""creatoruuid"" = :Id";
98 dbcon.Open();
99 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
100 {
101 cmd.Parameters.AddWithValue("Id", creatorId);
102 using( NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.Default))
103 {
104 if(reader.HasRows)
105 {
106 while (reader.Read())
107 {
108 OSDMap n = new OSDMap();
109 UUID Id = UUID.Zero;
110
111 string Name = null;
112 try
113 {
114 UUID.TryParse(Convert.ToString( reader["classifieduuid"]), out Id);
115 Name = Convert.ToString(reader["name"]);
116 }
117 catch (Exception e)
118 {
119 m_log.DebugFormat("[PROFILES_DATA]" +
120 ": UserAccount exception {0}", e.Message);
121 }
122 n.Add("classifieduuid", OSD.FromUUID(Id));
123 n.Add("name", OSD.FromString(Name));
124 data.Add(n);
125 }
126 }
127 }
128 }
129 }
130 return data;
131 }
132
133 public bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result)
134 {
135 string query = @"INSERT INTO classifieds ( ""classifieduuid"",""creatoruuid"", ""creationdate"", ""expirationdate"", ""category"",
136 ""name"", ""description"", ""parceluuid"", ""parentestate"", ""snapshotuuid"", ""simname"",
137 ""posglobal"", ""parcelname"", ""classifiedflags"", ""priceforlisting"")
138 Select :ClassifiedId, :CreatorId, :CreatedDate, :ExpirationDate, :Category,
139 :Name, :Description, :ParcelId, :ParentEstate, :SnapshotId, :SimName
140 :GlobalPos, :ParcelName, :Flags, :ListingPrice
141 Where not exists( Select ""classifieduuid"" from classifieds where ""classifieduuid"" = :ClassifiedId );
142
143 update classifieds
144 set category =:Category,
145 expirationdate = :ExpirationDate,
146 name = :Name,
147 description = :Description,
148 parentestate = :ParentEstate,
149 posglobal = :GlobalPos,
150 parcelname = :ParcelName,
151 classifiedflags = :Flags,
152 priceforlisting = :ListingPrice,
153 snapshotuuid = :SnapshotId
154 where classifieduuid = :ClassifiedId ;
155 ";
156
157 if(string.IsNullOrEmpty(ad.ParcelName))
158 ad.ParcelName = "Unknown";
159 if(ad.ParcelId == null)
160 ad.ParcelId = UUID.Zero;
161 if(string.IsNullOrEmpty(ad.Description))
162 ad.Description = "No Description";
163
164 DateTime epoch = new DateTime(1970, 1, 1);
165 DateTime now = DateTime.Now;
166 TimeSpan epochnow = now - epoch;
167 TimeSpan duration;
168 DateTime expiration;
169 TimeSpan epochexp;
170
171 if(ad.Flags == 2)
172 {
173 duration = new TimeSpan(7,0,0,0);
174 expiration = now.Add(duration);
175 epochexp = expiration - epoch;
176 }
177 else
178 {
179 duration = new TimeSpan(365,0,0,0);
180 expiration = now.Add(duration);
181 epochexp = expiration - epoch;
182 }
183 ad.CreationDate = (int)epochnow.TotalSeconds;
184 ad.ExpirationDate = (int)epochexp.TotalSeconds;
185
186 try
187 {
188 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
189 {
190 dbcon.Open();
191 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
192 {
193 cmd.Parameters.AddWithValue("ClassifiedId", ad.ClassifiedId.ToString());
194 cmd.Parameters.AddWithValue("CreatorId", ad.CreatorId.ToString());
195 cmd.Parameters.AddWithValue("CreatedDate", ad.CreationDate.ToString());
196 cmd.Parameters.AddWithValue("ExpirationDate", ad.ExpirationDate.ToString());
197 cmd.Parameters.AddWithValue("Category", ad.Category.ToString());
198 cmd.Parameters.AddWithValue("Name", ad.Name.ToString());
199 cmd.Parameters.AddWithValue("Description", ad.Description.ToString());
200 cmd.Parameters.AddWithValue("ParcelId", ad.ParcelId.ToString());
201 cmd.Parameters.AddWithValue("ParentEstate", ad.ParentEstate.ToString());
202 cmd.Parameters.AddWithValue("SnapshotId", ad.SnapshotId.ToString ());
203 cmd.Parameters.AddWithValue("SimName", ad.SimName.ToString());
204 cmd.Parameters.AddWithValue("GlobalPos", ad.GlobalPos.ToString());
205 cmd.Parameters.AddWithValue("ParcelName", ad.ParcelName.ToString());
206 cmd.Parameters.AddWithValue("Flags", ad.Flags.ToString());
207 cmd.Parameters.AddWithValue("ListingPrice", ad.Price.ToString ());
208
209 cmd.ExecuteNonQuery();
210 }
211 }
212 }
213 catch (Exception e)
214 {
215 m_log.DebugFormat("[PROFILES_DATA]" +
216 ": ClassifiedesUpdate exception {0}", e.Message);
217 result = e.Message;
218 return false;
219 }
220 return true;
221 }
222
223
224 public bool DeleteClassifiedRecord(UUID recordId)
225 {
226 string query = string.Empty;
227
228 query = @"DELETE FROM classifieds WHERE classifieduuid = :ClasifiedId ;";
229
230 try
231 {
232 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
233 {
234 dbcon.Open();
235
236 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
237 {
238 cmd.Parameters.AddWithValue("ClassifiedId", recordId.ToString());
239
240 lock(Lock)
241 {
242 cmd.ExecuteNonQuery();
243 }
244 }
245 }
246 }
247 catch (Exception e)
248 {
249 m_log.DebugFormat("[PROFILES_DATA]" +
250 ": DeleteClassifiedRecord exception {0}", e.Message);
251 return false;
252 }
253 return true;
254 }
255
256 public bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result)
257 {
258 string query = string.Empty;
259
260 query += "SELECT * FROM classifieds WHERE ";
261 query += "classifieduuid = :AdId";
262
263 try
264 {
265 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
266 {
267 dbcon.Open();
268 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
269 {
270 cmd.Parameters.AddWithValue("AdId", ad.ClassifiedId.ToString());
271
272 using (NpgsqlDataReader reader = cmd.ExecuteReader())
273 {
274 if(reader.Read ())
275 {
276 ad.CreatorId = GetUUID(reader["creatoruuid"]);
277 ad.ParcelId = GetUUID(reader["parceluuid"]);
278 ad.SnapshotId = GetUUID(reader["snapshotuuid"]);
279 ad.CreationDate = Convert.ToInt32(reader["creationdate"]);
280 ad.ExpirationDate = Convert.ToInt32(reader["expirationdate"]);
281 ad.ParentEstate = Convert.ToInt32(reader["parentestate"]);
282 ad.Flags = (byte)Convert.ToInt16(reader["classifiedflags"]);
283 ad.Category = Convert.ToInt32(reader["category"]);
284 ad.Price = Convert.ToInt16(reader["priceforlisting"]);
285 ad.Name = reader["name"].ToString();
286 ad.Description = reader["description"].ToString();
287 ad.SimName = reader["simname"].ToString();
288 ad.GlobalPos = reader["posglobal"].ToString();
289 ad.ParcelName = reader["parcelname"].ToString();
290
291 }
292 }
293 }
294 dbcon.Close();
295 }
296 }
297 catch (Exception e)
298 {
299 m_log.DebugFormat("[PROFILES_DATA]" +
300 ": GetPickInfo exception {0}", e.Message);
301 }
302 return true;
303 }
304
305 public static UUID GetUUID( object uuidValue ) {
306
307 UUID ret = UUID.Zero;
308
309 UUID.TryParse(uuidValue.ToString(), out ret);
310
311 return ret;
312 }
313
314
315 #endregion Classifieds Queries
316
317 #region Picks Queries
318 public OSDArray GetAvatarPicks(UUID avatarId)
319 {
320 string query = string.Empty;
321
322 query += "SELECT \"pickuuid\",\"name\" FROM userpicks WHERE ";
323 query += "creatoruuid = :Id";
324 OSDArray data = new OSDArray();
325
326 try
327 {
328 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
329 {
330 dbcon.Open();
331 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
332 {
333 cmd.Parameters.AddWithValue("Id", avatarId.ToString());
334
335 using (NpgsqlDataReader reader = cmd.ExecuteReader())
336 {
337 if(reader.HasRows)
338 {
339 while (reader.Read())
340 {
341 OSDMap record = new OSDMap();
342
343 record.Add("pickuuid",OSD.FromString((string)reader["pickuuid"]));
344 record.Add("name",OSD.FromString((string)reader["name"]));
345 data.Add(record);
346 }
347 }
348 }
349 }
350 }
351 }
352 catch (Exception e)
353 {
354 m_log.DebugFormat("[PROFILES_DATA]" +
355 ": GetAvatarPicks exception {0}", e.Message);
356 }
357 return data;
358 }
359
360 public UserProfilePick GetPickInfo(UUID avatarId, UUID pickId)
361 {
362 string query = string.Empty;
363 UserProfilePick pick = new UserProfilePick();
364
365 query += "SELECT * FROM userpicks WHERE ";
366 query += "creatoruuid = :CreatorId AND ";
367 query += "pickuuid = :PickId";
368
369 try
370 {
371 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
372 {
373 dbcon.Open();
374 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
375 {
376 cmd.Parameters.AddWithValue("CreatorId", avatarId.ToString());
377 cmd.Parameters.AddWithValue("PickId", pickId.ToString());
378
379 using (NpgsqlDataReader reader = cmd.ExecuteReader())
380 {
381 if(reader.HasRows)
382 {
383 reader.Read();
384
385 string description = (string)reader["description"];
386
387 if (string.IsNullOrEmpty(description))
388 description = "No description given.";
389
390 UUID.TryParse((string)reader["pickuuid"], out pick.PickId);
391 UUID.TryParse((string)reader["creatoruuid"], out pick.CreatorId);
392 UUID.TryParse((string)reader["parceluuid"], out pick.ParcelId);
393 UUID.TryParse((string)reader["snapshotuuid"], out pick.SnapshotId);
394 pick.GlobalPos = (string)reader["posglobal"];
395 bool.TryParse((string)reader["toppick"], out pick.TopPick);
396 bool.TryParse((string)reader["enabled"], out pick.Enabled);
397 pick.Name = (string)reader["name"];
398 pick.Desc = description;
399 pick.User = (string)reader["user"];
400 pick.OriginalName = (string)reader["originalname"];
401 pick.SimName = (string)reader["simname"];
402 pick.SortOrder = (int)reader["sortorder"];
403 }
404 }
405 }
406 dbcon.Close();
407 }
408 }
409 catch (Exception e)
410 {
411 m_log.DebugFormat("[PROFILES_DATA]" +
412 ": GetPickInfo exception {0}", e.Message);
413 }
414 return pick;
415 }
416
417 public bool UpdatePicksRecord(UserProfilePick pick)
418 {
419 string query = string.Empty;
420
421 query = @"INSERT INTO userpicks VALUES ( :PickId, :CreatorId, :TopPick, :ParcelId,:Name, :Desc, :SnapshotId,:User,
422 :Original, :SimName, :GlobalPos, :SortOrder, :Enabled)
423 where not exists ( select pickid from userpicks where pickid = :pickid);
424
425 Update userpicks
426 set parceluuid = :ParcelId,
427 name = :Name,
428 description = :Desc,
429 snapshotuuid = :SnapshotId,
430 pickuuid = :PickId,
431 posglobal = :GlobalPos
432 where pickid = :PickId;
433 ";
434
435 try
436 {
437 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
438 {
439 dbcon.Open();
440 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
441 {
442 cmd.Parameters.AddWithValue("PickId", pick.PickId.ToString());
443 cmd.Parameters.AddWithValue("CreatorId", pick.CreatorId.ToString());
444 cmd.Parameters.AddWithValue("TopPick", pick.TopPick.ToString());
445 cmd.Parameters.AddWithValue("ParcelId", pick.ParcelId.ToString());
446 cmd.Parameters.AddWithValue("Name", pick.Name.ToString());
447 cmd.Parameters.AddWithValue("Desc", pick.Desc.ToString());
448 cmd.Parameters.AddWithValue("SnapshotId", pick.SnapshotId.ToString());
449 cmd.Parameters.AddWithValue("User", pick.User.ToString());
450 cmd.Parameters.AddWithValue("Original", pick.OriginalName.ToString());
451 cmd.Parameters.AddWithValue("SimName",pick.SimName.ToString());
452 cmd.Parameters.AddWithValue("GlobalPos", pick.GlobalPos);
453 cmd.Parameters.AddWithValue("SortOrder", pick.SortOrder.ToString ());
454 cmd.Parameters.AddWithValue("Enabled", pick.Enabled.ToString());
455
456 cmd.ExecuteNonQuery();
457 }
458 }
459 }
460 catch (Exception e)
461 {
462 m_log.DebugFormat("[PROFILES_DATA]" +
463 ": UpdateAvatarNotes exception {0}", e.Message);
464 return false;
465 }
466 return true;
467 }
468
469 public bool DeletePicksRecord(UUID pickId)
470 {
471 string query = string.Empty;
472
473 query += "DELETE FROM userpicks WHERE ";
474 query += "pickuuid = :PickId";
475
476 try
477 {
478 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
479 {
480 dbcon.Open();
481
482 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
483 {
484 cmd.Parameters.AddWithValue("PickId", pickId.ToString());
485
486 cmd.ExecuteNonQuery();
487 }
488 }
489 }
490 catch (Exception e)
491 {
492 m_log.DebugFormat("[PROFILES_DATA]" +
493 ": DeleteUserPickRecord exception {0}", e.Message);
494 return false;
495 }
496 return true;
497 }
498 #endregion Picks Queries
499
500 #region Avatar Notes Queries
501 public bool GetAvatarNotes(ref UserProfileNotes notes)
502 { // WIP
503 string query = string.Empty;
504
505 query += "SELECT \"notes\" FROM usernotes WHERE ";
506 query += "useruuid = :Id AND ";
507 query += "targetuuid = :TargetId";
508 OSDArray data = new OSDArray();
509
510 try
511 {
512 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
513 {
514 dbcon.Open();
515 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
516 {
517 cmd.Parameters.AddWithValue("Id", notes.UserId.ToString());
518 cmd.Parameters.AddWithValue("TargetId", notes.TargetId.ToString());
519
520 using (NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
521 {
522 if(reader.HasRows)
523 {
524 reader.Read();
525 notes.Notes = OSD.FromString((string)reader["notes"]);
526 }
527 }
528 }
529 }
530 }
531 catch (Exception e)
532 {
533 m_log.DebugFormat("[PROFILES_DATA]" +
534 ": GetAvatarNotes exception {0}", e.Message);
535 }
536 return true;
537 }
538
539 public bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result)
540 {
541 string query = string.Empty;
542 bool remove;
543
544 if(string.IsNullOrEmpty(note.Notes))
545 {
546 remove = true;
547 query += "DELETE FROM usernotes WHERE ";
548 query += "useruuid=:UserId AND ";
549 query += "targetuuid=:TargetId";
550 }
551 else
552 {
553 remove = false;
554 query = @"INSERT INTO usernotes VALUES ( :UserId, :TargetId, :Notes )
555 where not exists ( Select useruuid from usernotes where useruuid = :UserId and targetuuid = :TargetId );
556
557 update usernotes
558 set notes = :Notes
559 where useruuid = :UserId
560 and targetuuid = :TargetId;
561 ";
562 }
563
564 try
565 {
566 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
567 {
568 dbcon.Open();
569 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
570 {
571 if(!remove)
572 cmd.Parameters.AddWithValue("Notes", note.Notes);
573 cmd.Parameters.AddWithValue("TargetId", note.TargetId.ToString ());
574 cmd.Parameters.AddWithValue("UserId", note.UserId.ToString());
575
576 cmd.ExecuteNonQuery();
577 }
578 }
579 }
580 catch (Exception e)
581 {
582 m_log.DebugFormat("[PROFILES_DATA]" +
583 ": UpdateAvatarNotes exception {0}", e.Message);
584 return false;
585 }
586 return true;
587
588 }
589 #endregion Avatar Notes Queries
590
591 #region Avatar Properties
592 public bool GetAvatarProperties(ref UserProfileProperties props, ref string result)
593 {
594 string query = string.Empty;
595
596 query += "SELECT * FROM userprofile WHERE ";
597 query += "useruuid = :Id";
598
599 try
600 {
601 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
602 {
603 dbcon.Open();
604 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
605 {
606 cmd.Parameters.AddWithValue("Id", props.UserId.ToString());
607
608 using (NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
609 {
610 if(reader.HasRows)
611 {
612 m_log.DebugFormat("[PROFILES_DATA]" +
613 ": Getting data for {0}.", props.UserId);
614 reader.Read();
615 props.WebUrl = (string)reader["profileURL"];
616 UUID.TryParse((string)reader["profileImage"], out props.ImageId);
617 props.AboutText = (string)reader["profileAboutText"];
618 UUID.TryParse((string)reader["profileFirstImage"], out props.FirstLifeImageId);
619 props.FirstLifeText = (string)reader["profileFirstText"];
620 UUID.TryParse((string)reader["profilePartner"], out props.PartnerId);
621 props.WantToMask = (int)reader["profileWantToMask"];
622 props.WantToText = (string)reader["profileWantToText"];
623 props.SkillsMask = (int)reader["profileSkillsMask"];
624 props.SkillsText = (string)reader["profileSkillsText"];
625 props.Language = (string)reader["profileLanguages"];
626 }
627 else
628 {
629 m_log.DebugFormat("[PROFILES_DATA]" +
630 ": No data for {0}", props.UserId);
631
632 props.WebUrl = string.Empty;
633 props.ImageId = UUID.Zero;
634 props.AboutText = string.Empty;
635 props.FirstLifeImageId = UUID.Zero;
636 props.FirstLifeText = string.Empty;
637 props.PartnerId = UUID.Zero;
638 props.WantToMask = 0;
639 props.WantToText = string.Empty;
640 props.SkillsMask = 0;
641 props.SkillsText = string.Empty;
642 props.Language = string.Empty;
643 props.PublishProfile = false;
644 props.PublishMature = false;
645
646 query = "INSERT INTO userprofile (";
647 query += "useruuid, ";
648 query += "profilePartner, ";
649 query += "profileAllowPublish, ";
650 query += "profileMaturePublish, ";
651 query += "profileURL, ";
652 query += "profileWantToMask, ";
653 query += "profileWantToText, ";
654 query += "profileSkillsMask, ";
655 query += "profileSkillsText, ";
656 query += "profileLanguages, ";
657 query += "profileImage, ";
658 query += "profileAboutText, ";
659 query += "profileFirstImage, ";
660 query += "profileFirstText) VALUES (";
661 query += ":userId, ";
662 query += ":profilePartner, ";
663 query += ":profileAllowPublish, ";
664 query += ":profileMaturePublish, ";
665 query += ":profileURL, ";
666 query += ":profileWantToMask, ";
667 query += ":profileWantToText, ";
668 query += ":profileSkillsMask, ";
669 query += ":profileSkillsText, ";
670 query += ":profileLanguages, ";
671 query += ":profileImage, ";
672 query += ":profileAboutText, ";
673 query += ":profileFirstImage, ";
674 query += ":profileFirstText)";
675
676 dbcon.Close();
677 dbcon.Open();
678
679 using (NpgsqlCommand put = new NpgsqlCommand(query, dbcon))
680 {
681 put.Parameters.AddWithValue("userId", props.UserId.ToString());
682 put.Parameters.AddWithValue("profilePartner", props.PartnerId.ToString());
683 put.Parameters.AddWithValue("profileAllowPublish", props.PublishProfile);
684 put.Parameters.AddWithValue("profileMaturePublish", props.PublishMature);
685 put.Parameters.AddWithValue("profileURL", props.WebUrl);
686 put.Parameters.AddWithValue("profileWantToMask", props.WantToMask);
687 put.Parameters.AddWithValue("profileWantToText", props.WantToText);
688 put.Parameters.AddWithValue("profileSkillsMask", props.SkillsMask);
689 put.Parameters.AddWithValue("profileSkillsText", props.SkillsText);
690 put.Parameters.AddWithValue("profileLanguages", props.Language);
691 put.Parameters.AddWithValue("profileImage", props.ImageId.ToString());
692 put.Parameters.AddWithValue("profileAboutText", props.AboutText);
693 put.Parameters.AddWithValue("profileFirstImage", props.FirstLifeImageId.ToString());
694 put.Parameters.AddWithValue("profileFirstText", props.FirstLifeText);
695
696 put.ExecuteNonQuery();
697 }
698 }
699 }
700 }
701 }
702 }
703 catch (Exception e)
704 {
705 m_log.DebugFormat("[PROFILES_DATA]" +
706 ": Requst properties exception {0}", e.Message);
707 result = e.Message;
708 return false;
709 }
710 return true;
711 }
712
713 public bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result)
714 {
715 string query = string.Empty;
716
717 query += "UPDATE userprofile SET ";
718 query += "profileURL=:profileURL, ";
719 query += "profileImage=:image, ";
720 query += "profileAboutText=:abouttext,";
721 query += "profileFirstImage=:firstlifeimage,";
722 query += "profileFirstText=:firstlifetext ";
723 query += "WHERE useruuid=:uuid";
724
725 try
726 {
727 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
728 {
729 dbcon.Open();
730 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
731 {
732 cmd.Parameters.AddWithValue("profileURL", props.WebUrl);
733 cmd.Parameters.AddWithValue("image", props.ImageId.ToString());
734 cmd.Parameters.AddWithValue("abouttext", props.AboutText);
735 cmd.Parameters.AddWithValue("firstlifeimage", props.FirstLifeImageId.ToString());
736 cmd.Parameters.AddWithValue("firstlifetext", props.FirstLifeText);
737 cmd.Parameters.AddWithValue("uuid", props.UserId.ToString());
738
739 cmd.ExecuteNonQuery();
740 }
741 }
742 }
743 catch (Exception e)
744 {
745 m_log.DebugFormat("[PROFILES_DATA]" +
746 ": AgentPropertiesUpdate exception {0}", e.Message);
747
748 return false;
749 }
750 return true;
751 }
752 #endregion Avatar Properties
753
754 #region Avatar Interests
755 public bool UpdateAvatarInterests(UserProfileProperties up, ref string result)
756 {
757 string query = string.Empty;
758
759 query += "UPDATE userprofile SET ";
760 query += "profileWantToMask=:WantMask, ";
761 query += "profileWantToText=:WantText,";
762 query += "profileSkillsMask=:SkillsMask,";
763 query += "profileSkillsText=:SkillsText, ";
764 query += "profileLanguages=:Languages ";
765 query += "WHERE useruuid=:uuid";
766
767 try
768 {
769 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
770 {
771 dbcon.Open();
772 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
773 {
774 cmd.Parameters.AddWithValue("WantMask", up.WantToMask);
775 cmd.Parameters.AddWithValue("WantText", up.WantToText);
776 cmd.Parameters.AddWithValue("SkillsMask", up.SkillsMask);
777 cmd.Parameters.AddWithValue("SkillsText", up.SkillsText);
778 cmd.Parameters.AddWithValue("Languages", up.Language);
779 cmd.Parameters.AddWithValue("uuid", up.UserId.ToString());
780
781 cmd.ExecuteNonQuery();
782 }
783 }
784 }
785 catch (Exception e)
786 {
787 m_log.DebugFormat("[PROFILES_DATA]" +
788 ": AgentInterestsUpdate exception {0}", e.Message);
789 result = e.Message;
790 return false;
791 }
792 return true;
793 }
794 #endregion Avatar Interests
795
796 public OSDArray GetUserImageAssets(UUID avatarId)
797 {
798 OSDArray data = new OSDArray();
799 string query = "SELECT \"snapshotuuid\" FROM {0} WHERE \"creatoruuid\" = :Id";
800
801 // Get classified image assets
802
803
804 try
805 {
806 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
807 {
808 dbcon.Open();
809
810 using (NpgsqlCommand cmd = new NpgsqlCommand(string.Format (query,"\"classifieds\""), dbcon))
811 {
812 cmd.Parameters.AddWithValue("Id", avatarId.ToString());
813
814 using (NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
815 {
816 if(reader.HasRows)
817 {
818 while (reader.Read())
819 {
820 data.Add(new OSDString((string)reader["snapshotuuid"].ToString ()));
821 }
822 }
823 }
824 }
825
826 dbcon.Close();
827 dbcon.Open();
828
829 using (NpgsqlCommand cmd = new NpgsqlCommand(string.Format (query,"\"userpicks\""), dbcon))
830 {
831 cmd.Parameters.AddWithValue("Id", avatarId.ToString());
832
833 using (NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
834 {
835 if(reader.HasRows)
836 {
837 while (reader.Read())
838 {
839 data.Add(new OSDString((string)reader["snapshotuuid"].ToString ()));
840 }
841 }
842 }
843 }
844
845 dbcon.Close();
846 dbcon.Open();
847
848 query = "SELECT \"profileImage\", \"profileFirstImage\" FROM \"userprofile\" WHERE \"useruuid\" = :Id";
849
850 using (NpgsqlCommand cmd = new NpgsqlCommand(string.Format (query,"\"userpicks\""), dbcon))
851 {
852 cmd.Parameters.AddWithValue("Id", avatarId.ToString());
853
854 using (NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
855 {
856 if(reader.HasRows)
857 {
858 while (reader.Read())
859 {
860 data.Add(new OSDString((string)reader["profileImage"].ToString ()));
861 data.Add(new OSDString((string)reader["profileFirstImage"].ToString ()));
862 }
863 }
864 }
865 }
866 }
867 }
868 catch (Exception e)
869 {
870 m_log.DebugFormat("[PROFILES_DATA]" +
871 ": GetAvatarNotes exception {0}", e.Message);
872 }
873 return data;
874 }
875
876 #region User Preferences
877 public OSDArray GetUserPreferences(UUID avatarId)
878 {
879 string query = string.Empty;
880
881 query += "SELECT imviaemail,visible,email FROM ";
882 query += "usersettings WHERE ";
883 query += "useruuid = :Id";
884
885 OSDArray data = new OSDArray();
886
887 try
888 {
889 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
890 {
891 dbcon.Open();
892 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
893 {
894 cmd.Parameters.AddWithValue("Id", avatarId.ToString());
895
896 using (NpgsqlDataReader reader = cmd.ExecuteReader())
897 {
898 if(reader.HasRows)
899 {
900 reader.Read();
901 OSDMap record = new OSDMap();
902
903 record.Add("imviaemail",OSD.FromString((string)reader["imviaemail"]));
904 record.Add("visible",OSD.FromString((string)reader["visible"]));
905 record.Add("email",OSD.FromString((string)reader["email"]));
906 data.Add(record);
907 }
908 else
909 {
910 using (NpgsqlCommand put = new NpgsqlCommand(query, dbcon))
911 {
912 query = "INSERT INTO usersettings VALUES ";
913 query += "(:Id,'false','false', '')";
914
915 lock(Lock)
916 {
917 put.ExecuteNonQuery();
918 }
919 }
920 }
921 }
922 }
923 }
924 }
925 catch (Exception e)
926 {
927 m_log.DebugFormat("[PROFILES_DATA]" +
928 ": Get preferences exception {0}", e.Message);
929 }
930 return data;
931 }
932
933 public bool UpdateUserPreferences(bool emailIm, bool visible, UUID avatarId )
934 {
935 string query = string.Empty;
936
937 query += "UPDATE userpsettings SET ";
938 query += "imviaemail=:ImViaEmail, ";
939 query += "visible=:Visible,";
940 query += "WHERE useruuid=:uuid";
941
942 try
943 {
944 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
945 {
946 dbcon.Open();
947 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
948 {
949 cmd.Parameters.AddWithValue("ImViaEmail", emailIm.ToString().ToLower ());
950 cmd.Parameters.AddWithValue("WantText", visible.ToString().ToLower ());
951 cmd.Parameters.AddWithValue("uuid", avatarId.ToString());
952
953 lock(Lock)
954 {
955 cmd.ExecuteNonQuery();
956 }
957 }
958 }
959 }
960 catch (Exception e)
961 {
962 m_log.DebugFormat("[PROFILES_DATA]" +
963 ": AgentInterestsUpdate exception {0}", e.Message);
964 return false;
965 }
966 return true;
967 }
968 #endregion User Preferences
969
970 #region Integration
971 public bool GetUserAppData(ref UserAppData props, ref string result)
972 {
973 string query = string.Empty;
974
975 query += "SELECT * FROM userdata WHERE ";
976 query += "\"UserId\" = :Id AND ";
977 query += "\"TagId\" = :TagId";
978
979 try
980 {
981 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
982 {
983 dbcon.Open();
984 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
985 {
986 cmd.Parameters.AddWithValue("Id", props.UserId.ToString());
987 cmd.Parameters.AddWithValue (":TagId", props.TagId.ToString());
988
989 using (NpgsqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
990 {
991 if(reader.HasRows)
992 {
993 reader.Read();
994 props.DataKey = (string)reader["DataKey"];
995 props.DataVal = (string)reader["DataVal"];
996 }
997 else
998 {
999 query += "INSERT INTO userdata VALUES ( ";
1000 query += ":UserId,";
1001 query += ":TagId,";
1002 query += ":DataKey,";
1003 query += ":DataVal) ";
1004
1005 using (NpgsqlCommand put = new NpgsqlCommand(query, dbcon))
1006 {
1007 put.Parameters.AddWithValue("Id", props.UserId.ToString());
1008 put.Parameters.AddWithValue("TagId", props.TagId.ToString());
1009 put.Parameters.AddWithValue("DataKey", props.DataKey.ToString());
1010 put.Parameters.AddWithValue("DataVal", props.DataVal.ToString());
1011
1012 lock(Lock)
1013 {
1014 put.ExecuteNonQuery();
1015 }
1016 }
1017 }
1018 }
1019 }
1020 }
1021 }
1022 catch (Exception e)
1023 {
1024 m_log.DebugFormat("[PROFILES_DATA]" +
1025 ": Requst application data exception {0}", e.Message);
1026 result = e.Message;
1027 return false;
1028 }
1029 return true;
1030 }
1031
1032 public bool SetUserAppData(UserAppData props, ref string result)
1033 {
1034 string query = string.Empty;
1035
1036 query += "UPDATE userdata SET ";
1037 query += "\"TagId\" = :TagId, ";
1038 query += "\"DataKey\" = :DataKey, ";
1039 query += "\"DataVal\" = :DataVal WHERE ";
1040 query += "\"UserId\" = :UserId AND ";
1041 query += "\"TagId\" = :TagId";
1042
1043 try
1044 {
1045 using (NpgsqlConnection dbcon = new NpgsqlConnection(ConnectionString))
1046 {
1047 dbcon.Open();
1048 using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon))
1049 {
1050 cmd.Parameters.AddWithValue("UserId", props.UserId.ToString());
1051 cmd.Parameters.AddWithValue("TagId", props.TagId.ToString ());
1052 cmd.Parameters.AddWithValue("DataKey", props.DataKey.ToString ());
1053 cmd.Parameters.AddWithValue("DataVal", props.DataKey.ToString ());
1054
1055 lock(Lock)
1056 {
1057 cmd.ExecuteNonQuery();
1058 }
1059 }
1060 }
1061 }
1062 catch (Exception e)
1063 {
1064 m_log.DebugFormat("[PROFILES_DATA]" +
1065 ": SetUserData exception {0}", e.Message);
1066 return false;
1067 }
1068 return true;
1069 }
1070 #endregion Integration
1071 }
1072}
1073
diff --git a/OpenSim/Data/PGSQL/PGSQLXAssetData.cs b/OpenSim/Data/PGSQL/PGSQLXAssetData.cs
new file mode 100644
index 0000000..e959619
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLXAssetData.cs
@@ -0,0 +1,535 @@
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.Data;
31using System.IO;
32using System.IO.Compression;
33using System.Reflection;
34using System.Security.Cryptography;
35using System.Text;
36using log4net;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Data;
40using Npgsql;
41
42namespace OpenSim.Data.PGSQL
43{
44 public class PGSQLXAssetData : IXAssetDataPlugin
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 protected virtual Assembly Assembly
49 {
50 get { return GetType().Assembly; }
51 }
52
53 /// <summary>
54 /// Number of days that must pass before we update the access time on an asset when it has been fetched.
55 /// </summary>
56 private const int DaysBetweenAccessTimeUpdates = 30;
57
58 private bool m_enableCompression = false;
59 private string m_connectionString;
60 private object m_dbLock = new object();
61
62 /// <summary>
63 /// We can reuse this for all hashing since all methods are single-threaded through m_dbBLock
64 /// </summary>
65 private HashAlgorithm hasher = new SHA256CryptoServiceProvider();
66
67 #region IPlugin Members
68
69 public string Version { get { return "1.0.0.0"; } }
70
71 /// <summary>
72 /// <para>Initialises Asset interface</para>
73 /// <para>
74 /// <list type="bullet">
75 /// <item>Loads and initialises the PGSQL storage plugin.</item>
76 /// <item>Warns and uses the obsolete pgsql_connection.ini if connect string is empty.</item>
77 /// <item>Check for migration</item>
78 /// </list>
79 /// </para>
80 /// </summary>
81 /// <param name="connect">connect string</param>
82 public void Initialise(string connect)
83 {
84 m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
85 m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
86 m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
87 m_log.ErrorFormat("[PGSQL XASSETDATA]: THIS PLUGIN IS STRICTLY EXPERIMENTAL.");
88 m_log.ErrorFormat("[PGSQL XASSETDATA]: DO NOT USE FOR ANY DATA THAT YOU DO NOT MIND LOSING.");
89 m_log.ErrorFormat("[PGSQL XASSETDATA]: DATABASE TABLES CAN CHANGE AT ANY TIME, CAUSING EXISTING DATA TO BE LOST.");
90 m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
91 m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
92 m_log.ErrorFormat("[PGSQL XASSETDATA]: ***********************************************************");
93
94 m_connectionString = connect;
95
96 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
97 {
98 dbcon.Open();
99 Migration m = new Migration(dbcon, Assembly, "XAssetStore");
100 m.Update();
101 }
102 }
103
104 public void Initialise()
105 {
106 throw new NotImplementedException();
107 }
108
109 public void Dispose() { }
110
111 /// <summary>
112 /// The name of this DB provider
113 /// </summary>
114 public string Name
115 {
116 get { return "PGSQL XAsset storage engine"; }
117 }
118
119 #endregion
120
121 #region IAssetDataPlugin Members
122
123 /// <summary>
124 /// Fetch Asset <paramref name="assetID"/> from database
125 /// </summary>
126 /// <param name="assetID">Asset UUID to fetch</param>
127 /// <returns>Return the asset</returns>
128 /// <remarks>On failure : throw an exception and attempt to reconnect to database</remarks>
129 public AssetBase GetAsset(UUID assetID)
130 {
131// m_log.DebugFormat("[PGSQL XASSET DATA]: Looking for asset {0}", assetID);
132
133 AssetBase asset = null;
134 lock (m_dbLock)
135 {
136 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
137 {
138 dbcon.Open();
139
140 using (NpgsqlCommand cmd = new NpgsqlCommand(
141 @"SELECT ""Name"", ""Description"", ""AccessTime"", ""AssetType"", ""Local"", ""Temporary"", ""AssetFlags"", ""CreatorID"", ""Data""
142 FROM XAssetsMeta
143 JOIN XAssetsData ON XAssetsMeta.Hash = XAssetsData.Hash WHERE ""ID""=:ID",
144 dbcon))
145 {
146 cmd.Parameters.AddWithValue("ID", assetID.ToString());
147
148 try
149 {
150 using (NpgsqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
151 {
152 if (dbReader.Read())
153 {
154 asset = new AssetBase(assetID, (string)dbReader["Name"], (sbyte)dbReader["AssetType"], dbReader["CreatorID"].ToString());
155 asset.Data = (byte[])dbReader["Data"];
156 asset.Description = (string)dbReader["Description"];
157
158 string local = dbReader["Local"].ToString();
159 if (local.Equals("1") || local.Equals("true", StringComparison.InvariantCultureIgnoreCase))
160 asset.Local = true;
161 else
162 asset.Local = false;
163
164 asset.Temporary = Convert.ToBoolean(dbReader["Temporary"]);
165 asset.Flags = (AssetFlags)Convert.ToInt32(dbReader["AssetFlags"]);
166
167 if (m_enableCompression)
168 {
169 using (GZipStream decompressionStream = new GZipStream(new MemoryStream(asset.Data), CompressionMode.Decompress))
170 {
171 MemoryStream outputStream = new MemoryStream();
172 WebUtil.CopyStream(decompressionStream, outputStream, int.MaxValue);
173 // int compressedLength = asset.Data.Length;
174 asset.Data = outputStream.ToArray();
175
176 // m_log.DebugFormat(
177 // "[XASSET DB]: Decompressed {0} {1} to {2} bytes from {3}",
178 // asset.ID, asset.Name, asset.Data.Length, compressedLength);
179 }
180 }
181
182 UpdateAccessTime(asset.Metadata, (int)dbReader["AccessTime"]);
183 }
184 }
185 }
186 catch (Exception e)
187 {
188 m_log.Error(string.Format("[PGSQL XASSET DATA]: Failure fetching asset {0}", assetID), e);
189 }
190 }
191 }
192 }
193
194 return asset;
195 }
196
197 /// <summary>
198 /// Create an asset in database, or update it if existing.
199 /// </summary>
200 /// <param name="asset">Asset UUID to create</param>
201 /// <remarks>On failure : Throw an exception and attempt to reconnect to database</remarks>
202 public void StoreAsset(AssetBase asset)
203 {
204// m_log.DebugFormat("[XASSETS DB]: Storing asset {0} {1}", asset.Name, asset.ID);
205
206 lock (m_dbLock)
207 {
208 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
209 {
210 dbcon.Open();
211
212 using (NpgsqlTransaction transaction = dbcon.BeginTransaction())
213 {
214 string assetName = asset.Name;
215 if (asset.Name.Length > 64)
216 {
217 assetName = asset.Name.Substring(0, 64);
218 m_log.WarnFormat(
219 "[XASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add",
220 asset.Name, asset.ID, asset.Name.Length, assetName.Length);
221 }
222
223 string assetDescription = asset.Description;
224 if (asset.Description.Length > 64)
225 {
226 assetDescription = asset.Description.Substring(0, 64);
227 m_log.WarnFormat(
228 "[XASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add",
229 asset.Description, asset.ID, asset.Description.Length, assetDescription.Length);
230 }
231
232 if (m_enableCompression)
233 {
234 MemoryStream outputStream = new MemoryStream();
235
236 using (GZipStream compressionStream = new GZipStream(outputStream, CompressionMode.Compress, false))
237 {
238 // Console.WriteLine(WebUtil.CopyTo(new MemoryStream(asset.Data), compressionStream, int.MaxValue));
239 // We have to close the compression stream in order to make sure it writes everything out to the underlying memory output stream.
240 compressionStream.Close();
241 byte[] compressedData = outputStream.ToArray();
242 asset.Data = compressedData;
243 }
244 }
245
246 byte[] hash = hasher.ComputeHash(asset.Data);
247
248// m_log.DebugFormat(
249// "[XASSET DB]: Compressed data size for {0} {1}, hash {2} is {3}",
250// asset.ID, asset.Name, hash, compressedData.Length);
251
252 try
253 {
254 using (NpgsqlCommand cmd =
255 new NpgsqlCommand(
256 @"insert INTO XAssetsMeta(""ID"", ""Hash"", ""Name"", ""Description"", ""AssetType"", ""Local"", ""Temporary"", ""CreateTime"", ""AccessTime"", ""AssetFlags"", ""CreatorID"")
257 Select :ID, :Hash, :Name, :Description, :AssetType, :Local, :Temporary, :CreateTime, :AccessTime, :AssetFlags, :CreatorID
258 where not exists( Select ""ID"" from XAssetsMeta where ""ID"" = :ID ;
259
260 update XAssetsMeta
261 set ""ID"" = :ID, ""Hash"" = :Hash, ""Name"" = :Name, ""Description"" = :Description,
262 ""AssetType"" = :AssetType, ""Local"" = :Local, ""Temporary"" = :Temporary, ""CreateTime"" = :CreateTime,
263 ""AccessTime"" = :AccessTime, ""AssetFlags"" = :AssetFlags, ""CreatorID"" = :CreatorID
264 where ""ID"" = :ID;
265 ",
266 dbcon))
267 {
268 // create unix epoch time
269 int now = (int)Utils.DateTimeToUnixTime(DateTime.UtcNow);
270 cmd.Parameters.AddWithValue("ID", asset.ID);
271 cmd.Parameters.AddWithValue("Hash", hash);
272 cmd.Parameters.AddWithValue("Name", assetName);
273 cmd.Parameters.AddWithValue("Description", assetDescription);
274 cmd.Parameters.AddWithValue("AssetType", asset.Type);
275 cmd.Parameters.AddWithValue("Local", asset.Local);
276 cmd.Parameters.AddWithValue("Temporary", asset.Temporary);
277 cmd.Parameters.AddWithValue("CreateTime", now);
278 cmd.Parameters.AddWithValue("AccessTime", now);
279 cmd.Parameters.AddWithValue("CreatorID", asset.Metadata.CreatorID);
280 cmd.Parameters.AddWithValue("AssetFlags", (int)asset.Flags);
281 cmd.ExecuteNonQuery();
282 }
283 }
284 catch (Exception e)
285 {
286 m_log.ErrorFormat("[ASSET DB]: PGSQL failure creating asset metadata {0} with name \"{1}\". Error: {2}",
287 asset.FullID, asset.Name, e.Message);
288
289 transaction.Rollback();
290
291 return;
292 }
293
294 if (!ExistsData(dbcon, transaction, hash))
295 {
296 try
297 {
298 using (NpgsqlCommand cmd =
299 new NpgsqlCommand(
300 @"INSERT INTO XAssetsData(""Hash"", ""Data"") VALUES(:Hash, :Data)",
301 dbcon))
302 {
303 cmd.Parameters.AddWithValue("Hash", hash);
304 cmd.Parameters.AddWithValue("Data", asset.Data);
305 cmd.ExecuteNonQuery();
306 }
307 }
308 catch (Exception e)
309 {
310 m_log.ErrorFormat("[XASSET DB]: PGSQL failure creating asset data {0} with name \"{1}\". Error: {2}",
311 asset.FullID, asset.Name, e.Message);
312
313 transaction.Rollback();
314
315 return;
316 }
317 }
318
319 transaction.Commit();
320 }
321 }
322 }
323 }
324
325 /// <summary>
326 /// Updates the access time of the asset if it was accessed above a given threshhold amount of time.
327 /// </summary>
328 /// <remarks>
329 /// This gives us some insight into assets which haven't ben accessed for a long period. This is only done
330 /// over the threshold time to avoid excessive database writes as assets are fetched.
331 /// </remarks>
332 /// <param name='asset'></param>
333 /// <param name='accessTime'></param>
334 private void UpdateAccessTime(AssetMetadata assetMetadata, int accessTime)
335 {
336 DateTime now = DateTime.UtcNow;
337
338 if ((now - Utils.UnixTimeToDateTime(accessTime)).TotalDays < DaysBetweenAccessTimeUpdates)
339 return;
340
341 lock (m_dbLock)
342 {
343 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
344 {
345 dbcon.Open();
346 NpgsqlCommand cmd =
347 new NpgsqlCommand(@"update XAssetsMeta set ""AccessTime""=:AccessTime where ID=:ID", dbcon);
348
349 try
350 {
351 using (cmd)
352 {
353 // create unix epoch time
354 cmd.Parameters.AddWithValue("ID", assetMetadata.ID);
355 cmd.Parameters.AddWithValue("AccessTime", (int)Utils.DateTimeToUnixTime(now));
356 cmd.ExecuteNonQuery();
357 }
358 }
359 catch (Exception e)
360 {
361 m_log.ErrorFormat(
362 "[XASSET PGSQL DB]: Failure updating access_time for asset {0} with name {1} : {2}",
363 assetMetadata.ID, assetMetadata.Name, e.Message);
364 }
365 }
366 }
367 }
368
369 /// <summary>
370 /// We assume we already have the m_dbLock.
371 /// </summary>
372 /// TODO: need to actually use the transaction.
373 /// <param name="dbcon"></param>
374 /// <param name="transaction"></param>
375 /// <param name="hash"></param>
376 /// <returns></returns>
377 private bool ExistsData(NpgsqlConnection dbcon, NpgsqlTransaction transaction, byte[] hash)
378 {
379// m_log.DebugFormat("[ASSETS DB]: Checking for asset {0}", uuid);
380
381 bool exists = false;
382
383 using (NpgsqlCommand cmd = new NpgsqlCommand(@"SELECT ""Hash"" FROM XAssetsData WHERE ""Hash""=:Hash", dbcon))
384 {
385 cmd.Parameters.AddWithValue("Hash", hash);
386
387 try
388 {
389 using (NpgsqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
390 {
391 if (dbReader.Read())
392 {
393// m_log.DebugFormat("[ASSETS DB]: Found asset {0}", uuid);
394 exists = true;
395 }
396 }
397 }
398 catch (Exception e)
399 {
400 m_log.ErrorFormat(
401 "[XASSETS DB]: PGSql failure in ExistsData fetching hash {0}. Exception {1}{2}",
402 hash, e.Message, e.StackTrace);
403 }
404 }
405
406 return exists;
407 }
408
409 /// <summary>
410 /// Check if the asset exists in the database
411 /// </summary>
412 /// <param name="uuid">The asset UUID</param>
413 /// <returns>true if it exists, false otherwise.</returns>
414 public bool ExistsAsset(UUID uuid)
415 {
416// m_log.DebugFormat("[ASSETS DB]: Checking for asset {0}", uuid);
417
418 bool assetExists = false;
419
420 lock (m_dbLock)
421 {
422 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
423 {
424 dbcon.Open();
425 using (NpgsqlCommand cmd = new NpgsqlCommand(@"SELECT ""ID"" FROM XAssetsMeta WHERE ""ID""=:ID", dbcon))
426 {
427 cmd.Parameters.AddWithValue("ID", uuid.ToString());
428
429 try
430 {
431 using (NpgsqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow))
432 {
433 if (dbReader.Read())
434 {
435// m_log.DebugFormat("[ASSETS DB]: Found asset {0}", uuid);
436 assetExists = true;
437 }
438 }
439 }
440 catch (Exception e)
441 {
442 m_log.Error(string.Format("[XASSETS DB]: PGSql failure fetching asset {0}", uuid), e);
443 }
444 }
445 }
446 }
447
448 return assetExists;
449 }
450
451
452 /// <summary>
453 /// Returns a list of AssetMetadata objects. The list is a subset of
454 /// the entire data set offset by <paramref name="start" /> containing
455 /// <paramref name="count" /> elements.
456 /// </summary>
457 /// <param name="start">The number of results to discard from the total data set.</param>
458 /// <param name="count">The number of rows the returned list should contain.</param>
459 /// <returns>A list of AssetMetadata objects.</returns>
460 public List<AssetMetadata> FetchAssetMetadataSet(int start, int count)
461 {
462 List<AssetMetadata> retList = new List<AssetMetadata>(count);
463
464 lock (m_dbLock)
465 {
466 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
467 {
468 dbcon.Open();
469 NpgsqlCommand cmd = new NpgsqlCommand( @"SELECT ""Name"", ""Description"", ""AccessTime"", ""AssetType"", ""Temporary"", ""ID"", ""AssetFlags"", ""CreatorID""
470 FROM XAssetsMeta
471 LIMIT :start, :count", dbcon);
472 cmd.Parameters.AddWithValue("start", start);
473 cmd.Parameters.AddWithValue("count", count);
474
475 try
476 {
477 using (NpgsqlDataReader dbReader = cmd.ExecuteReader())
478 {
479 while (dbReader.Read())
480 {
481 AssetMetadata metadata = new AssetMetadata();
482 metadata.Name = (string)dbReader["Name"];
483 metadata.Description = (string)dbReader["Description"];
484 metadata.Type = (sbyte)dbReader["AssetType"];
485 metadata.Temporary = Convert.ToBoolean(dbReader["Temporary"]); // Not sure if this is correct.
486 metadata.Flags = (AssetFlags)Convert.ToInt32(dbReader["AssetFlags"]);
487 metadata.FullID = DBGuid.FromDB(dbReader["ID"]);
488 metadata.CreatorID = dbReader["CreatorID"].ToString();
489
490 // We'll ignore this for now - it appears unused!
491// metadata.SHA1 = dbReader["hash"]);
492
493 UpdateAccessTime(metadata, (int)dbReader["AccessTime"]);
494
495 retList.Add(metadata);
496 }
497 }
498 }
499 catch (Exception e)
500 {
501 m_log.Error("[XASSETS DB]: PGSql failure fetching asset set" + Environment.NewLine + e.ToString());
502 }
503 }
504 }
505
506 return retList;
507 }
508
509 public bool Delete(string id)
510 {
511// m_log.DebugFormat("[XASSETS DB]: Deleting asset {0}", id);
512
513 lock (m_dbLock)
514 {
515 using (NpgsqlConnection dbcon = new NpgsqlConnection(m_connectionString))
516 {
517 dbcon.Open();
518
519 using (NpgsqlCommand cmd = new NpgsqlCommand(@"delete from XAssetsMeta where ""ID""=:ID", dbcon))
520 {
521 cmd.Parameters.AddWithValue("ID", id);
522 cmd.ExecuteNonQuery();
523 }
524
525 // TODO: How do we deal with data from deleted assets? Probably not easily reapable unless we
526 // keep a reference count (?)
527 }
528 }
529
530 return true;
531 }
532
533 #endregion
534 }
535}
diff --git a/OpenSim/Data/PGSQL/PGSQLXInventoryData.cs b/OpenSim/Data/PGSQL/PGSQLXInventoryData.cs
new file mode 100644
index 0000000..a22b882
--- /dev/null
+++ b/OpenSim/Data/PGSQL/PGSQLXInventoryData.cs
@@ -0,0 +1,330 @@
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.Data;
32using OpenMetaverse;
33using OpenSim.Framework;
34using System.Reflection;
35using System.Text;
36using log4net;
37using Npgsql;
38using NpgsqlTypes;
39
40namespace OpenSim.Data.PGSQL
41{
42 public class PGSQLXInventoryData : IXInventoryData
43 {
44// private static readonly ILog m_log = LogManager.GetLogger(
45// MethodBase.GetCurrentMethod().DeclaringType);
46
47 private PGSQLFolderHandler m_Folders;
48 private PGSQLItemHandler m_Items;
49
50 public PGSQLXInventoryData(string conn, string realm)
51 {
52 m_Folders = new PGSQLFolderHandler(
53 conn, "inventoryfolders", "InventoryStore");
54 m_Items = new PGSQLItemHandler(
55 conn, "inventoryitems", String.Empty);
56 }
57
58 public static UUID str2UUID(string strUUID)
59 {
60 UUID newUUID = UUID.Zero;
61
62 UUID.TryParse(strUUID, out newUUID);
63
64 return newUUID;
65 }
66
67 public XInventoryFolder[] GetFolders(string[] fields, string[] vals)
68 {
69 return m_Folders.Get(fields, vals);
70 }
71
72 public XInventoryItem[] GetItems(string[] fields, string[] vals)
73 {
74 return m_Items.Get(fields, vals);
75 }
76
77 public bool StoreFolder(XInventoryFolder folder)
78 {
79 if (folder.folderName.Length > 64)
80 folder.folderName = folder.folderName.Substring(0, 64);
81 return m_Folders.Store(folder);
82 }
83
84 public bool StoreItem(XInventoryItem item)
85 {
86 if (item.inventoryName.Length > 64)
87 item.inventoryName = item.inventoryName.Substring(0, 64);
88 if (item.inventoryDescription.Length > 128)
89 item.inventoryDescription = item.inventoryDescription.Substring(0, 128);
90
91 return m_Items.Store(item);
92 }
93
94 public bool DeleteFolders(string field, string val)
95 {
96 return m_Folders.Delete(field, val);
97 }
98
99 public bool DeleteFolders(string[] fields, string[] vals)
100 {
101 return m_Folders.Delete(fields, vals);
102 }
103
104 public bool DeleteItems(string field, string val)
105 {
106 return m_Items.Delete(field, val);
107 }
108
109 public bool DeleteItems(string[] fields, string[] vals)
110 {
111 return m_Items.Delete(fields, vals);
112 }
113
114 public bool MoveItem(string id, string newParent)
115 {
116 return m_Items.MoveItem(id, newParent);
117 }
118
119 public bool MoveFolder(string id, string newParent)
120 {
121 return m_Folders.MoveFolder(id, newParent);
122 }
123
124 public XInventoryItem[] GetActiveGestures(UUID principalID)
125 {
126 return m_Items.GetActiveGestures(principalID.ToString());
127 }
128
129 public int GetAssetPermissions(UUID principalID, UUID assetID)
130 {
131 return m_Items.GetAssetPermissions(principalID, assetID);
132 }
133 }
134
135 public class PGSQLItemHandler : PGSQLInventoryHandler<XInventoryItem>
136 {
137 public PGSQLItemHandler(string c, string t, string m) :
138 base(c, t, m)
139 {
140 }
141
142 public bool MoveItem(string id, string newParent)
143 {
144 XInventoryItem[] retrievedItems = Get(new string[] { "inventoryID" }, new string[] { id });
145 if (retrievedItems.Length == 0)
146 return false;
147
148 UUID oldParent = retrievedItems[0].parentFolderID;
149
150 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
151 {
152 using (NpgsqlCommand cmd = new NpgsqlCommand())
153 {
154 cmd.CommandText = String.Format(@"update {0} set ""parentFolderID"" = :ParentFolderID where ""inventoryID"" = :InventoryID", m_Realm);
155 cmd.Parameters.Add(m_database.CreateParameter("ParentFolderID", newParent));
156 cmd.Parameters.Add(m_database.CreateParameter("InventoryID", id ));
157 cmd.Connection = conn;
158 conn.Open();
159
160 if (cmd.ExecuteNonQuery() == 0)
161 return false;
162 }
163 }
164
165 IncrementFolderVersion(oldParent);
166 IncrementFolderVersion(newParent);
167
168 return true;
169 }
170
171 public XInventoryItem[] GetActiveGestures(string principalID)
172 {
173 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
174 {
175 using (NpgsqlCommand cmd = new NpgsqlCommand())
176 {
177 cmd.CommandText = String.Format(@"select * from inventoryitems where ""avatarID"" = :uuid and ""assetType"" = :type and ""flags"" = 1", m_Realm);
178
179 UUID princID = UUID.Zero;
180 UUID.TryParse(principalID, out princID);
181
182 cmd.Parameters.Add(m_database.CreateParameter("uuid", principalID));
183 cmd.Parameters.Add(m_database.CreateParameter("type", (int)AssetType.Gesture));
184 cmd.Connection = conn;
185 conn.Open();
186 return DoQuery(cmd);
187 }
188 }
189 }
190
191 public int GetAssetPermissions(UUID principalID, UUID assetID)
192 {
193 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
194 {
195 using (NpgsqlCommand cmd = new NpgsqlCommand())
196 {
197 cmd.CommandText = String.Format(@"select bit_or(""inventoryCurrentPermissions"") as ""inventoryCurrentPermissions""
198 from inventoryitems
199 where ""avatarID"" = :PrincipalID
200 and ""assetID"" = :AssetID
201 group by ""assetID"" ", m_Realm);
202
203 cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID));
204 cmd.Parameters.Add(m_database.CreateParameter("AssetID", assetID));
205 cmd.Connection = conn;
206 conn.Open();
207 using (NpgsqlDataReader reader = cmd.ExecuteReader())
208 {
209
210 int perms = 0;
211
212 if (reader.Read())
213 {
214 perms = Convert.ToInt32(reader["inventoryCurrentPermissions"]);
215 }
216
217 return perms;
218 }
219
220 }
221 }
222 }
223
224 public override bool Store(XInventoryItem item)
225 {
226 if (!base.Store(item))
227 return false;
228
229 IncrementFolderVersion(item.parentFolderID);
230
231 return true;
232 }
233 }
234
235 public class PGSQLFolderHandler : PGSQLInventoryHandler<XInventoryFolder>
236 {
237 public PGSQLFolderHandler(string c, string t, string m) :
238 base(c, t, m)
239 {
240 }
241
242 public bool MoveFolder(string id, string newParentFolderID)
243 {
244 XInventoryFolder[] folders = Get(new string[] { "folderID" }, new string[] { id });
245
246 if (folders.Length == 0)
247 return false;
248
249 UUID oldParentFolderUUID = folders[0].parentFolderID;
250
251 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
252 {
253 using (NpgsqlCommand cmd = new NpgsqlCommand())
254 {
255 UUID foldID = UUID.Zero;
256 UUID.TryParse(id, out foldID);
257
258 UUID newPar = UUID.Zero;
259 UUID.TryParse(newParentFolderID, out newPar);
260
261 cmd.CommandText = String.Format(@"update {0} set ""parentFolderID"" = :ParentFolderID where ""folderID"" = :folderID", m_Realm);
262 cmd.Parameters.Add(m_database.CreateParameter("ParentFolderID", newPar));
263 cmd.Parameters.Add(m_database.CreateParameter("folderID", foldID));
264 cmd.Connection = conn;
265 conn.Open();
266
267 if (cmd.ExecuteNonQuery() == 0)
268 return false;
269 }
270 }
271
272 IncrementFolderVersion(oldParentFolderUUID);
273 IncrementFolderVersion(newParentFolderID);
274
275 return true;
276 }
277
278 public override bool Store(XInventoryFolder folder)
279 {
280 if (!base.Store(folder))
281 return false;
282
283 IncrementFolderVersion(folder.parentFolderID);
284
285 return true;
286 }
287 }
288
289 public class PGSQLInventoryHandler<T> : PGSQLGenericTableHandler<T> where T: class, new()
290 {
291 public PGSQLInventoryHandler(string c, string t, string m) : base(c, t, m) {}
292
293 protected bool IncrementFolderVersion(UUID folderID)
294 {
295 return IncrementFolderVersion(folderID.ToString());
296 }
297
298 protected bool IncrementFolderVersion(string folderID)
299 {
300// m_log.DebugFormat("[PGSQL ITEM HANDLER]: Incrementing version on folder {0}", folderID);
301// Util.PrintCallStack();
302
303 string sql = @"update inventoryfolders set version=version+1 where ""folderID"" = :folderID";
304
305 using (NpgsqlConnection conn = new NpgsqlConnection(m_ConnectionString))
306 {
307 using (NpgsqlCommand cmd = new NpgsqlCommand(sql, conn))
308 {
309 UUID foldID = UUID.Zero;
310 UUID.TryParse(folderID, out foldID);
311
312 conn.Open();
313
314 cmd.Parameters.Add( m_database.CreateParameter("folderID", foldID) );
315
316 try
317 {
318 cmd.ExecuteNonQuery();
319 }
320 catch (Exception)
321 {
322 return false;
323 }
324 }
325 }
326
327 return true;
328 }
329 }
330}
diff --git a/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs b/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..27d0679
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Properties/AssemblyInfo.cs
@@ -0,0 +1,65 @@
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.Reflection;
29using System.Runtime.InteropServices;
30
31// General information about an assembly is controlled through the following
32// set of attributes. Change these attribute values to modify the information
33// associated with an assembly.
34
35[assembly : AssemblyTitle("OpenSim.Data.PGSQL")]
36[assembly : AssemblyDescription("")]
37[assembly : AssemblyConfiguration("")]
38[assembly : AssemblyCompany("http://opensimulator.org")]
39[assembly : AssemblyProduct("OpenSim.Data.PGSQL")]
40[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")]
41[assembly : AssemblyTrademark("")]
42[assembly : AssemblyCulture("")]
43
44// Setting ComVisible to false makes the types in this assembly not visible
45// to COM components. If you need to access a type in this assembly from
46// COM, set the ComVisible attribute to true on that type.
47
48[assembly : ComVisible(false)]
49
50// The following GUID is for the ID of the typelib if this project is exposed to COM
51
52[assembly : Guid("0e1c1ca4-2cf2-4315-b0e7-432c02feea8a")]
53
54// Version information for an assembly consists of the following four values:
55//
56// Major Version
57// Minor Version
58// Build Number
59// Revision
60//
61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below:
63
64[assembly : AssemblyVersion("0.7.6.*")]
65
diff --git a/OpenSim/Data/PGSQL/Resources/AssetStore.migrations b/OpenSim/Data/PGSQL/Resources/AssetStore.migrations
new file mode 100644
index 0000000..b6db585
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/AssetStore.migrations
@@ -0,0 +1,94 @@
1:VERSION 1
2
3CREATE TABLE assets (
4 "id" varchar(36) NOT NULL PRIMARY KEY,
5 "name" varchar(64) NOT NULL,
6 "description" varchar(64) NOT NULL,
7 "assetType" smallint NOT NULL,
8 "local" smallint NOT NULL,
9 "temporary" smallint NOT NULL,
10 "data" bytea NOT NULL
11) ;
12
13:VERSION 2
14
15BEGIN TRANSACTION;
16
17CREATE TABLE Tmp_assets
18 (
19 "id" varchar(36) NOT NULL,
20 "name" varchar(64) NOT NULL,
21 "description" varchar(64) NOT NULL,
22 "assetType" smallint NOT NULL,
23 "local" boolean NOT NULL,
24 "temporary" boolean NOT NULL,
25 "data" bytea NOT NULL
26 ) ;
27
28INSERT INTO Tmp_assets ("id", "name", "description", "assetType", "local", "temporary", "data")
29 SELECT "id", "name", "description", "assetType", case when "local" = 1 then true else false end, case when "temporary" = 1 then true else false end, "data"
30 FROM assets ;
31
32DROP TABLE assets;
33
34Alter table Tmp_assets
35 rename to assets;
36
37ALTER TABLE assets ADD PRIMARY KEY ("id");
38
39COMMIT;
40
41
42:VERSION 3
43
44BEGIN TRANSACTION;
45
46ALTER TABLE assets add "create_time" integer default 0;
47ALTER TABLE assets add "access_time" integer default 0;
48
49COMMIT;
50
51
52:VERSION 4
53
54BEGIN TRANSACTION;
55
56CREATE TABLE Tmp_assets
57 (
58 "id" uuid NOT NULL,
59 "name" varchar(64) NOT NULL,
60 "description" varchar(64) NOT NULL,
61 "assetType" smallint NOT NULL,
62 "local" boolean NOT NULL,
63 "temporary" boolean NOT NULL,
64 "data" bytea NOT NULL,
65 "create_time" int NULL,
66 "access_time" int NULL
67 ) ;
68
69
70INSERT INTO Tmp_assets ("id", "name", "description", "assetType", "local", "temporary", "data", "create_time", "access_time")
71 SELECT cast("id" as uuid), "name", "description", "assetType", "local", "temporary", "data", "create_time", "access_time"
72 FROM assets ;
73
74DROP TABLE assets;
75
76Alter table Tmp_assets
77 rename to assets;
78
79 ALTER TABLE assets ADD PRIMARY KEY ("id");
80
81COMMIT;
82
83
84:VERSION 5
85
86DELETE FROM assets WHERE "id" = 'dc4b9f0b-d008-45c6-96a4-01dd947ac621';
87
88:VERSION 6
89
90ALTER TABLE assets ADD "asset_flags" INTEGER NOT NULL DEFAULT 0;
91
92:VERSION 7
93
94alter table assets add "creatorid" varchar(36) not null default '';
diff --git a/OpenSim/Data/PGSQL/Resources/AuthStore.migrations b/OpenSim/Data/PGSQL/Resources/AuthStore.migrations
new file mode 100644
index 0000000..a1f5b61
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/AuthStore.migrations
@@ -0,0 +1,32 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE auth (
6 uuid uuid NOT NULL default '00000000-0000-0000-0000-000000000000',
7 "passwordHash" varchar(32) NOT NULL,
8 "passwordSalt" varchar(32) NOT NULL,
9 "webLoginKey" varchar(255) NOT NULL,
10 "accountType" VARCHAR(32) NOT NULL DEFAULT 'UserAccount'
11) ;
12
13CREATE TABLE tokens (
14 uuid uuid NOT NULL default '00000000-0000-0000-0000-000000000000',
15 token varchar(255) NOT NULL,
16 validity TIMESTAMP NOT NULL )
17 ;
18
19COMMIT;
20
21:VERSION 2
22
23BEGIN TRANSACTION;
24
25 INSERT INTO auth (uuid, "passwordHash", "passwordSalt", "webLoginKey", "accountType")
26 SELECT uuid AS UUID, passwordHash AS passwordHash, passwordSalt AS passwordSalt, webLoginKey AS webLoginKey, 'UserAccount' as accountType
27 FROM users
28 where exists ( Select * from information_schema.tables where table_name = 'users' )
29 ;
30
31COMMIT;
32
diff --git a/OpenSim/Data/PGSQL/Resources/Avatar.migrations b/OpenSim/Data/PGSQL/Resources/Avatar.migrations
new file mode 100644
index 0000000..160086d
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/Avatar.migrations
@@ -0,0 +1,59 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE Avatars (
6"PrincipalID" uuid NOT NULL PRIMARY KEY,
7"Name" varchar(32) NOT NULL,
8"Value" varchar(255) NOT NULL DEFAULT ''
9);
10
11
12COMMIT;
13
14:VERSION 2
15
16BEGIN TRANSACTION;
17
18CREATE TABLE Tmp_Avatars
19 (
20 "PrincipalID" uuid NOT NULL,
21 "Name" varchar(32) NOT NULL,
22 "Value" text NOT NULL DEFAULT ''
23 ) ;
24
25 INSERT INTO Tmp_Avatars ("PrincipalID", "Name", "Value")
26 SELECT "PrincipalID", cast("Name" as text), "Value"
27 FROM Avatars ;
28
29DROP TABLE Avatars;
30
31Alter table Tmp_Avatars
32 rename to Avatars;
33
34COMMIT;
35
36:VERSION 3
37
38BEGIN TRANSACTION;
39
40CREATE TABLE Tmp_Avatars
41 (
42 "PrincipalID" uuid NOT NULL,
43 "Name" varchar(32) NOT NULL,
44 "Value" text NOT NULL DEFAULT ''
45);
46
47ALTER TABLE Tmp_Avatars ADD PRIMARY KEY ("PrincipalID", "Name");
48
49
50INSERT INTO Tmp_Avatars ("PrincipalID", "Name", "Value")
51 SELECT "PrincipalID", "Name", cast("Value" as text) FROM Avatars ;
52
53DROP TABLE Avatars;
54
55Alter table Tmp_Avatars
56 rename to Avatars;
57
58COMMIT;
59
diff --git a/OpenSim/Data/PGSQL/Resources/EstateStore.migrations b/OpenSim/Data/PGSQL/Resources/EstateStore.migrations
new file mode 100644
index 0000000..59270f8
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/EstateStore.migrations
@@ -0,0 +1,307 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE estate_managers(
6 "EstateID" int NOT NULL Primary Key,
7 uuid varchar(36) NOT NULL
8 );
9
10CREATE TABLE estate_groups(
11 "EstateID" int NOT NULL,
12 uuid varchar(36) NOT NULL
13 );
14
15
16CREATE TABLE estate_users(
17 "EstateID" int NOT NULL,
18 uuid varchar(36) NOT NULL
19 );
20
21
22CREATE TABLE estateban(
23 "EstateID" int NOT NULL,
24 "bannedUUID" varchar(36) NOT NULL,
25 "bannedIp" varchar(16) NOT NULL,
26 "bannedIpHostMask" varchar(16) NOT NULL,
27 "bannedNameMask" varchar(64) NULL DEFAULT NULL
28 );
29
30Create Sequence estate_settings_id increment by 100 start with 100;
31
32CREATE TABLE estate_settings(
33 "EstateID" integer DEFAULT nextval('estate_settings_id') NOT NULL,
34 "EstateName" varchar(64) NULL DEFAULT (NULL),
35 "AbuseEmailToEstateOwner" boolean NOT NULL,
36 "DenyAnonymous" boolean NOT NULL,
37 "ResetHomeOnTeleport" boolean NOT NULL,
38 "FixedSun" boolean NOT NULL,
39 "DenyTransacted" boolean NOT NULL,
40 "BlockDwell" boolean NOT NULL,
41 "DenyIdentified" boolean NOT NULL,
42 "AllowVoice" boolean NOT NULL,
43 "UseGlobalTime" boolean NOT NULL,
44 "PricePerMeter" int NOT NULL,
45 "TaxFree" boolean NOT NULL,
46 "AllowDirectTeleport" boolean NOT NULL,
47 "RedirectGridX" int NOT NULL,
48 "RedirectGridY" int NOT NULL,
49 "ParentEstateID" int NOT NULL,
50 "SunPosition" double precision NOT NULL,
51 "EstateSkipScripts" boolean NOT NULL,
52 "BillableFactor" double precision NOT NULL,
53 "PublicAccess" boolean NOT NULL,
54 "AbuseEmail" varchar(255) NOT NULL,
55 "EstateOwner" varchar(36) NOT NULL,
56 "DenyMinors" boolean NOT NULL
57 );
58
59
60CREATE TABLE estate_map(
61 "RegionID" varchar(36) NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
62 "EstateID" int NOT NULL
63 );
64
65COMMIT;
66
67:VERSION 2
68
69BEGIN TRANSACTION;
70
71CREATE INDEX IX_estate_managers ON estate_managers
72 (
73 "EstateID"
74 );
75
76
77CREATE INDEX IX_estate_groups ON estate_groups
78 (
79 "EstateID"
80 );
81
82
83CREATE INDEX IX_estate_users ON estate_users
84 (
85 "EstateID"
86 );
87
88COMMIT;
89
90:VERSION 3
91
92BEGIN TRANSACTION;
93
94CREATE TABLE Tmp_estateban
95 (
96 "EstateID" int NOT NULL,
97 "bannedUUID" varchar(36) NOT NULL,
98 "bannedIp" varchar(16) NULL,
99 "bannedIpHostMask" varchar(16) NULL,
100 "bannedNameMask" varchar(64) NULL
101 );
102
103 INSERT INTO Tmp_estateban ("EstateID", "bannedUUID", "bannedIp", "bannedIpHostMask", "bannedNameMask")
104 SELECT "EstateID", "bannedUUID", "bannedIp", "bannedIpHostMask", "bannedNameMask" FROM estateban;
105
106DROP TABLE estateban;
107
108Alter table Tmp_estateban
109 rename to estateban;
110
111CREATE INDEX IX_estateban ON estateban
112 (
113 "EstateID"
114 );
115
116COMMIT;
117
118
119:VERSION 4
120
121BEGIN TRANSACTION;
122
123CREATE TABLE Tmp_estate_managers
124 (
125 "EstateID" int NOT NULL,
126 uuid uuid NOT NULL
127 );
128
129INSERT INTO Tmp_estate_managers ("EstateID", uuid)
130 SELECT "EstateID", cast(uuid as uuid) FROM estate_managers;
131
132DROP TABLE estate_managers;
133
134Alter table Tmp_estate_managers
135 rename to estate_managers;
136
137CREATE INDEX IX_estate_managers ON estate_managers
138 (
139 "EstateID"
140 );
141
142COMMIT;
143
144
145:VERSION 5
146
147BEGIN TRANSACTION;
148
149CREATE TABLE Tmp_estate_groups
150 (
151 "EstateID" int NOT NULL,
152 uuid uuid NOT NULL
153 ) ;
154
155 INSERT INTO Tmp_estate_groups ("EstateID", uuid)
156 SELECT "EstateID", cast(uuid as uuid) FROM estate_groups;
157
158DROP TABLE estate_groups;
159
160Alter table Tmp_estate_groups
161 rename to estate_groups;
162
163CREATE INDEX IX_estate_groups ON estate_groups
164 (
165 "EstateID"
166 );
167
168COMMIT;
169
170
171:VERSION 6
172
173BEGIN TRANSACTION;
174
175CREATE TABLE Tmp_estate_users
176 (
177 "EstateID" int NOT NULL,
178 uuid uuid NOT NULL
179 );
180
181INSERT INTO Tmp_estate_users ("EstateID", uuid)
182 SELECT "EstateID", cast(uuid as uuid) FROM estate_users ;
183
184DROP TABLE estate_users;
185
186Alter table Tmp_estate_users
187 rename to estate_users;
188
189CREATE INDEX IX_estate_users ON estate_users
190 (
191 "EstateID"
192 );
193
194COMMIT;
195
196
197:VERSION 7
198
199BEGIN TRANSACTION;
200
201CREATE TABLE Tmp_estateban
202 (
203 "EstateID" int NOT NULL,
204 "bannedUUID" uuid NOT NULL,
205 "bannedIp" varchar(16) NULL,
206 "bannedIpHostMask" varchar(16) NULL,
207 "bannedNameMask" varchar(64) NULL
208 );
209
210INSERT INTO Tmp_estateban ("EstateID", "bannedUUID", "bannedIp", "bannedIpHostMask", "bannedNameMask")
211 SELECT "EstateID", cast("bannedUUID" as uuid), "bannedIp", "bannedIpHostMask", "bannedNameMask" FROM estateban ;
212
213DROP TABLE estateban;
214
215Alter table Tmp_estateban
216 rename to estateban;
217
218CREATE INDEX IX_estateban ON estateban
219 (
220 "EstateID"
221 );
222
223COMMIT;
224
225
226:VERSION 8
227
228BEGIN TRANSACTION;
229
230CREATE TABLE Tmp_estate_settings
231 (
232 "EstateID" integer default nextval('estate_settings_id') NOT NULL,
233 "EstateName" varchar(64) NULL DEFAULT (NULL),
234 "AbuseEmailToEstateOwner" boolean NOT NULL,
235 "DenyAnonymous" boolean NOT NULL,
236 "ResetHomeOnTeleport" boolean NOT NULL,
237 "FixedSun" boolean NOT NULL,
238 "DenyTransacted" boolean NOT NULL,
239 "BlockDwell" boolean NOT NULL,
240 "DenyIdentified" boolean NOT NULL,
241 "AllowVoice" boolean NOT NULL,
242 "UseGlobalTime" boolean NOT NULL,
243 "PricePerMeter" int NOT NULL,
244 "TaxFree" boolean NOT NULL,
245 "AllowDirectTeleport" boolean NOT NULL,
246 "RedirectGridX" int NOT NULL,
247 "RedirectGridY" int NOT NULL,
248 "ParentEstateID" int NOT NULL,
249 "SunPosition" double precision NOT NULL,
250 "EstateSkipScripts" boolean NOT NULL,
251 "BillableFactor" double precision NOT NULL,
252 "PublicAccess" boolean NOT NULL,
253 "AbuseEmail" varchar(255) NOT NULL,
254 "EstateOwner" uuid NOT NULL,
255 "DenyMinors" boolean NOT NULL
256 );
257
258INSERT INTO Tmp_estate_settings ("EstateID", "EstateName", "AbuseEmailToEstateOwner", "DenyAnonymous", "ResetHomeOnTeleport", "FixedSun", "DenyTransacted", "BlockDwell", "DenyIdentified", "AllowVoice", "UseGlobalTime", "PricePerMeter", "TaxFree", "AllowDirectTeleport", "RedirectGridX", "RedirectGridY", "ParentEstateID", "SunPosition", "EstateSkipScripts", "BillableFactor", "PublicAccess", "AbuseEmail", "EstateOwner", "DenyMinors")
259 SELECT "EstateID", "EstateName", "AbuseEmailToEstateOwner", "DenyAnonymous", "ResetHomeOnTeleport", "FixedSun", "DenyTransacted", "BlockDwell", "DenyIdentified", "AllowVoice", "UseGlobalTime", "PricePerMeter", "TaxFree", "AllowDirectTeleport", "RedirectGridX", "RedirectGridY", "ParentEstateID", "SunPosition", "EstateSkipScripts", "BillableFactor", "PublicAccess", "AbuseEmail", cast("EstateOwner" as uuid), "DenyMinors" FROM estate_settings ;
260
261DROP TABLE estate_settings;
262
263
264Alter table Tmp_estate_settings
265 rename to estate_settings;
266
267
268Create index on estate_settings (lower("EstateName"));
269
270COMMIT;
271
272
273:VERSION 9
274
275BEGIN TRANSACTION;
276
277CREATE TABLE Tmp_estate_map
278 (
279 "RegionID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
280 "EstateID" int NOT NULL
281 );
282
283INSERT INTO Tmp_estate_map ("RegionID", "EstateID")
284 SELECT cast("RegionID" as uuid), "EstateID" FROM estate_map ;
285
286DROP TABLE estate_map;
287
288Alter table Tmp_estate_map
289 rename to estate_map;
290
291COMMIT;
292
293:VERSION 10
294
295BEGIN TRANSACTION;
296ALTER TABLE estate_settings ADD COLUMN "AllowLandmark" boolean NOT NULL default true;
297ALTER TABLE estate_settings ADD COLUMN "AllowParcelChanges" boolean NOT NULL default true;
298ALTER TABLE estate_settings ADD COLUMN "AllowSetHome" boolean NOT NULL default true;
299COMMIT;
300
301:VERSION 11
302
303Begin transaction;
304
305
306Commit;
307
diff --git a/OpenSim/Data/PGSQL/Resources/FriendsStore.migrations b/OpenSim/Data/PGSQL/Resources/FriendsStore.migrations
new file mode 100644
index 0000000..a87199b
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/FriendsStore.migrations
@@ -0,0 +1,44 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE Friends (
6"PrincipalID" uuid NOT NULL,
7"Friend" varchar(255) NOT NULL,
8"Flags" char(16) NOT NULL DEFAULT '0',
9"Offered" varchar(32) NOT NULL DEFAULT 0);
10
11
12COMMIT;
13
14:VERSION 2
15
16BEGIN TRANSACTION;
17
18INSERT INTO Friends ("PrincipalID", "Friend", "Flags", "Offered")
19SELECT "ownerID", "friendID", "friendPerms", 0 FROM userfriends;
20
21COMMIT;
22
23:VERSION 3
24
25BEGIN TRANSACTION;
26
27CREATE TABLE Tmp_Friends
28 ("PrincipalID" varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
29 "Friend" varchar(255) NOT NULL,
30 "Flags" char(16) NOT NULL DEFAULT '0',
31 "Offered" varchar(32) NOT NULL DEFAULT 0) ;
32
33INSERT INTO Tmp_Friends ("PrincipalID", "Friend", "Flags", "Offered")
34 SELECT cast("PrincipalID" as varchar(255)), "Friend", "Flags", "Offered" FROM Friends ;
35
36DROP TABLE Friends;
37
38Alter table Tmp_Friends
39 rename to Friends;
40
41ALTER TABLE Friends ADD PRIMARY KEY("PrincipalID", "Friend");
42
43
44COMMIT;
diff --git a/OpenSim/Data/PGSQL/Resources/GridStore.migrations b/OpenSim/Data/PGSQL/Resources/GridStore.migrations
new file mode 100644
index 0000000..0ab8d2b
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/GridStore.migrations
@@ -0,0 +1,242 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE regions(
6 "regionHandle" varchar(255) NULL,
7 "regionName" varchar(255) NULL,
8 uuid varchar(255) NOT NULL PRIMARY KEY,
9 "regionRecvKey" varchar(255) NULL,
10 "regionSecret" varchar(255) NULL,
11 "regionSendKey" varchar(255) NULL,
12 "regionDataURI" varchar(255) NULL,
13 "serverIP" varchar(255) NULL,
14 "serverPort" varchar(255) NULL,
15 "serverURI" varchar(255) NULL,
16 "locX" varchar(255) NULL,
17 "locY" varchar(255) NULL,
18 "locZ" varchar(255) NULL,
19 "eastOverrideHandle" varchar(255) NULL,
20 "westOverrideHandle" varchar(255) NULL,
21 "southOverrideHandle" varchar(255) NULL,
22 "northOverrideHandle" varchar(255) NULL,
23 "regionAssetURI" varchar(255) NULL,
24 "regionAssetRecvKey" varchar(255) NULL,
25 "regionAssetSendKey" varchar(255) NULL,
26 "regionUserURI" varchar(255) NULL,
27 "regionUserRecvKey" varchar(255) NULL,
28 "regionUserSendKey" varchar(255) NULL,
29 "regionMapTexture" varchar(255) NULL,
30 "serverHttpPort" varchar(255) NULL,
31 "serverRemotingPort" varchar(255) NULL,
32 "owner_uuid" varchar(36) NULL
33);
34
35COMMIT;
36
37
38:VERSION 2
39
40BEGIN TRANSACTION;
41
42CREATE TABLE Tmp_regions
43 (
44 uuid varchar(36) NOT NULL,
45 "regionHandle" bigint NULL,
46 "regionName" varchar(20) NULL,
47 "regionRecvKey" varchar(128) NULL,
48 "regionSendKey" varchar(128) NULL,
49 "regionSecret" varchar(128) NULL,
50 "regionDataURI" varchar(128) NULL,
51 "serverIP" varchar(64) NULL,
52 "serverPort" int NULL,
53 "serverURI" varchar(255) NULL,
54 "locX" int NULL,
55 "locY" int NULL,
56 "locZ" int NULL,
57 "eastOverrideHandle" bigint NULL,
58 "westOverrideHandle" bigint NULL,
59 "southOverrideHandle" bigint NULL,
60 "northOverrideHandle" bigint NULL,
61 "regionAssetURI" varchar(255) NULL,
62 "regionAssetRecvKey" varchar(128) NULL,
63 "regionAssetSendKey" varchar(128) NULL,
64 "regionUserURI" varchar(255) NULL,
65 "regionUserRecvKey" varchar(128) NULL,
66 "regionUserSendKey" varchar(128) NULL,
67 "regionMapTexture" varchar(36) NULL,
68 "serverHttpPort" int NULL,
69 "serverRemotingPort" int NULL,
70 "owner_uuid" varchar(36) NULL,
71 "originUUID" varchar(36) NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000')
72 );
73
74INSERT INTO Tmp_regions (uuid, "regionHandle", "regionName", "regionRecvKey", "regionSendKey", "regionSecret", "regionDataURI", "serverIP", "serverPort", "serverURI", "locX", "locY", "locZ", "eastOverrideHandle", "westOverrideHandle", "southOverrideHandle", "northOverrideHandle", "regionAssetURI", "regionAssetRecvKey", "regionAssetSendKey", "regionUserURI", "regionUserRecvKey", "regionUserSendKey", "regionMapTexture", "serverHttpPort", "serverRemotingPort", "owner_uuid")
75 SELECT cast(uuid as varchar(36)), cast("regionHandle" as bigint), cast("regionName" as varchar(20)), cast("regionRecvKey" as varchar(128)), cast("regionSendKey" as varchar(128)), cast("regionSecret" as varchar(128)), cast("regionDataURI" as varchar(128)), cast("serverIP" as varchar(64)), cast("serverPort" as int), "serverURI", cast("locX" as int), cast("locY" as int), cast("locZ" as int), cast("eastOverrideHandle" as bigint), cast("westOverrideHandle" as bigint),
76 cast("southOverrideHandle" as bigint), cast("northOverrideHandle" as bigint), "regionAssetURI", cast("regionAssetRecvKey" as varchar(128)), cast("regionAssetSendKey" as varchar(128)), "regionUserURI", cast("regionUserRecvKey" as varchar(128)), cast("regionUserSendKey" as varchar(128)), cast("regionMapTexture" as varchar(36)),
77 cast("serverHttpPort" as int), cast("serverRemotingPort" as int), "owner_uuid"
78 FROM regions;
79
80DROP TABLE regions;
81
82alter table Tmp_regions
83 rename to regions;
84
85COMMIT;
86
87:VERSION 3
88
89BEGIN TRANSACTION;
90
91CREATE INDEX IX_regions_name ON regions
92 (
93 "regionName"
94 );
95
96CREATE INDEX IX_regions_handle ON regions
97 (
98 "regionHandle"
99 );
100
101
102CREATE INDEX IX_regions_override ON regions
103 (
104 "eastOverrideHandle",
105 "westOverrideHandle",
106 "southOverrideHandle",
107 "northOverrideHandle"
108 );
109
110COMMIT;
111
112
113:VERSION 4
114
115/* To prevent any potential data loss issues, you should review this script in detail before running it outside the cotext of the database designer.*/
116BEGIN TRANSACTION;
117
118CREATE TABLE Tmp_regions
119 (
120 uuid uuid NOT NULL,
121 "regionHandle" bigint NULL,
122 "regionName" varchar(20) NULL,
123 "regionRecvKey" varchar(128) NULL,
124 "regionSendKey" varchar(128) NULL,
125 "regionSecret" varchar(128) NULL,
126 "regionDataURI" varchar(128) NULL,
127 "serverIP" varchar(64) NULL,
128 "serverPort" int NULL,
129 "serverURI" varchar(255) NULL,
130 "locX" int NULL,
131 "locY" int NULL,
132 "locZ" int NULL,
133 "eastOverrideHandle" bigint NULL,
134 "westOverrideHandle" bigint NULL,
135 "southOverrideHandle" bigint NULL,
136 "northOverrideHandle" bigint NULL,
137 "regionAssetURI" varchar(255) NULL,
138 "regionAssetRecvKey" varchar(128) NULL,
139 "regionAssetSendKey" varchar(128) NULL,
140 "regionUserURI" varchar(255) NULL,
141 "regionUserRecvKey" varchar(128) NULL,
142 "regionUserSendKey" varchar(128) NULL,
143 "regionMapTexture" uuid NULL,
144 "serverHttpPort" int NULL,
145 "serverRemotingPort" int NULL,
146 "owner_uuid" uuid NOT NULL,
147 "originUUID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000')
148 );
149
150
151INSERT INTO Tmp_regions (uuid, "regionHandle", "regionName", "regionRecvKey", "regionSendKey", "regionSecret", "regionDataURI", "serverIP", "serverPort", "serverURI", "locX", "locY", "locZ", "eastOverrideHandle", "westOverrideHandle", "southOverrideHandle", "northOverrideHandle", "regionAssetURI", "regionAssetRecvKey", "regionAssetSendKey", "regionUserURI", "regionUserRecvKey", "regionUserSendKey", "regionMapTexture", "serverHttpPort", "serverRemotingPort", "owner_uuid", "originUUID")
152 SELECT cast(uuid as uuid), "regionHandle", "regionName", "regionRecvKey", "regionSendKey", "regionSecret", "regionDataURI", "serverIP", "serverPort", "serverURI", "locX", "locY", "locZ", "eastOverrideHandle", "westOverrideHandle", "southOverrideHandle", "northOverrideHandle", "regionAssetURI", "regionAssetRecvKey", "regionAssetSendKey", "regionUserURI", "regionUserRecvKey", "regionUserSendKey", cast("regionMapTexture" as uuid), "serverHttpPort", "serverRemotingPort", cast( "owner_uuid" as uuid), cast("originUUID" as uuid) FROM regions ;
153
154
155DROP TABLE regions;
156
157alter table Tmp_regions rename to regions;
158
159ALTER TABLE regions ADD CONSTRAINT
160 PK__regions__uuid PRIMARY KEY
161 (
162 uuid
163 );
164
165CREATE INDEX IX_regions_name ON regions
166 (
167 "regionName"
168 );
169
170CREATE INDEX IX_regions_handle ON regions
171 (
172 "regionHandle"
173 );
174
175CREATE INDEX IX_regions_override ON regions
176 (
177 "eastOverrideHandle",
178 "westOverrideHandle",
179 "southOverrideHandle",
180 "northOverrideHandle"
181 );
182
183COMMIT;
184
185
186:VERSION 5
187
188BEGIN TRANSACTION;
189
190ALTER TABLE regions ADD access int default 0;
191
192COMMIT;
193
194
195:VERSION 6
196
197BEGIN TRANSACTION;
198
199ALTER TABLE regions ADD "ScopeID" uuid default '00000000-0000-0000-0000-000000000000';
200ALTER TABLE regions alter column "owner_uuid" set DEFAULT ('00000000-0000-0000-0000-000000000000');
201ALTER TABLE regions ADD "sizeX" integer not null default 0;
202ALTER TABLE regions ADD "sizeY" integer not null default 0;
203
204COMMIT;
205
206
207:VERSION 7
208
209BEGIN TRANSACTION;
210
211ALTER TABLE regions ADD "flags" integer NOT NULL DEFAULT 0;
212CREATE INDEX flags ON regions("flags");
213ALTER TABLE regions ADD "last_seen" integer NOT NULL DEFAULT 0;
214ALTER TABLE regions ADD "PrincipalID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
215ALTER TABLE regions ADD "Token" varchar(255) NOT NULL DEFAULT 0;
216
217COMMIT;
218
219:VERSION 8
220
221BEGIN TRANSACTION;
222ALTER TABLE regions ALTER COLUMN "regionName" type VarChar(128) ;
223
224DROP INDEX IX_regions_name;
225ALTER TABLE regions ALTER COLUMN "regionName" type VarChar(128),
226 ALTER COLUMN "regionName" SET NOT NULL;
227
228CREATE INDEX IX_regions_name ON regions
229 (
230 "regionName"
231 );
232
233COMMIT;
234
235:VERSION 9
236
237BEGIN TRANSACTION;
238
239ALTER TABLE regions ADD "parcelMapTexture" uuid NULL;
240
241COMMIT;
242
diff --git a/OpenSim/Data/PGSQL/Resources/GridUserStore.migrations b/OpenSim/Data/PGSQL/Resources/GridUserStore.migrations
new file mode 100644
index 0000000..d37c4f6d
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/GridUserStore.migrations
@@ -0,0 +1,60 @@
1:VERSION 1 # --------------------------
2
3BEGIN TRANSACTION;
4
5CREATE TABLE GridUser (
6 "UserID" VARCHAR(255) NOT NULL Primary Key,
7 "HomeRegionID" CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
8 "HomePosition" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
9 "HomeLookAt" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
10 "LastRegionID" CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
11 "LastPosition" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
12 "LastLookAt" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
13 "Online" CHAR(5) NOT NULL DEFAULT 'false',
14 "Login" CHAR(16) NOT NULL DEFAULT '0',
15 "Logout" CHAR(16) NOT NULL DEFAULT '0'
16) ;
17
18COMMIT;
19
20:VERSION 2 # --------------------------
21
22BEGIN TRANSACTION;
23
24CREATE TABLE GridUser_tmp (
25 "UserID" VARCHAR(255) NOT NULL PRIMARY KEY,
26 "HomeRegionID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
27 "HomePosition" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
28 "HomeLookAt" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
29 "LastRegionID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
30 "LastPosition" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
31 "LastLookAt" CHAR(64) NOT NULL DEFAULT '<0,0,0>',
32 "Online" CHAR(5) NOT NULL DEFAULT 'false',
33 "Login" CHAR(16) NOT NULL DEFAULT '0',
34 "Logout" CHAR(16) NOT NULL DEFAULT '0'
35 );
36
37COMMIT;
38
39
40INSERT INTO GridUser_tmp ("UserID"
41 ,"HomeRegionID"
42 ,"HomePosition"
43 ,"HomeLookAt"
44 ,"LastRegionID"
45 ,"LastPosition"
46 ,"LastLookAt"
47 ,"Online"
48 ,"Login"
49 ,"Logout")
50 SELECT "UserID", cast("HomeRegionID" as uuid), "HomePosition" ,"HomeLookAt" , cast("LastRegionID" as uuid),
51 "LastPosition"
52 ,"LastLookAt"
53 ,"Online"
54 ,"Login"
55 ,"Logout" FROM GridUser;
56
57DROP TABLE GridUser;
58
59alter table GridUser_tmp rename to GridUser;
60
diff --git a/OpenSim/Data/PGSQL/Resources/HGTravelStore.migrations b/OpenSim/Data/PGSQL/Resources/HGTravelStore.migrations
new file mode 100644
index 0000000..adf126d
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/HGTravelStore.migrations
@@ -0,0 +1,17 @@
1:VERSION 1 # --------------------------
2
3BEGIN;
4
5CREATE TABLE hg_traveling_data (
6 "SessionID" VARCHAR(36) NOT NULL Primary Key,
7 "UserID" VARCHAR(36) NOT NULL,
8 "GridExternalName" VARCHAR(255) NOT NULL DEFAULT '',
9 "ServiceToken" VARCHAR(255) NOT NULL DEFAULT '',
10 "ClientIPAddress" VARCHAR(16) NOT NULL DEFAULT '',
11 "MyIPAddress" VARCHAR(16) NOT NULL DEFAULT '',
12 "TMStamp" timestamp NOT NULL default now()
13);
14
15
16COMMIT;
17
diff --git a/OpenSim/Data/PGSQL/Resources/IM_Store.migrations b/OpenSim/Data/PGSQL/Resources/IM_Store.migrations
new file mode 100644
index 0000000..70dc011
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/IM_Store.migrations
@@ -0,0 +1,26 @@
1:VERSION 1 # --------------------------
2
3BEGIN Transaction;
4
5Create Sequence im_offiline_id increment by 1 start with 1;
6
7CREATE TABLE im_offline (
8 "ID" integer PRIMARY KEY NOT NULL DEFAULT nextval('im_offiline_id') ,
9 "PrincipalID" char(36) NOT NULL default '',
10 "Message" text NOT NULL,
11 "TMStamp" timestamp NOT NULL default now()
12);
13
14COMMIT;
15
16:VERSION 2 # --------------------------
17
18BEGIN;
19
20/*
21INSERT INTO `im_offline` SELECT * from `diva_im_offline`;
22DROP TABLE `diva_im_offline`;
23DELETE FROM `migrations` WHERE name='diva_im_Store';
24*/
25
26COMMIT;
diff --git a/OpenSim/Data/PGSQL/Resources/InventoryStore.migrations b/OpenSim/Data/PGSQL/Resources/InventoryStore.migrations
new file mode 100644
index 0000000..8f7982a
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/InventoryStore.migrations
@@ -0,0 +1,220 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE inventoryfolders (
6 "folderID" varchar(36) NOT NULL default '' PRIMARY KEY,
7 "agentID" varchar(36) default NULL,
8 "parentFolderID" varchar(36) default NULL,
9 "folderName" varchar(64) default NULL,
10 "type" smallint NOT NULL default 0,
11 "version" int NOT NULL default 0
12);
13
14
15CREATE INDEX owner ON inventoryfolders
16(
17 "agentID" ASC
18);
19
20CREATE INDEX parent ON inventoryfolders
21(
22 "parentFolderID" ASC
23);
24
25
26CREATE TABLE inventoryitems (
27 "inventoryID" varchar(36) NOT NULL default '' Primary Key,
28 "assetID" varchar(36) default NULL,
29 "assetType" int default NULL,
30 "parentFolderID" varchar(36) default NULL,
31 "avatarID" varchar(36) default NULL,
32 "inventoryName" varchar(64) default NULL,
33 "inventoryDescription" varchar(128) default NULL,
34 "inventoryNextPermissions" int default NULL,
35 "inventoryCurrentPermissions" int default NULL,
36 "invType" int default NULL,
37 "creatorID" varchar(36) default NULL,
38 "inventoryBasePermissions" int NOT NULL default 0,
39 "inventoryEveryOnePermissions" int NOT NULL default 0,
40 "salePrice" int default NULL,
41 "saleType" smallint default NULL,
42 "creationDate" int default NULL,
43 "groupID" varchar(36) default NULL,
44 "groupOwned" boolean default NULL,
45 "flags" int default NULL
46);
47
48
49CREATE INDEX ii_owner ON inventoryitems
50(
51 "avatarID" ASC
52);
53
54CREATE INDEX ii_folder ON inventoryitems
55(
56 "parentFolderID" ASC
57);
58
59COMMIT;
60
61
62:VERSION 2
63
64BEGIN TRANSACTION;
65
66ALTER TABLE inventoryitems ADD "inventoryGroupPermissions" INTEGER NOT NULL default 0;
67
68COMMIT;
69
70:VERSION 3
71
72/* To prevent any potential data loss issues, you should review this script in detail before running it outside the cotext of the database designer.*/
73BEGIN TRANSACTION;
74
75CREATE TABLE Tmp_inventoryfolders
76 (
77 "folderID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
78 "agentID" uuid NULL DEFAULT (NULL),
79 "parentFolderID" uuid NULL DEFAULT (NULL),
80 "folderName" varchar(64) NULL DEFAULT (NULL),
81 "type" smallint NOT NULL DEFAULT ((0)),
82 "version" int NOT NULL DEFAULT ((0))
83 );
84
85 INSERT INTO Tmp_inventoryfolders ("folderID", "agentID", "parentFolderID", "folderName", type, version)
86 SELECT cast("folderID" as uuid), cast("agentID" as uuid), cast("parentFolderID" as uuid), "folderName", "type", "version"
87 FROM inventoryfolders;
88
89DROP TABLE inventoryfolders;
90
91alter table Tmp_inventoryfolders rename to inventoryfolders;
92
93ALTER TABLE inventoryfolders ADD CONSTRAINT
94 PK__inventor__C2FABFB3173876EA PRIMARY KEY
95 (
96 "folderID"
97 );
98
99CREATE INDEX owner ON inventoryfolders
100 (
101 "agentID"
102 );
103
104CREATE INDEX parent ON inventoryfolders
105 (
106 "parentFolderID"
107 );
108
109COMMIT;
110
111
112:VERSION 4
113
114BEGIN TRANSACTION;
115
116CREATE TABLE Tmp_inventoryitems
117 (
118 "inventoryID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
119 "assetID" uuid NULL DEFAULT (NULL),
120 "assetType" int NULL DEFAULT (NULL),
121 "parentFolderID" uuid NULL DEFAULT (NULL),
122 "avatarID" uuid NULL DEFAULT (NULL),
123 "inventoryName" varchar(64) NULL DEFAULT (NULL),
124 "inventoryDescription" varchar(128) NULL DEFAULT (NULL),
125 "inventoryNextPermissions" int NULL DEFAULT (NULL),
126 "inventoryCurrentPermissions" int NULL DEFAULT (NULL),
127 "invType" int NULL DEFAULT (NULL),
128 "creatorID" uuid NULL DEFAULT (NULL),
129 "inventoryBasePermissions" int NOT NULL DEFAULT ((0)),
130 "inventoryEveryOnePermissions" int NOT NULL DEFAULT ((0)),
131 "salePrice" int NULL DEFAULT (NULL),
132 "SaleType" smallint NULL DEFAULT (NULL),
133 "creationDate" int NULL DEFAULT (NULL),
134 "groupID" uuid NULL DEFAULT (NULL),
135 "groupOwned" boolean NULL DEFAULT (NULL),
136 "flags" int NULL DEFAULT (NULL),
137 "inventoryGroupPermissions" int NOT NULL DEFAULT ((0))
138 );
139
140
141 INSERT INTO Tmp_inventoryitems ("inventoryID", "assetID", "assetType", "parentFolderID", "avatarID", "inventoryName", "inventoryDescription", "inventoryNextPermissions", "inventoryCurrentPermissions", "invType", "creatorID", "inventoryBasePermissions", "inventoryEveryOnePermissions", "salePrice", "SaleType", "creationDate", "groupID", "groupOwned", "flags", "inventoryGroupPermissions")
142 SELECT cast("inventoryID" as uuid), cast("assetID" as uuid), "assetType", cast("parentFolderID" as uuid), cast("avatarID" as uuid), "inventoryName", "inventoryDescription", "inventoryNextPermissions", "inventoryCurrentPermissions", "invType", cast("creatorID" as uuid), "inventoryBasePermissions", "inventoryEveryOnePermissions", "salePrice", "SaleType", "creationDate", cast("groupID" as uuid), "groupOwned", "flags", "inventoryGroupPermissions"
143 FROM inventoryitems ;
144
145DROP TABLE inventoryitems;
146
147alter table Tmp_inventoryitems rename to inventoryitems;
148
149ALTER TABLE inventoryitems ADD CONSTRAINT
150 PK__inventor__C4B7BC2220C1E124 PRIMARY KEY
151 (
152 "inventoryID"
153 );
154
155
156CREATE INDEX ii2_owner ON inventoryitems
157 (
158 "avatarID"
159 );
160
161CREATE INDEX ii2_folder ON inventoryitems
162 (
163 "parentFolderID"
164 );
165
166COMMIT;
167
168:VERSION 5
169
170
171BEGIN TRANSACTION;
172
173-- # Restoring defaults:
174-- # NOTE: "inventoryID" does NOT need one: it's NOT NULL PK and a unique Guid must be provided every time anyway!
175
176alter table inventoryitems
177 alter column "inventoryBasePermissions" set default 0;
178alter table inventoryitems
179 alter column "inventoryEveryOnePermissions" set default 0;
180alter table inventoryitems
181 alter column "inventoryGroupPermissions" set default 0 ;
182
183COMMIT ;
184
185:VERSION 7
186
187BEGIN TRANSACTION;
188
189-- # "creatorID" goes back to VARCHAR(36) (???)
190
191alter table inventoryitems
192 alter column "creatorID" type varchar(36);
193
194COMMIT ;
195
196:VERSION 8
197
198ALTER TABLE inventoryitems
199 alter column "creatorID" set DEFAULT '00000000-0000-0000-0000-000000000000';
200
201
202:VERSION 9
203
204BEGIN TRANSACTION;
205
206--# "creatorID" goes up to VARCHAR(255)
207
208alter table inventoryitems
209 alter column "creatorID" type varchar(255);
210
211Commit;
212
213:VERSION 10
214
215BEGIN TRANSACTION;
216
217Alter table inventoryitems Rename Column "SaleType" to "saleType";
218
219Commit;
220
diff --git a/OpenSim/Data/PGSQL/Resources/LogStore.migrations b/OpenSim/Data/PGSQL/Resources/LogStore.migrations
new file mode 100644
index 0000000..83727c6
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/LogStore.migrations
@@ -0,0 +1,16 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE logs (
6 "logID" int NOT NULL Primary Key,
7 "target" varchar(36) default NULL,
8 "server" varchar(64) default NULL,
9 "method" varchar(64) default NULL,
10 "arguments" varchar(255) default NULL,
11 "priority" int default NULL,
12 "message" text
13);
14
15COMMIT;
16
diff --git a/OpenSim/Data/PGSQL/Resources/Presence.migrations b/OpenSim/Data/PGSQL/Resources/Presence.migrations
new file mode 100644
index 0000000..684faa2
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/Presence.migrations
@@ -0,0 +1,30 @@
1:VERSION 1
2
3BEGIN TRANSACTION;
4
5CREATE TABLE Presence (
6"UserID" varchar(255) NOT NULL,
7"RegionID" uuid NOT NULL,
8"SessionID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
9"SecureSessionID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'
10);
11
12
13COMMIT;
14
15:VERSION 2
16
17BEGIN TRANSACTION;
18
19CREATE UNIQUE INDEX SessionID ON Presence("SessionID");
20CREATE INDEX UserID ON Presence("UserID");
21
22COMMIT;
23
24:VERSION 2
25
26BEGIN TRANSACTION;
27
28ALTER TABLE Presence ADD "LastSeen" Timestamp;
29
30COMMIT;
diff --git a/OpenSim/Data/PGSQL/Resources/RegionStore.migrations b/OpenSim/Data/PGSQL/Resources/RegionStore.migrations
new file mode 100644
index 0000000..1e33027
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/RegionStore.migrations
@@ -0,0 +1,1154 @@
1begin transaction ;
2:VERSION 1
3
4CREATE TABLE prims(
5 "UUID" varchar(255) NOT NULL Primary key,
6 "RegionUUID" varchar(255) NULL,
7 "ParentID" int NULL,
8 "CreationDate" int NULL,
9 "Name" varchar(255) NULL,
10 "SceneGroupID" varchar(255) NULL,
11 "Text" varchar(255) NULL,
12 "Description" varchar(255) NULL,
13 "SitName" varchar(255) NULL,
14 "TouchName" varchar(255) NULL,
15 "ObjectFlags" int NULL,
16 "CreatorID" varchar(255) NULL,
17 "OwnerID" varchar(255) NULL,
18 "GroupID" varchar(255) NULL,
19 "LastOwnerID" varchar(255) NULL,
20 "OwnerMask" int NULL,
21 "NextOwnerMask" int NULL,
22 "GroupMask" int NULL,
23 "EveryoneMask" int NULL,
24 "BaseMask" int NULL,
25 "PositionX" double precision NULL,
26 "PositionY" double precision NULL,
27 "PositionZ" double precision NULL,
28 "GroupPositionX" double precision NULL,
29 "GroupPositionY" double precision NULL,
30 "GroupPositionZ" double precision NULL,
31 "VelocityX" double precision NULL,
32 "VelocityY" double precision NULL,
33 "VelocityZ" double precision NULL,
34 "AngularVelocityX" double precision NULL,
35 "AngularVelocityY" double precision NULL,
36 "AngularVelocityZ" double precision NULL,
37 "AccelerationX" double precision NULL,
38 "AccelerationY" double precision NULL,
39 "AccelerationZ" double precision NULL,
40 "RotationX" double precision NULL,
41 "RotationY" double precision NULL,
42 "RotationZ" double precision NULL,
43 "RotationW" double precision NULL,
44 "SitTargetOffsetX" double precision NULL,
45 "SitTargetOffsetY" double precision NULL,
46 "SitTargetOffsetZ" double precision NULL,
47 "SitTargetOrientW" double precision NULL,
48 "SitTargetOrientX" double precision NULL,
49 "SitTargetOrientY" double precision NULL,
50 "SitTargetOrientZ" double precision NULL
51 );
52
53CREATE TABLE primshapes(
54 "UUID" varchar(255) NOT NULL primary key,
55 "Shape" int NULL,
56 "ScaleX" double precision NULL,
57 "ScaleY" double precision NULL,
58 "ScaleZ" double precision NULL,
59 "PCode" int NULL,
60 "PathBegin" int NULL,
61 "PathEnd" int NULL,
62 "PathScaleX" int NULL,
63 "PathScaleY" int NULL,
64 "PathShearX" int NULL,
65 "PathShearY" int NULL,
66 "PathSkew" int NULL,
67 "PathCurve" int NULL,
68 "PathRadiusOffset" int NULL,
69 "PathRevolutions" int NULL,
70 "PathTaperX" int NULL,
71 "PathTaperY" int NULL,
72 "PathTwist" int NULL,
73 "PathTwistBegin" int NULL,
74 "ProfileBegin" int NULL,
75 "ProfileEnd" int NULL,
76 "ProfileCurve" int NULL,
77 "ProfileHollow" int NULL,
78 "State" int NULL,
79 "Texture" bytea NULL,
80 "ExtraParams" bytea NULL
81 );
82
83CREATE TABLE primitems(
84 "itemID" varchar(255) NOT NULL primary key,
85 "primID" varchar(255) NULL,
86 "assetID" varchar(255) NULL,
87 "parentFolderID" varchar(255) NULL,
88 "invType" int NULL,
89 "assetType" int NULL,
90 "name" varchar(255) NULL,
91 "description" varchar(255) NULL,
92 "creationDate" varchar(255) NULL,
93 "creatorID" varchar(255) NULL,
94 "ownerID" varchar(255) NULL,
95 "lastOwnerID" varchar(255) NULL,
96 "groupID" varchar(255) NULL,
97 "nextPermissions" int NULL,
98 "currentPermissions" int NULL,
99 "basePermissions" int NULL,
100 "everyonePermissions" int NULL,
101 "groupPermissions" int NULL
102 );
103
104CREATE TABLE terrain(
105 "RegionUUID" varchar(255) NULL,
106 "Revision" int NULL,
107 "Heightfield" bytea NULL
108);
109
110
111CREATE TABLE land(
112 "UUID" varchar(255) NOT NULL primary key,
113 "RegionUUID" varchar(255) NULL,
114 "LocalLandID" int NULL,
115 "Bitmap" bytea NULL,
116 "Name" varchar(255) NULL,
117 "Description" varchar(255) NULL,
118 "OwnerUUID" varchar(255) NULL,
119 "IsGroupOwned" boolean NULL,
120 "Area" int NULL,
121 "AuctionID" int NULL,
122 "Category" int NULL,
123 "ClaimDate" int NULL,
124 "ClaimPrice" int NULL,
125 "GroupUUID" varchar(255) NULL,
126 "SalePrice" int NULL,
127 "LandStatus" int NULL,
128 "LandFlags" int NULL,
129 "LandingType" int NULL,
130 "MediaAutoScale" int NULL,
131 "MediaTextureUUID" varchar(255) NULL,
132 "MediaURL" varchar(255) NULL,
133 "MusicURL" varchar(255) NULL,
134 "PassHours" double precision NULL,
135 "PassPrice" int NULL,
136 "SnapshotUUID" varchar(255) NULL,
137 "UserLocationX" double precision NULL,
138 "UserLocationY" double precision NULL,
139 "UserLocationZ" double precision NULL,
140 "UserLookAtX" double precision NULL,
141 "UserLookAtY" double precision NULL,
142 "UserLookAtZ" double precision NULL
143);
144
145Create index on land (lower("Name"));
146
147CREATE TABLE landaccesslist(
148 "LandUUID" varchar(255) NULL,
149 "AccessUUID" varchar(255) NULL,
150 "Flags" int NULL
151);
152
153COMMIT;
154
155:VERSION 2
156
157BEGIN TRANSACTION;
158
159CREATE TABLE regionban (
160 "regionUUID" VARCHAR(36) NOT NULL,
161 "bannedUUID" VARCHAR(36) NOT NULL,
162 "bannedIp" VARCHAR(16) NOT NULL,
163 "bannedIpHostMask" VARCHAR(16) NOT NULL
164 );
165
166create table regionsettings (
167 "regionUUID" varchar(36) not null primary key,
168 "block_terraform" boolean not null,
169 "block_fly" boolean not null,
170 "allow_damage" boolean not null,
171 "restrict_pushing" boolean not null,
172 "allow_land_resell" boolean not null,
173 "allow_land_join_divide" boolean not null,
174 "block_show_in_search" boolean not null,
175 "agent_limit" int not null,
176 "object_bonus" double precision not null,
177 "maturity" int not null,
178 "disable_scripts" boolean not null,
179 "disable_collisions" boolean not null,
180 "disable_physics" boolean not null,
181 "terrain_texture_1" varchar(36) not null,
182 "terrain_texture_2" varchar(36) not null,
183 "terrain_texture_3" varchar(36) not null,
184 "terrain_texture_4" varchar(36) not null,
185 "elevation_1_nw" double precision not null,
186 "elevation_2_nw" double precision not null,
187 "elevation_1_ne" double precision not null,
188 "elevation_2_ne" double precision not null,
189 "elevation_1_se" double precision not null,
190 "elevation_2_se" double precision not null,
191 "elevation_1_sw" double precision not null,
192 "elevation_2_sw" double precision not null,
193 "water_height" double precision not null,
194 "terrain_raise_limit" double precision not null,
195 "terrain_lower_limit" double precision not null,
196 "use_estate_sun" boolean not null,
197 "fixed_sun" boolean not null,
198 "sun_position" double precision not null,
199 "covenant" varchar(36) default NULL,
200 "Sandbox" boolean NOT NULL
201 );
202
203COMMIT;
204
205:VERSION 3
206
207BEGIN TRANSACTION;
208
209CREATE TABLE Tmp_prims
210 (
211 "UUID" varchar(36) NOT NULL ,
212 "RegionUUID" varchar(36) NULL,
213 "ParentID" int NULL,
214 "CreationDate" int NULL,
215 "Name" varchar(255) NULL,
216 "SceneGroupID" varchar(36) NULL,
217 "Text" varchar(255) NULL,
218 "Description" varchar(255) NULL,
219 "SitName" varchar(255) NULL,
220 "TouchName" varchar(255) NULL,
221 "ObjectFlags" int NULL,
222 "CreatorID" varchar(36) NULL,
223 "OwnerID" varchar(36) NULL,
224 "GroupID" varchar(36) NULL,
225 "LastOwnerID" varchar(36) NULL,
226 "OwnerMask" int NULL,
227 "NextOwnerMask" int NULL,
228 "GroupMask" int NULL,
229 "EveryoneMask" int NULL,
230 "BaseMask" int NULL,
231 "PositionX" double precision NULL,
232 "PositionY" double precision NULL,
233 "PositionZ" double precision NULL,
234 "GroupPositionX" double precision NULL,
235 "GroupPositionY" double precision NULL,
236 "GroupPositionZ" double precision NULL,
237 "VelocityX" double precision NULL,
238 "VelocityY" double precision NULL,
239 "VelocityZ" double precision NULL,
240 "AngularVelocityX" double precision NULL,
241 "AngularVelocityY" double precision NULL,
242 "AngularVelocityZ" double precision NULL,
243 "AccelerationX" double precision NULL,
244 "AccelerationY" double precision NULL,
245 "AccelerationZ" double precision NULL,
246 "RotationX" double precision NULL,
247 "RotationY" double precision NULL,
248 "RotationZ" double precision NULL,
249 "RotationW" double precision NULL,
250 "SitTargetOffsetX" double precision NULL,
251 "SitTargetOffsetY" double precision NULL,
252 "SitTargetOffsetZ" double precision NULL,
253 "SitTargetOrientW" double precision NULL,
254 "SitTargetOrientX" double precision NULL,
255 "SitTargetOrientY" double precision NULL,
256 "SitTargetOrientZ" double precision NULL
257 );
258
259INSERT INTO Tmp_prims ("UUID", "RegionUUID", "ParentID", "CreationDate", "Name", "SceneGroupID", "Text", "Description", "SitName", "TouchName", "ObjectFlags", "CreatorID", "OwnerID", "GroupID", "LastOwnerID", "OwnerMask", "NextOwnerMask", "GroupMask", "EveryoneMask", "BaseMask", "PositionX", "PositionY", "PositionZ", "GroupPositionX", "GroupPositionY", "GroupPositionZ", "VelocityX", "VelocityY", "VelocityZ", "AngularVelocityX", "AngularVelocityY", "AngularVelocityZ", "AccelerationX", "AccelerationY", "AccelerationZ", "RotationX", "RotationY", "RotationZ", "RotationW", "SitTargetOffsetX", "SitTargetOffsetY", "SitTargetOffsetZ", "SitTargetOrientW", "SitTargetOrientX", "SitTargetOrientY", "SitTargetOrientZ")
260 SELECT cast("UUID" as varchar(36)), cast("RegionUUID" as varchar(36)), "ParentID", "CreationDate", "Name", cast("SceneGroupID" as varchar(36)), "Text", "Description", "SitName", "TouchName", "ObjectFlags", cast("CreatorID" as varchar(36)), cast("OwnerID" as varchar(36)), cast( "GroupID" as varchar(36)), cast("LastOwnerID" as varchar(36)), "OwnerMask", "NextOwnerMask", "GroupMask", "EveryoneMask", "BaseMask", "PositionX", "PositionY", "PositionZ", "GroupPositionX", "GroupPositionY", "GroupPositionZ", "VelocityX", "VelocityY", "VelocityZ", "AngularVelocityX", "AngularVelocityY", "AngularVelocityZ", "AccelerationX", "AccelerationY", "AccelerationZ", "RotationX", "RotationY", "RotationZ", "RotationW", "SitTargetOffsetX", "SitTargetOffsetY", "SitTargetOffsetZ", "SitTargetOrientW", "SitTargetOrientX", "SitTargetOrientY", "SitTargetOrientZ"
261 FROM prims ;
262
263DROP TABLE prims;
264
265alter table Tmp_prims rename to prims;
266
267
268ALTER TABLE prims ADD CONSTRAINT
269 PK__prims__10566F31 PRIMARY KEY
270 (
271 "UUID"
272 );
273
274COMMIT;
275
276:VERSION 4
277
278BEGIN TRANSACTION;
279
280CREATE TABLE Tmp_primitems
281 (
282 "itemID" varchar(36) NOT NULL,
283 "primID" varchar(36) NULL,
284 "assetID" varchar(36) NULL,
285 "parentFolderID" varchar(36) NULL,
286 "invType" int NULL,
287 "assetType" int NULL,
288 "name" varchar(255) NULL,
289 "description" varchar(255) NULL,
290 "creationDate" varchar(255) NULL,
291 "creatorID" varchar(36) NULL,
292 "ownerID" varchar(36) NULL,
293 "lastOwnerID" varchar(36) NULL,
294 "groupID" varchar(36) NULL,
295 "nextPermissions" int NULL,
296 "currentPermissions" int NULL,
297 "basePermissions" int NULL,
298 "everyonePermissions" int NULL,
299 "groupPermissions" int NULL
300 );
301
302INSERT INTO Tmp_primitems ("itemID", "primID", "assetID", "parentFolderID", "invType", "assetType", "name", "description", "creationDate", "creatorID", "ownerID", "lastOwnerID", "groupID", "nextPermissions", "currentPermissions", "basePermissions", "everyonePermissions", "groupPermissions")
303 SELECT cast("itemID" as varchar(36)), cast("primID" as varchar(36)), cast("assetID" as varchar(36)), cast( "parentFolderID" as varchar(36)), "invType", "assetType", "name", "description", "creationDate", cast( "creatorID" as varchar(36)), cast("ownerID" as varchar(36)), cast("lastOwnerID" as varchar(36)), cast("groupID" as varchar(36)), "nextPermissions", "currentPermissions", "basePermissions", "everyonePermissions", "groupPermissions"
304 from primitems;
305
306DROP TABLE primitems;
307
308alter table Tmp_primitems rename to primitems;
309
310ALTER TABLE primitems ADD CONSTRAINT
311 PK__primitems__0A688BB1 PRIMARY KEY
312 (
313 "itemID"
314 );
315
316
317COMMIT;
318
319
320:VERSION 5
321
322BEGIN TRANSACTION;
323
324CREATE TABLE Tmp_primshapes
325 (
326 "UUID" varchar(36) NOT NULL,
327 "Shape" int NULL,
328 "ScaleX" double precision NULL,
329 "ScaleY" double precision NULL,
330 "ScaleZ" double precision NULL,
331 "PCode" int NULL,
332 "PathBegin" int NULL,
333 "PathEnd" int NULL,
334 "PathScaleX" int NULL,
335 "PathScaleY" int NULL,
336 "PathShearX" int NULL,
337 "PathShearY" int NULL,
338 "PathSkew" int NULL,
339 "PathCurve" int NULL,
340 "PathRadiusOffset" int NULL,
341 "PathRevolutions" int NULL,
342 "PathTaperX" int NULL,
343 "PathTaperY" int NULL,
344 "PathTwist" int NULL,
345 "PathTwistBegin" int NULL,
346 "ProfileBegin" int NULL,
347 "ProfileEnd" int NULL,
348 "ProfileCurve" int NULL,
349 "ProfileHollow" int NULL,
350 "State" int NULL,
351 "Texture" bytea NULL,
352 "ExtraParams" bytea NULL
353 ) ;
354
355INSERT INTO Tmp_primshapes ("UUID", "Shape", "ScaleX", "ScaleY", "ScaleZ", "PCode", "PathBegin", "PathEnd", "PathScaleX", "PathScaleY", "PathShearX", "PathShearY", "PathSkew", "PathCurve", "PathRadiusOffset", "PathRevolutions", "PathTaperX", "PathTaperY", "PathTwist", "PathTwistBegin", "ProfileBegin", "ProfileEnd", "ProfileCurve", "ProfileHollow", "State", "Texture", "ExtraParams")
356 SELECT cast("UUID" as varchar(36)), "Shape", "ScaleX", "ScaleY", "ScaleZ", "PCode", "PathBegin", "PathEnd", "PathScaleX", "PathScaleY", "PathShearX", "PathShearY", "PathSkew", "PathCurve", "PathRadiusOffset", "PathRevolutions", "PathTaperX", "PathTaperY", "PathTwist", "PathTwistBegin", "ProfileBegin", "ProfileEnd", "ProfileCurve", "ProfileHollow", "State", "Texture", "ExtraParams"
357 FROM primshapes;
358
359DROP TABLE primshapes;
360
361alter table Tmp_primshapes rename to primshapes;
362
363ALTER TABLE primshapes ADD CONSTRAINT
364 PK__primshapes__0880433F PRIMARY KEY
365 (
366 "UUID"
367 ) ;
368
369COMMIT;
370
371
372:VERSION 6
373
374BEGIN TRANSACTION;
375
376ALTER TABLE prims ADD "PayPrice" int not null default 0;
377ALTER TABLE prims ADD "PayButton1" int not null default 0;
378ALTER TABLE prims ADD "PayButton2" int not null default 0;
379ALTER TABLE prims ADD "PayButton3" int not null default 0;
380ALTER TABLE prims ADD "PayButton4" int not null default 0;
381ALTER TABLE prims ADD "LoopedSound" varchar(36) not null default '00000000-0000-0000-0000-000000000000';
382ALTER TABLE prims ADD "LoopedSoundGain" double precision not null default 0.0;
383ALTER TABLE prims ADD "TextureAnimation" bytea;
384ALTER TABLE prims ADD "OmegaX" double precision not null default 0.0;
385ALTER TABLE prims ADD "OmegaY" double precision not null default 0.0;
386ALTER TABLE prims ADD "OmegaZ" double precision not null default 0.0;
387ALTER TABLE prims ADD "CameraEyeOffsetX" double precision not null default 0.0;
388ALTER TABLE prims ADD "CameraEyeOffsetY" double precision not null default 0.0;
389ALTER TABLE prims ADD "CameraEyeOffsetZ" double precision not null default 0.0;
390ALTER TABLE prims ADD "CameraAtOffsetX" double precision not null default 0.0;
391ALTER TABLE prims ADD "CameraAtOffsetY" double precision not null default 0.0;
392ALTER TABLE prims ADD "CameraAtOffsetZ" double precision not null default 0.0;
393ALTER TABLE prims ADD "ForceMouselook" smallint not null default 0;
394ALTER TABLE prims ADD "ScriptAccessPin" int not null default 0;
395ALTER TABLE prims ADD "AllowedDrop" smallint not null default 0;
396ALTER TABLE prims ADD "DieAtEdge" smallint not null default 0;
397ALTER TABLE prims ADD "SalePrice" int not null default 10;
398ALTER TABLE prims ADD "SaleType" smallint not null default 0;
399
400ALTER TABLE primitems add "flags" integer not null default 0;
401
402ALTER TABLE land ADD "AuthbuyerID" varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000';
403
404CREATE index prims_regionuuid on prims("RegionUUID");
405CREATE index prims_parentid on prims("ParentID");
406
407CREATE index primitems_primid on primitems("primID");
408
409COMMIT;
410
411
412:VERSION 7
413
414BEGIN TRANSACTION;
415
416ALTER TABLE prims ADD "ColorR" int not null default 0;
417ALTER TABLE prims ADD "ColorG" int not null default 0;
418ALTER TABLE prims ADD "ColorB" int not null default 0;
419ALTER TABLE prims ADD "ColorA" int not null default 0;
420ALTER TABLE prims ADD "ParticleSystem" bytea;
421ALTER TABLE prims ADD "ClickAction" smallint NOT NULL default 0;
422
423COMMIT;
424
425
426:VERSION 8
427
428BEGIN TRANSACTION;
429
430ALTER TABLE land ADD "OtherCleanTime" integer NOT NULL default 0;
431ALTER TABLE land ADD "Dwell" integer NOT NULL default 0;
432
433COMMIT;
434
435:VERSION 9
436
437BEGIN TRANSACTION;
438
439ALTER TABLE prims ADD "Material" smallint NOT NULL default 3;
440
441COMMIT;
442
443
444:VERSION 10
445
446BEGIN TRANSACTION;
447
448ALTER TABLE regionsettings ADD "sunvectorx" double precision NOT NULL default 0;
449ALTER TABLE regionsettings ADD "sunvectory" double precision NOT NULL default 0;
450ALTER TABLE regionsettings ADD "sunvectorz" double precision NOT NULL default 0;
451
452COMMIT;
453
454
455:VERSION 11
456
457BEGIN TRANSACTION;
458
459ALTER TABLE prims ADD "CollisionSound" char(36) not null default '00000000-0000-0000-0000-000000000000';
460ALTER TABLE prims ADD "CollisionSoundVolume" double precision not null default 0.0;
461
462COMMIT;
463
464
465:VERSION 12
466
467BEGIN TRANSACTION;
468
469ALTER TABLE prims ADD "LinkNumber" integer not null default 0;
470
471COMMIT;
472
473
474:VERSION 13
475
476BEGIN TRANSACTION;
477
478CREATE TABLE Tmp_prims
479 (
480 "UUID" uuid NOT NULL,
481 "RegionUUID" uuid NULL,
482 "ParentID" int NULL,
483 "CreationDate" int NULL,
484 "Name" varchar(255) NULL,
485 "SceneGroupID" uuid NULL,
486 "Text" varchar(255) NULL,
487 "Description" varchar(255) NULL,
488 "SitName" varchar(255) NULL,
489 "TouchName" varchar(255) NULL,
490 "ObjectFlags" int NULL,
491 "CreatorID" uuid NULL,
492 "OwnerID" uuid NULL,
493 "GroupID" uuid NULL,
494 "LastOwnerID" uuid NULL,
495 "OwnerMask" int NULL,
496 "NextOwnerMask" int NULL,
497 "GroupMask" int NULL,
498 "EveryoneMask" int NULL,
499 "BaseMask" int NULL,
500 "PositionX" double precision NULL,
501 "PositionY" double precision NULL,
502 "PositionZ" double precision NULL,
503 "GroupPositionX" double precision NULL,
504 "GroupPositionY" double precision NULL,
505 "GroupPositionZ" double precision NULL,
506 "VelocityX" double precision NULL,
507 "VelocityY" double precision NULL,
508 "VelocityZ" double precision NULL,
509 "AngularVelocityX" double precision NULL,
510 "AngularVelocityY" double precision NULL,
511 "AngularVelocityZ" double precision NULL,
512 "AccelerationX" double precision NULL,
513 "AccelerationY" double precision NULL,
514 "AccelerationZ" double precision NULL,
515 "RotationX" double precision NULL,
516 "RotationY" double precision NULL,
517 "RotationZ" double precision NULL,
518 "RotationW" double precision NULL,
519 "SitTargetOffsetX" double precision NULL,
520 "SitTargetOffsetY" double precision NULL,
521 "SitTargetOffsetZ" double precision NULL,
522 "SitTargetOrientW" double precision NULL,
523 "SitTargetOrientX" double precision NULL,
524 "SitTargetOrientY" double precision NULL,
525 "SitTargetOrientZ" double precision NULL,
526 "PayPrice" int NOT NULL DEFAULT ((0)),
527 "PayButton1" int NOT NULL DEFAULT ((0)),
528 "PayButton2" int NOT NULL DEFAULT ((0)),
529 "PayButton3" int NOT NULL DEFAULT ((0)),
530 "PayButton4" int NOT NULL DEFAULT ((0)),
531 "LoopedSound" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
532 "LoopedSoundGain" double precision NOT NULL DEFAULT ((0.0)),
533 "TextureAnimation" bytea NULL,
534 "OmegaX" double precision NOT NULL DEFAULT ((0.0)),
535 "OmegaY" double precision NOT NULL DEFAULT ((0.0)),
536 "OmegaZ" double precision NOT NULL DEFAULT ((0.0)),
537 "CameraEyeOffsetX" double precision NOT NULL DEFAULT ((0.0)),
538 "CameraEyeOffsetY" double precision NOT NULL DEFAULT ((0.0)),
539 "CameraEyeOffsetZ" double precision NOT NULL DEFAULT ((0.0)),
540 "CameraAtOffsetX" double precision NOT NULL DEFAULT ((0.0)),
541 "CameraAtOffsetY" double precision NOT NULL DEFAULT ((0.0)),
542 "CameraAtOffsetZ" double precision NOT NULL DEFAULT ((0.0)),
543 "ForceMouselook" smallint NOT NULL DEFAULT ((0)),
544 "ScriptAccessPin" int NOT NULL DEFAULT ((0)),
545 "AllowedDrop" smallint NOT NULL DEFAULT ((0)),
546 "DieAtEdge" smallint NOT NULL DEFAULT ((0)),
547 "SalePrice" int NOT NULL DEFAULT ((10)),
548 "SaleType" smallint NOT NULL DEFAULT ((0)),
549 "ColorR" int NOT NULL DEFAULT ((0)),
550 "ColorG" int NOT NULL DEFAULT ((0)),
551 "ColorB" int NOT NULL DEFAULT ((0)),
552 "ColorA" int NOT NULL DEFAULT ((0)),
553 "ParticleSystem" bytea NULL,
554 "ClickAction" smallint NOT NULL DEFAULT ((0)),
555 "Material" smallint NOT NULL DEFAULT ((3)),
556 "CollisionSound" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
557 "CollisionSoundVolume" double precision NOT NULL DEFAULT ((0.0)),
558 "LinkNumber" int NOT NULL DEFAULT ((0))
559 );
560
561INSERT INTO Tmp_prims ("UUID", "RegionUUID", "ParentID", "CreationDate", "Name", "SceneGroupID", "Text", "Description", "SitName", "TouchName", "ObjectFlags", "CreatorID", "OwnerID", "GroupID", "LastOwnerID", "OwnerMask", "NextOwnerMask", "GroupMask", "EveryoneMask", "BaseMask", "PositionX", "PositionY", "PositionZ", "GroupPositionX", "GroupPositionY", "GroupPositionZ", "VelocityX", "VelocityY", "VelocityZ", "AngularVelocityX", "AngularVelocityY", "AngularVelocityZ", "AccelerationX", "AccelerationY", "AccelerationZ", "RotationX", "RotationY", "RotationZ", "RotationW", "SitTargetOffsetX", "SitTargetOffsetY", "SitTargetOffsetZ", "SitTargetOrientW", "SitTargetOrientX", "SitTargetOrientY", "SitTargetOrientZ", "PayPrice", "PayButton1", "PayButton2", "PayButton3", "PayButton4", "LoopedSound", "LoopedSoundGain", "TextureAnimation", "OmegaX", "OmegaY", "OmegaZ", "CameraEyeOffsetX", "CameraEyeOffsetY", "CameraEyeOffsetZ", "CameraAtOffsetX", "CameraAtOffsetY", "CameraAtOffsetZ", "ForceMouselook", "ScriptAccessPin", "AllowedDrop", "DieAtEdge", "SalePrice", "SaleType", "ColorR", "ColorG", "ColorB", "ColorA", "ParticleSystem", "ClickAction", "Material", "CollisionSound", "CollisionSoundVolume", "LinkNumber")
562 SELECT cast("UUID" as uuid), cast("RegionUUID" as uuid), "ParentID", "CreationDate", "Name", cast("SceneGroupID" as uuid), "Text", "Description", "SitName", "TouchName", "ObjectFlags", cast("CreatorID" as uuid), cast("OwnerID" as uuid), cast("GroupID" as uuid), cast("LastOwnerID" as uuid), "OwnerMask", "NextOwnerMask", "GroupMask", "EveryoneMask", "BaseMask", "PositionX", "PositionY", "PositionZ", "GroupPositionX", "GroupPositionY", "GroupPositionZ", "VelocityX", "VelocityY", "VelocityZ", "AngularVelocityX", "AngularVelocityY", "AngularVelocityZ", "AccelerationX", "AccelerationY", "AccelerationZ", "RotationX", "RotationY", "RotationZ", "RotationW", "SitTargetOffsetX", "SitTargetOffsetY", "SitTargetOffsetZ", "SitTargetOrientW", "SitTargetOrientX", "SitTargetOrientY", "SitTargetOrientZ", "PayPrice", "PayButton1", "PayButton2", "PayButton3", "PayButton4", cast("LoopedSound" as uuid), "LoopedSoundGain", "TextureAnimation", "OmegaX", "OmegaY", "OmegaZ", "CameraEyeOffsetX", "CameraEyeOffsetY", "CameraEyeOffsetZ", "CameraAtOffsetX", "CameraAtOffsetY", "CameraAtOffsetZ", "ForceMouselook", "ScriptAccessPin", "AllowedDrop", "DieAtEdge", "SalePrice", "SaleType", "ColorR", "ColorG", "ColorB", "ColorA", "ParticleSystem", "ClickAction", "Material", cast("CollisionSound" as uuid), "CollisionSoundVolume", "LinkNumber"
563 FROM prims ;
564
565DROP TABLE prims;
566
567alter table Tmp_prims rename to prims;
568
569ALTER TABLE prims ADD CONSTRAINT
570 PK__prims__10566F31 PRIMARY KEY
571 (
572 "UUID"
573 );
574
575
576CREATE INDEX prims_regionuuid ON prims
577 (
578 "RegionUUID"
579 );
580
581CREATE INDEX prims_parentid ON prims
582 (
583 "ParentID"
584 );
585
586COMMIT;
587
588
589:VERSION 14
590
591BEGIN TRANSACTION;
592
593CREATE TABLE Tmp_primshapes
594 (
595 "UUID" uuid NOT NULL,
596 "Shape" int NULL,
597 "ScaleX" double precision NULL,
598 "ScaleY" double precision NULL,
599 "ScaleZ" double precision NULL,
600 "PCode" int NULL,
601 "PathBegin" int NULL,
602 "PathEnd" int NULL,
603 "PathScaleX" int NULL,
604 "PathScaleY" int NULL,
605 "PathShearX" int NULL,
606 "PathShearY" int NULL,
607 "PathSkew" int NULL,
608 "PathCurve" int NULL,
609 "PathRadiusOffset" int NULL,
610 "PathRevolutions" int NULL,
611 "PathTaperX" int NULL,
612 "PathTaperY" int NULL,
613 "PathTwist" int NULL,
614 "PathTwistBegin" int NULL,
615 "ProfileBegin" int NULL,
616 "ProfileEnd" int NULL,
617 "ProfileCurve" int NULL,
618 "ProfileHollow" int NULL,
619 "State" int NULL,
620 "Texture" bytea NULL,
621 "ExtraParams" bytea NULL
622 );
623
624INSERT INTO Tmp_primshapes ("UUID", "Shape", "ScaleX", "ScaleY", "ScaleZ", "PCode", "PathBegin", "PathEnd", "PathScaleX", "PathScaleY", "PathShearX", "PathShearY", "PathSkew", "PathCurve", "PathRadiusOffset", "PathRevolutions", "PathTaperX", "PathTaperY", "PathTwist", "PathTwistBegin", "ProfileBegin", "ProfileEnd", "ProfileCurve", "ProfileHollow", "State", "Texture", "ExtraParams")
625 SELECT cast("UUID" as uuid), "Shape", "ScaleX", "ScaleY", "ScaleZ", "PCode", "PathBegin", "PathEnd", "PathScaleX", "PathScaleY", "PathShearX", "PathShearY", "PathSkew", "PathCurve", "PathRadiusOffset", "PathRevolutions", "PathTaperX", "PathTaperY", "PathTwist", "PathTwistBegin", "ProfileBegin", "ProfileEnd", "ProfileCurve", "ProfileHollow", "State", "Texture", "ExtraParams"
626 FROM primshapes;
627
628DROP TABLE primshapes;
629
630alter table Tmp_primshapes rename to primshapes;
631
632ALTER TABLE primshapes ADD CONSTRAINT
633 PK__primshapes__0880433F PRIMARY KEY
634 (
635 "UUID"
636 );
637
638COMMIT;
639
640
641:VERSION 15
642
643BEGIN TRANSACTION;
644
645CREATE TABLE Tmp_primitems
646 (
647 "itemID" uuid NOT NULL,
648 "primID" uuid NULL,
649 "assetID" uuid NULL,
650 "parentFolderID" uuid NULL,
651 "invType" int NULL,
652 "assetType" int NULL,
653 "name" varchar(255) NULL,
654 "description" varchar(255) NULL,
655 "creationDate" varchar(255) NULL,
656 "creatorID" uuid NULL,
657 "ownerID" uuid NULL,
658 "lastOwnerID" uuid NULL,
659 "groupID" uuid NULL,
660 "nextPermissions" int NULL,
661 "currentPermissions" int NULL,
662 "basePermissions" int NULL,
663 "everyonePermissions" int NULL,
664 "groupPermissions" int NULL,
665 flags int NOT NULL DEFAULT ((0))
666 );
667
668INSERT INTO Tmp_primitems ("itemID", "primID", "assetID", "parentFolderID", "invType", "assetType", "name", "description", "creationDate", "creatorID", "ownerID", "lastOwnerID", "groupID", "nextPermissions", "currentPermissions", "basePermissions", "everyonePermissions", "groupPermissions", flags)
669 SELECT cast("itemID" as uuid), cast("primID" as uuid), cast("assetID" as uuid), cast("parentFolderID" as uuid), "invType", "assetType", "name", "description", "creationDate", cast("creatorID" as uuid), cast("ownerID" as uuid), cast("lastOwnerID" as uuid), cast("groupID" as uuid), "nextPermissions", "currentPermissions", "basePermissions", "everyonePermissions", "groupPermissions", flags
670 FROM primitems ;
671
672DROP TABLE primitems;
673
674alter table Tmp_primitems rename to primitems;
675
676ALTER TABLE primitems ADD CONSTRAINT
677 PK__primitems__0A688BB1 PRIMARY KEY
678 (
679 "itemID"
680 );
681
682CREATE INDEX primitems_primid ON primitems
683 (
684 "primID"
685 ) ;
686
687COMMIT;
688
689
690:VERSION 16
691
692
693BEGIN TRANSACTION;
694
695CREATE TABLE Tmp_terrain
696 (
697 "RegionUUID" uuid NULL,
698 "Revision" int NULL,
699 "Heightfield" bytea NULL
700 );
701
702INSERT INTO Tmp_terrain ("RegionUUID", "Revision", "Heightfield")
703 SELECT cast("RegionUUID" as uuid), "Revision", "Heightfield"
704 FROM terrain ;
705
706DROP TABLE terrain;
707
708alter table Tmp_terrain rename to terrain;
709
710COMMIT;
711
712
713:VERSION 17
714
715BEGIN TRANSACTION;
716
717CREATE TABLE Tmp_land
718 (
719 "UUID" uuid NOT NULL,
720 "RegionUUID" uuid NULL,
721 "LocalLandID" int NULL,
722 "Bitmap" bytea NULL,
723 "Name" varchar(255) NULL,
724 "Description" varchar(255) NULL,
725 "OwnerUUID" uuid NULL,
726 "IsGroupOwned" boolean NULL,
727 "Area" int NULL,
728 "AuctionID" int NULL,
729 "Category" int NULL,
730 "ClaimDate" int NULL,
731 "ClaimPrice" int NULL,
732 "GroupUUID" uuid NULL,
733 "SalePrice" int NULL,
734 "LandStatus" int NULL,
735 "LandFlags" int NULL,
736 "LandingType" int NULL,
737 "MediaAutoScale" int NULL,
738 "MediaTextureUUID" uuid NULL,
739 "MediaURL" varchar(255) NULL,
740 "MusicURL" varchar(255) NULL,
741 "PassHours" double precision NULL,
742 "PassPrice" int NULL,
743 "SnapshotUUID" uuid NULL,
744 "UserLocationX" double precision NULL,
745 "UserLocationY" double precision NULL,
746 "UserLocationZ" double precision NULL,
747 "UserLookAtX" double precision NULL,
748 "UserLookAtY" double precision NULL,
749 "UserLookAtZ" double precision NULL,
750 "AuthbuyerID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
751 "OtherCleanTime" int NOT NULL DEFAULT ((0)),
752 "Dwell" int NOT NULL DEFAULT ((0))
753 );
754
755INSERT INTO Tmp_land ("UUID", "RegionUUID", "LocalLandID", "Bitmap", "Name", "Description", "OwnerUUID", "IsGroupOwned", "Area", "AuctionID", "Category", "ClaimDate", "ClaimPrice", "GroupUUID", "SalePrice", "LandStatus", "LandFlags", "LandingType", "MediaAutoScale", "MediaTextureUUID", "MediaURL", "MusicURL", "PassHours", "PassPrice", "SnapshotUUID", "UserLocationX", "UserLocationY", "UserLocationZ", "UserLookAtX", "UserLookAtY", "UserLookAtZ", "AuthbuyerID", "OtherCleanTime", "Dwell")
756 SELECT cast("UUID" as uuid), cast("RegionUUID" as uuid), "LocalLandID", "Bitmap", "Name", "Description", cast("OwnerUUID" as uuid), "IsGroupOwned", "Area", "AuctionID", "Category", "ClaimDate", "ClaimPrice", cast("GroupUUID" as uuid), "SalePrice", "LandStatus", "LandFlags", "LandingType", "MediaAutoScale", cast("MediaTextureUUID" as uuid), "MediaURL", "MusicURL", "PassHours", "PassPrice", cast("SnapshotUUID" as uuid), "UserLocationX", "UserLocationY", "UserLocationZ", "UserLookAtX", "UserLookAtY", "UserLookAtZ", cast("AuthbuyerID" as uuid), "OtherCleanTime", "Dwell"
757 FROM land ;
758
759DROP TABLE land;
760
761alter table Tmp_land rename to land;
762
763ALTER TABLE land ADD CONSTRAINT
764 PK__land__65A475E71BFD2C07 PRIMARY KEY
765 (
766 "UUID"
767 );
768
769Create index on land (lower("Name"));
770
771COMMIT;
772
773
774
775:VERSION 18
776
777BEGIN TRANSACTION;
778
779CREATE TABLE Tmp_landaccesslist
780 (
781 "LandUUID" uuid NULL,
782 "AccessUUID" uuid NULL,
783 "Flags" int NULL
784 );
785
786INSERT INTO Tmp_landaccesslist ("LandUUID", "AccessUUID", "Flags")
787 SELECT cast("LandUUID" as uuid), cast("AccessUUID" as uuid), "Flags"
788 FROM landaccesslist ;
789
790DROP TABLE landaccesslist;
791
792alter table Tmp_landaccesslist rename to landaccesslist;
793
794COMMIT;
795
796
797
798:VERSION 19
799
800BEGIN TRANSACTION;
801
802CREATE TABLE Tmp_regionban
803 (
804 "regionUUID" uuid NOT NULL,
805 "bannedUUID" uuid NOT NULL,
806 "bannedIp" varchar(16) NOT NULL,
807 "bannedIpHostMask" varchar(16) NOT NULL
808 );
809
810INSERT INTO Tmp_regionban ("regionUUID", "bannedUUID", "bannedIp", "bannedIpHostMask")
811 SELECT cast("regionUUID" as uuid), cast("bannedUUID" as uuid), "bannedIp", "bannedIpHostMask"
812 FROM regionban ;
813
814DROP TABLE regionban;
815
816alter table Tmp_regionban rename to regionban;
817
818COMMIT;
819
820
821:VERSION 20
822
823BEGIN TRANSACTION;
824
825CREATE TABLE Tmp_regionsettings
826 (
827 "regionUUID" uuid NOT NULL,
828 "block_terraform" boolean NOT NULL,
829 "block_fly" boolean NOT NULL,
830 "allow_damage" boolean NOT NULL,
831 "restrict_pushing" boolean NOT NULL,
832 "allow_land_resell" boolean NOT NULL,
833 "allow_land_join_divide" boolean NOT NULL,
834 "block_show_in_search" boolean NOT NULL,
835 "agent_limit" int NOT NULL,
836 "object_bonus" double precision NOT NULL,
837 "maturity" int NOT NULL,
838 "disable_scripts" boolean NOT NULL,
839 "disable_collisions" boolean NOT NULL,
840 "disable_physics" boolean NOT NULL,
841 "terrain_texture_1" uuid NOT NULL,
842 "terrain_texture_2" uuid NOT NULL,
843 "terrain_texture_3" uuid NOT NULL,
844 "terrain_texture_4" uuid NOT NULL,
845 "elevation_1_nw" double precision NOT NULL,
846 "elevation_2_nw" double precision NOT NULL,
847 "elevation_1_ne" double precision NOT NULL,
848 "elevation_2_ne" double precision NOT NULL,
849 "elevation_1_se" double precision NOT NULL,
850 "elevation_2_se" double precision NOT NULL,
851 "elevation_1_sw" double precision NOT NULL,
852 "elevation_2_sw" double precision NOT NULL,
853 "water_height" double precision NOT NULL,
854 "terrain_raise_limit" double precision NOT NULL,
855 "terrain_lower_limit" double precision NOT NULL,
856 "use_estate_sun" boolean NOT NULL,
857 "fixed_sun" boolean NOT NULL,
858 "sun_position" double precision NOT NULL,
859 "covenant" uuid NULL DEFAULT (NULL),
860 "Sandbox" boolean NOT NULL,
861 "sunvectorx" double precision NOT NULL DEFAULT ((0)),
862 "sunvectory" double precision NOT NULL DEFAULT ((0)),
863 "sunvectorz" double precision NOT NULL DEFAULT ((0))
864 );
865
866INSERT INTO Tmp_regionsettings ("regionUUID", "block_terraform", "block_fly", "allow_damage", "restrict_pushing", "allow_land_resell", "allow_land_join_divide", "block_show_in_search", "agent_limit", "object_bonus", "maturity", "disable_scripts", "disable_collisions", "disable_physics", "terrain_texture_1", "terrain_texture_2", "terrain_texture_3", "terrain_texture_4", "elevation_1_nw", "elevation_2_nw", "elevation_1_ne", "elevation_2_ne", "elevation_1_se", "elevation_2_se", "elevation_1_sw", "elevation_2_sw", "water_height", "terrain_raise_limit", "terrain_lower_limit", "use_estate_sun", "fixed_sun", "sun_position", "covenant", "Sandbox", "sunvectorx", "sunvectory", "sunvectorz")
867 SELECT cast("regionUUID" as uuid), "block_terraform", "block_fly", "allow_damage", "restrict_pushing", "allow_land_resell", "allow_land_join_divide", "block_show_in_search", "agent_limit", "object_bonus", "maturity", "disable_scripts", "disable_collisions", "disable_physics", cast("terrain_texture_1" as uuid), cast("terrain_texture_2" as uuid), cast("terrain_texture_3" as uuid), cast("terrain_texture_4" as uuid), "elevation_1_nw", "elevation_2_nw", "elevation_1_ne", "elevation_2_ne", "elevation_1_se", "elevation_2_se", "elevation_1_sw", "elevation_2_sw", "water_height", "terrain_raise_limit", "terrain_lower_limit", "use_estate_sun", "fixed_sun", "sun_position", cast("covenant" as uuid), "Sandbox", "sunvectorx", "sunvectory", "sunvectorz"
868 FROM regionsettings ;
869
870DROP TABLE regionsettings;
871
872alter table Tmp_regionsettings rename to regionsettings;
873
874ALTER TABLE regionsettings ADD CONSTRAINT
875 PK__regionse__5B35159D21B6055D PRIMARY KEY
876 (
877 "regionUUID"
878 );
879
880COMMIT;
881
882
883:VERSION 21
884
885BEGIN TRANSACTION;
886
887ALTER TABLE prims ADD "PassTouches" boolean not null default false;
888
889COMMIT;
890
891
892:VERSION 22
893
894BEGIN TRANSACTION;
895
896ALTER TABLE regionsettings ADD "loaded_creation_date" varchar(20) ;
897ALTER TABLE regionsettings ADD "loaded_creation_time" varchar(20) ;
898ALTER TABLE regionsettings ADD "loaded_creation_id" varchar(64) ;
899
900COMMIT;
901
902:VERSION 23
903
904BEGIN TRANSACTION;
905
906ALTER TABLE regionsettings DROP COLUMN "loaded_creation_date";
907ALTER TABLE regionsettings DROP COLUMN "loaded_creation_time";
908ALTER TABLE regionsettings ADD "loaded_creation_datetime" int NOT NULL default 0;
909
910COMMIT;
911
912:VERSION 24
913
914BEGIN TRANSACTION;
915
916ALTER TABLE prims ADD "MediaURL" varchar(255);
917ALTER TABLE primshapes ADD "Media" TEXT NULL;
918
919COMMIT;
920
921:VERSION 25
922
923BEGIN TRANSACTION;
924CREATE TABLE regionwindlight (
925 "region_id" varchar(36) NOT NULL DEFAULT '000000-0000-0000-0000-000000000000' PRIMARY KEY,
926 "water_color_r" double precision NOT NULL DEFAULT '4.000000',
927 water_color_g double precision NOT NULL DEFAULT '38.000000',
928 water_color_b double precision NOT NULL DEFAULT '64.000000',
929 water_fog_density_exponent double precision NOT NULL DEFAULT '4.0',
930 underwater_fog_modifier double precision NOT NULL DEFAULT '0.25',
931 reflection_wavelet_scale_1 double precision NOT NULL DEFAULT '2.0',
932 reflection_wavelet_scale_2 double precision NOT NULL DEFAULT '2.0',
933 reflection_wavelet_scale_3 double precision NOT NULL DEFAULT '2.0',
934 fresnel_scale double precision NOT NULL DEFAULT '0.40',
935 fresnel_offset double precision NOT NULL DEFAULT '0.50',
936 refract_scale_above double precision NOT NULL DEFAULT '0.03',
937 refract_scale_below double precision NOT NULL DEFAULT '0.20',
938 blur_multiplier double precision NOT NULL DEFAULT '0.040',
939 big_wave_direction_x double precision NOT NULL DEFAULT '1.05',
940 big_wave_direction_y double precision NOT NULL DEFAULT '-0.42',
941 little_wave_direction_x double precision NOT NULL DEFAULT '1.11',
942 little_wave_direction_y double precision NOT NULL DEFAULT '-1.16',
943 normal_map_texture varchar(36) NOT NULL DEFAULT '822ded49-9a6c-f61c-cb89-6df54f42cdf4',
944 horizon_r double precision NOT NULL DEFAULT '0.25',
945 horizon_g double precision NOT NULL DEFAULT '0.25',
946 horizon_b double precision NOT NULL DEFAULT '0.32',
947 horizon_i double precision NOT NULL DEFAULT '0.32',
948 haze_horizon double precision NOT NULL DEFAULT '0.19',
949 blue_density_r double precision NOT NULL DEFAULT '0.12',
950 blue_density_g double precision NOT NULL DEFAULT '0.22',
951 blue_density_b double precision NOT NULL DEFAULT '0.38',
952 blue_density_i double precision NOT NULL DEFAULT '0.38',
953 haze_density double precision NOT NULL DEFAULT '0.70',
954 density_multiplier double precision NOT NULL DEFAULT '0.18',
955 distance_multiplier double precision NOT NULL DEFAULT '0.8',
956 max_altitude int NOT NULL DEFAULT '1605',
957 sun_moon_color_r double precision NOT NULL DEFAULT '0.24',
958 sun_moon_color_g double precision NOT NULL DEFAULT '0.26',
959 sun_moon_color_b double precision NOT NULL DEFAULT '0.30',
960 sun_moon_color_i double precision NOT NULL DEFAULT '0.30',
961 sun_moon_position double precision NOT NULL DEFAULT '0.317',
962 ambient_r double precision NOT NULL DEFAULT '0.35',
963 ambient_g double precision NOT NULL DEFAULT '0.35',
964 ambient_b double precision NOT NULL DEFAULT '0.35',
965 ambient_i double precision NOT NULL DEFAULT '0.35',
966 east_angle double precision NOT NULL DEFAULT '0.00',
967 sun_glow_focus double precision NOT NULL DEFAULT '0.10',
968 sun_glow_size double precision NOT NULL DEFAULT '1.75',
969 scene_gamma double precision NOT NULL DEFAULT '1.00',
970 star_brightness double precision NOT NULL DEFAULT '0.00',
971 cloud_color_r double precision NOT NULL DEFAULT '0.41',
972 cloud_color_g double precision NOT NULL DEFAULT '0.41',
973 cloud_color_b double precision NOT NULL DEFAULT '0.41',
974 cloud_color_i double precision NOT NULL DEFAULT '0.41',
975 cloud_x double precision NOT NULL DEFAULT '1.00',
976 cloud_y double precision NOT NULL DEFAULT '0.53',
977 cloud_density double precision NOT NULL DEFAULT '1.00',
978 cloud_coverage double precision NOT NULL DEFAULT '0.27',
979 cloud_scale double precision NOT NULL DEFAULT '0.42',
980 cloud_detail_x double precision NOT NULL DEFAULT '1.00',
981 cloud_detail_y double precision NOT NULL DEFAULT '0.53',
982 cloud_detail_density double precision NOT NULL DEFAULT '0.12',
983 cloud_scroll_x double precision NOT NULL DEFAULT '0.20',
984 cloud_scroll_x_lock smallint NOT NULL DEFAULT '0',
985 cloud_scroll_y double precision NOT NULL DEFAULT '0.01',
986 cloud_scroll_y_lock smallint NOT NULL DEFAULT '0',
987 draw_classic_clouds smallint NOT NULL DEFAULT '1'
988);
989
990COMMIT;
991
992:VERSION 26
993
994BEGIN TRANSACTION;
995
996ALTER TABLE regionsettings ADD "map_tile_ID" CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
997
998COMMIT;
999
1000:VERSION 27 #---------------------
1001
1002BEGIN TRANSACTION;
1003ALTER TABLE land ADD "MediaType" VARCHAR(32) NOT NULL DEFAULT 'none/none' ;
1004ALTER TABLE land ADD "MediaDescription" VARCHAR(255) NOT NULL DEFAULT '';
1005ALTER TABLE land ADD "MediaSize" VARCHAR(16) NOT NULL DEFAULT '0,0';
1006ALTER TABLE land ADD "MediaLoop" boolean NOT NULL DEFAULT false;
1007ALTER TABLE land ADD "ObscureMusic" boolean NOT NULL DEFAULT false;
1008ALTER TABLE land ADD "ObscureMedia" boolean NOT NULL DEFAULT false;
1009COMMIT;
1010
1011:VERSION 28 #---------------------
1012
1013BEGIN TRANSACTION;
1014
1015ALTER TABLE prims
1016alter column "CreatorID" set DEFAULT '00000000-0000-0000-0000-000000000000' ;
1017
1018ALTER TABLE prims ALTER COLUMN "CreatorID" set NOT NULL;
1019
1020ALTER TABLE primitems
1021alter column "creatorID" set DEFAULT '00000000-0000-0000-0000-000000000000' ;
1022
1023ALTER TABLE primitems ALTER COLUMN "creatorID" set NOT NULL;
1024
1025COMMIT;
1026
1027:VERSION 29 #----------------- Region Covenant changed time
1028
1029BEGIN TRANSACTION;
1030
1031ALTER TABLE regionsettings ADD "covenant_datetime" int NOT NULL default 0;
1032
1033COMMIT;
1034
1035:VERSION 30 #------------------Migrate "creatorID" storage to varchars instead of UUIDs for HG support
1036
1037BEGIN TRANSACTION;
1038
1039alter table prims rename column "CreatorID" to "CreatorIDOld";
1040alter table primitems rename column "creatorID" to "creatorIDOld";
1041
1042COMMIT;
1043
1044:VERSION 31 #---------------------
1045
1046BEGIN TRANSACTION;
1047
1048ALTER TABLE prims ADD "CreatorID" varchar(255);
1049ALTER TABLE primitems ADD "creatorID" varchar(255);
1050
1051COMMIT;
1052
1053:VERSION 32 #---------------------
1054
1055BEGIN TRANSACTION;
1056
1057UPDATE prims SET "CreatorID" = cast("CreatorIDOld" as varchar(255));
1058UPDATE primitems SET "creatorID" = cast("creatorIDOld" as varchar(255));
1059
1060COMMIT;
1061
1062:VERSION 33 #---------------------
1063
1064BEGIN TRANSACTION;
1065
1066ALTER TABLE prims alter column "CreatorID" set default '00000000-0000-0000-0000-000000000000' ;
1067
1068ALTER TABLE prims ALTER COLUMN "CreatorID" set NOT NULL;
1069
1070ALTER TABLE primitems alter column "creatorID" set DEFAULT '00000000-0000-0000-0000-000000000000' ;
1071
1072ALTER TABLE primitems ALTER COLUMN "creatorID" set NOT NULL;
1073
1074COMMIT;
1075
1076:VERSION 34 #--------------- Telehub support
1077
1078BEGIN TRANSACTION;
1079
1080CREATE TABLE spawn_points(
1081 "RegionUUID" uuid NOT NULL PRIMARY KEY,
1082 "Yaw" double precision NOT NULL,
1083 "Pitch" double precision NOT NULL,
1084 "Distance" double precision NOT NULL
1085);
1086
1087ALTER TABLE regionsettings ADD "TelehubObject" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
1088
1089COMMIT;
1090
1091:VERSION 35 #---------------- Parcels for sale
1092
1093BEGIN TRANSACTION;
1094
1095ALTER TABLE regionsettings ADD "parcel_tile_ID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
1096
1097COMMIT;
1098
1099:VERSION 36 #---------------- Timed bans/access
1100
1101BEGIN TRANSACTION;
1102
1103ALTER TABLE landaccesslist ADD "Expires" integer NOT NULL DEFAULT 0;
1104
1105COMMIT;
1106
1107:VERSION 37 #---------------- Environment Settings
1108
1109BEGIN TRANSACTION;
1110
1111CREATE TABLE regionenvironment(
1112 "region_id" uuid NOT NULL primary key,
1113 "llsd_settings" varchar NOT NULL
1114);
1115
1116COMMIT;
1117
1118:VERSION 38 #---------------- Dynamic attributes
1119
1120BEGIN TRANSACTION;
1121
1122ALTER TABLE prims ADD "DynAttrs" TEXT;
1123
1124COMMIT;
1125
1126:VERSION 39 #---------------- Extra physics params
1127
1128BEGIN TRANSACTION;
1129
1130ALTER TABLE prims ADD "PhysicsShapeType" smallint NOT NULL default '0';
1131ALTER TABLE prims ADD "Density" double precision NOT NULL default '1000';
1132ALTER TABLE prims ADD "GravityModifier" double precision NOT NULL default '1';
1133ALTER TABLE prims ADD "Friction" double precision NOT NULL default '0.6';
1134ALTER TABLE prims ADD "Restitution" double precision NOT NULL default '0.5';
1135
1136COMMIT;
1137
1138:VERSION 40 #-- regionwindlight changed type from smallint to bool
1139
1140BEGIN TRANSACTION;
1141
1142ALTER TABLE regionwindlight ALTER COLUMN cloud_scroll_x_lock DROP DEFAULT;
1143ALTER TABLE regionwindlight ALTER cloud_scroll_x_lock TYPE bool USING CASE WHEN cloud_scroll_x_lock=0 THEN FALSE ELSE TRUE END;
1144ALTER TABLE regionwindlight ALTER COLUMN cloud_scroll_x_lock SET DEFAULT FALSE;
1145
1146ALTER TABLE regionwindlight ALTER COLUMN cloud_scroll_y_lock DROP DEFAULT;
1147ALTER TABLE regionwindlight ALTER cloud_scroll_y_lock TYPE bool USING CASE WHEN cloud_scroll_y_lock=0 THEN FALSE ELSE TRUE END;
1148ALTER TABLE regionwindlight ALTER COLUMN cloud_scroll_y_lock SET DEFAULT FALSE;
1149
1150ALTER TABLE regionwindlight ALTER COLUMN draw_classic_clouds DROP DEFAULT;
1151ALTER TABLE regionwindlight ALTER draw_classic_clouds TYPE bool USING CASE WHEN draw_classic_clouds=0 THEN FALSE ELSE TRUE END;
1152ALTER TABLE regionwindlight ALTER COLUMN draw_classic_clouds SET DEFAULT FALSE;
1153
1154COMMIT;
diff --git a/OpenSim/Data/PGSQL/Resources/UserAccount.migrations b/OpenSim/Data/PGSQL/Resources/UserAccount.migrations
new file mode 100644
index 0000000..c785463
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/UserAccount.migrations
@@ -0,0 +1,51 @@
1:VERSION 1
2
3CREATE TABLE UserAccounts (
4 "PrincipalID" uuid NOT NULL Primary key,
5 "ScopeID" uuid NOT NULL,
6 "FirstName" varchar(64) NOT NULL,
7 "LastName" varchar(64) NOT NULL,
8 "Email" varchar(64) NULL,
9 "ServiceURLs" text NULL,
10 "Created" int default NULL
11);
12
13
14:VERSION 2
15
16BEGIN TRANSACTION;
17
18INSERT INTO UserAccounts ("PrincipalID", "ScopeID", "FirstName", "LastName", "Email", "ServiceURLs", "Created")
19SELECT UUID AS "PrincipalID", '00000000-0000-0000-0000-000000000000' AS "ScopeID",
20username AS "FirstName",
21lastname AS "LastName",
22email as "Email", (
23'AssetServerURI=' +
24userAssetURI + ' InventoryServerURI=' + userInventoryURI + ' GatewayURI= HomeURI=') AS "ServiceURLs",
25created as "Created" FROM users;
26
27COMMIT;
28
29:VERSION 3
30
31BEGIN TRANSACTION;
32
33CREATE UNIQUE INDEX "PrincipalID" ON UserAccounts("PrincipalID");
34CREATE INDEX "Email" ON UserAccounts("Email");
35CREATE INDEX "FirstName" ON UserAccounts("FirstName");
36CREATE INDEX "LastName" ON UserAccounts("LastName");
37CREATE INDEX Name ON UserAccounts("FirstName","LastName");
38
39COMMIT;
40
41:VERSION 4
42
43BEGIN TRANSACTION;
44
45ALTER TABLE UserAccounts ADD "UserLevel" integer NOT NULL DEFAULT 0;
46ALTER TABLE UserAccounts ADD "UserFlags" integer NOT NULL DEFAULT 0;
47ALTER TABLE UserAccounts ADD "UserTitle" varchar(64) NOT NULL DEFAULT '';
48
49COMMIT;
50
51
diff --git a/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations b/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations
new file mode 100644
index 0000000..f23c870
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations
@@ -0,0 +1,83 @@
1:VERSION 1 # -------------------------------
2
3begin;
4
5CREATE TABLE classifieds (
6 "classifieduuid" char(36) NOT NULL,
7 "creatoruuid" char(36) NOT NULL,
8 "creationdate" integer NOT NULL,
9 "expirationdate" integer NOT NULL,
10 "category" varchar(20) NOT NULL,
11 "name" varchar(255) NOT NULL,
12 "description" text NOT NULL,
13 "parceluuid" char(36) NOT NULL,
14 "parentestate" integer NOT NULL,
15 "snapshotuuid" char(36) NOT NULL,
16 "simname" varchar(255) NOT NULL,
17 "posglobal" varchar(255) NOT NULL,
18 "parcelname" varchar(255) NOT NULL,
19 "classifiedflags" integer NOT NULL,
20 "priceforlisting" integer NOT NULL,
21 constraint classifiedspk PRIMARY KEY ("classifieduuid")
22);
23
24
25CREATE TABLE usernotes (
26 "useruuid" varchar(36) NOT NULL,
27 "targetuuid" varchar(36) NOT NULL,
28 "notes" text NOT NULL,
29 constraint usernoteuk UNIQUE ("useruuid","targetuuid")
30);
31
32
33CREATE TABLE userpicks (
34 "pickuuid" varchar(36) NOT NULL,
35 "creatoruuid" varchar(36) NOT NULL,
36 "toppick" boolean NOT NULL,
37 "parceluuid" varchar(36) NOT NULL,
38 "name" varchar(255) NOT NULL,
39 "description" text NOT NULL,
40 "snapshotuuid" varchar(36) NOT NULL,
41 "user" varchar(255) NOT NULL,
42 "originalname" varchar(255) NOT NULL,
43 "simname" varchar(255) NOT NULL,
44 "posglobal" varchar(255) NOT NULL,
45 "sortorder" integer NOT NULL,
46 "enabled" boolean NOT NULL,
47 PRIMARY KEY ("pickuuid")
48);
49
50
51CREATE TABLE userprofile (
52 "useruuid" varchar(36) NOT NULL,
53 "profilePartner" varchar(36) NOT NULL,
54 "profileAllowPublish" bytea NOT NULL,
55 "profileMaturePublish" bytea NOT NULL,
56 "profileURL" varchar(255) NOT NULL,
57 "profileWantToMask" integer NOT NULL,
58 "profileWantToText" text NOT NULL,
59 "profileSkillsMask" integer NOT NULL,
60 "profileSkillsText" text NOT NULL,
61 "profileLanguages" text NOT NULL,
62 "profileImage" varchar(36) NOT NULL,
63 "profileAboutText" text NOT NULL,
64 "profileFirstImage" varchar(36) NOT NULL,
65 "profileFirstText" text NOT NULL,
66 PRIMARY KEY ("useruuid")
67);
68
69commit;
70
71:VERSION 2 # -------------------------------
72
73begin;
74CREATE TABLE userdata (
75 "UserId" char(36) NOT NULL,
76 "TagId" varchar(64) NOT NULL,
77 "DataKey" varchar(255),
78 "DataVal" varchar(255),
79 PRIMARY KEY ("UserId","TagId")
80);
81
82commit;
83
diff --git a/OpenSim/Data/PGSQL/Resources/UserStore.migrations b/OpenSim/Data/PGSQL/Resources/UserStore.migrations
new file mode 100644
index 0000000..974d489
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/UserStore.migrations
@@ -0,0 +1,404 @@
1:VERSION 1
2
3CREATE TABLE users (
4 "UUID" varchar(36) NOT NULL default '' Primary Key,
5 "username" varchar(32) NOT NULL,
6 "lastname" varchar(32) NOT NULL,
7 "passwordHash" varchar(32) NOT NULL,
8 "passwordSalt" varchar(32) NOT NULL,
9 "homeRegion" bigint default NULL,
10 "homeLocationX" double precision default NULL,
11 "homeLocationY" double precision default NULL,
12 "homeLocationZ" double precision default NULL,
13 "homeLookAtX" double precision default NULL,
14 "homeLookAtY" double precision default NULL,
15 "homeLookAtZ" double precision default NULL,
16 "created" int NOT NULL,
17 "lastLogin" int NOT NULL,
18 "userInventoryURI" varchar(255) default NULL,
19 "userAssetURI" varchar(255) default NULL,
20 "profileCanDoMask" int default NULL,
21 "profileWantDoMask" int default NULL,
22 "profileAboutText" text,
23 "profileFirstText" text,
24 "profileImage" varchar(36) default NULL,
25 "profileFirstImage" varchar(36) default NULL,
26 "webLoginKey" varchar(36) default NULL
27);
28
29CREATE INDEX "usernames" ON users
30(
31 "username" ASC,
32 "lastname" ASC
33);
34
35
36CREATE TABLE agents (
37 "UUID" varchar(36) NOT NULL Primary Key,
38 "sessionID" varchar(36) NOT NULL,
39 "secureSessionID" varchar(36) NOT NULL,
40 "agentIP" varchar(16) NOT NULL,
41 "agentPort" int NOT NULL,
42 "agentOnline" smallint NOT NULL,
43 "loginTime" int NOT NULL,
44 "logoutTime" int NOT NULL,
45 "currentRegion" varchar(36) NOT NULL,
46 "currentHandle" bigint NOT NULL,
47 "currentPos" varchar(64) NOT NULL
48);
49
50CREATE INDEX session ON agents
51(
52 "sessionID" ASC
53);
54
55CREATE INDEX ssession ON agents
56(
57 "secureSessionID" ASC
58);
59
60
61CREATE TABLE userfriends(
62 "ownerID" varchar(50) NOT NULL,
63 "friendID" varchar(50) NOT NULL,
64 "friendPerms" varchar(50) NOT NULL,
65 "datetimestamp" varchar(50) NOT NULL
66);
67
68CREATE TABLE avatarappearance (
69 "Owner" varchar(36) NOT NULL primary key,
70 "Serial" int NOT NULL,
71 "Visual_Params" bytea NOT NULL,
72 "Texture" bytea NOT NULL,
73 "Avatar_Height" double precision NOT NULL,
74 "Body_Item" varchar(36) NOT NULL,
75 "Body_Asset" varchar(36) NOT NULL,
76 "Skin_Item" varchar(36) NOT NULL,
77 "Skin_Asset" varchar(36) NOT NULL,
78 "Hair_Item" varchar(36) NOT NULL,
79 "Hair_Asset" varchar(36) NOT NULL,
80 "Eyes_Item" varchar(36) NOT NULL,
81 "Eyes_Asset" varchar(36) NOT NULL,
82 "Shirt_Item" varchar(36) NOT NULL,
83 "Shirt_Asset" varchar(36) NOT NULL,
84 "Pants_Item" varchar(36) NOT NULL,
85 "Pants_Asset" varchar(36) NOT NULL,
86 "Shoes_Item" varchar(36) NOT NULL,
87 "Shoes_Asset" varchar(36) NOT NULL,
88 "Socks_Item" varchar(36) NOT NULL,
89 "Socks_Asset" varchar(36) NOT NULL,
90 "Jacket_Item" varchar(36) NOT NULL,
91 "Jacket_Asset" varchar(36) NOT NULL,
92 "Gloves_Item" varchar(36) NOT NULL,
93 "Gloves_Asset" varchar(36) NOT NULL,
94 "Undershirt_Item" varchar(36) NOT NULL,
95 "Undershirt_Asset" varchar(36) NOT NULL,
96 "Underpants_Item" varchar(36) NOT NULL,
97 "Underpants_Asset" varchar(36) NOT NULL,
98 "Skirt_Item" varchar(36) NOT NULL,
99 "Skirt_Asset" varchar(36) NOT NULL
100);
101
102:VERSION 2
103
104BEGIN TRANSACTION;
105
106ALTER TABLE users ADD "homeRegionID" varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000';
107ALTER TABLE users ADD "userFlags" int NOT NULL default 0;
108ALTER TABLE users ADD "godLevel" int NOT NULL default 0;
109ALTER TABLE users ADD "customType" varchar(32) not null default '';
110ALTER TABLE users ADD "partner" varchar(36) not null default '00000000-0000-0000-0000-000000000000';
111
112COMMIT;
113
114
115:VERSION 3
116
117BEGIN TRANSACTION;
118
119CREATE TABLE avatarattachments (
120 "UUID" varchar(36) NOT NULL
121 , "attachpoint" int NOT NULL
122 , item varchar(36) NOT NULL
123 , asset varchar(36) NOT NULL);
124
125CREATE INDEX IX_avatarattachments ON avatarattachments
126 (
127 "UUID"
128 );
129
130COMMIT;
131
132
133:VERSION 4
134
135BEGIN TRANSACTION;
136
137CREATE TABLE Tmp_userfriends
138 (
139 "ownerID" varchar(36) NOT NULL,
140 "friendID" varchar(36) NOT NULL,
141 "friendPerms" int NOT NULL,
142 "datetimestamp" int NOT NULL
143 );
144
145INSERT INTO Tmp_userfriends ("ownerID", "friendID", "friendPerms", "datetimestamp")
146 SELECT cast("ownerID" as varchar(36)), cast("friendID" as varchar(36)), cast("friendPerms" as int), cast("datetimestamp" as int)
147 FROM userfriends;
148
149DROP TABLE userfriends;
150
151alter table Tmp_userfriends rename to userfriends;
152
153CREATE INDEX IX_userfriends_ownerID ON userfriends
154 (
155 "ownerID"
156 );
157
158CREATE INDEX IX_userfriends_friendID ON userfriends
159 (
160 "friendID"
161 );
162
163COMMIT;
164
165
166:VERSION 5
167
168BEGIN TRANSACTION;
169
170 ALTER TABLE users add "email" varchar(250);
171
172COMMIT;
173
174
175:VERSION 6
176
177BEGIN TRANSACTION;
178
179CREATE TABLE Tmp_users
180 (
181 "UUID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
182 "username" varchar(32) NOT NULL,
183 "lastname" varchar(32) NOT NULL,
184 "passwordHash" varchar(32) NOT NULL,
185 "passwordSalt" varchar(32) NOT NULL,
186 "homeRegion" bigint NULL DEFAULT (NULL),
187 "homeLocationX" double precision NULL DEFAULT (NULL),
188 "homeLocationY" double precision NULL DEFAULT (NULL),
189 "homeLocationZ" double precision NULL DEFAULT (NULL),
190 "homeLookAtX" double precision NULL DEFAULT (NULL),
191 "homeLookAtY" double precision NULL DEFAULT (NULL),
192 "homeLookAtZ" double precision NULL DEFAULT (NULL),
193 "created" int NOT NULL,
194 "lastLogin" int NOT NULL,
195 "userInventoryURI" varchar(255) NULL DEFAULT (NULL),
196 "userAssetURI" varchar(255) NULL DEFAULT (NULL),
197 "profileCanDoMask" int NULL DEFAULT (NULL),
198 "profileWantDoMask" int NULL DEFAULT (NULL),
199 "profileAboutText" text NULL,
200 "profileFirstText" text NULL,
201 "profileImage" uuid NULL DEFAULT (NULL),
202 "profileFirstImage" uuid NULL DEFAULT (NULL),
203 "webLoginKey" uuid NULL DEFAULT (NULL),
204 "homeRegionID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
205 "userFlags" int NOT NULL DEFAULT ((0)),
206 "godLevel" int NOT NULL DEFAULT ((0)),
207 "customType" varchar(32) NOT NULL DEFAULT (''),
208 "partner" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'),
209 email varchar(250) NULL
210 );
211
212INSERT INTO Tmp_users ("UUID", "username", "lastname", "passwordHash", "passwordSalt", "homeRegion", "homeLocationX", "homeLocationY", "homeLocationZ", "homeLookAtX", "homeLookAtY", "homeLookAtZ", "created", "lastLogin", "userInventoryURI", "userAssetURI", "profileCanDoMask", "profileWantDoMask", "profileAboutText", "profileFirstText", "profileImage", "profileFirstImage", "webLoginKey", "homeRegionID", "userFlags", "godLevel", "customType", "partner", email)
213 SELECT cast("UUID" as uuid), "username", "lastname", "passwordHash", "passwordSalt", "homeRegion", "homeLocationX", "homeLocationY", "homeLocationZ", "homeLookAtX", "homeLookAtY", "homeLookAtZ", "created", "lastLogin", "userInventoryURI", "userAssetURI", "profileCanDoMask", "profileWantDoMask", "profileAboutText", "profileFirstText", cast("profileImage" as uuid), cast("profileFirstImage" as uuid), cast("webLoginKey" as uuid), cast("homeRegionID" as uuid), "userFlags", "godLevel", "customType", cast("partner" as uuid), email
214 FROM users ;
215
216DROP TABLE users;
217
218alter table Tmp_users rename to users;
219
220ALTER TABLE users ADD CONSTRAINT
221 PK__users__65A475E737A5467C PRIMARY KEY
222 (
223 "UUID"
224 );
225
226CREATE INDEX "usernames" ON users
227 (
228 "username",
229 "lastname"
230 );
231
232COMMIT;
233
234
235:VERSION 7
236
237BEGIN TRANSACTION;
238
239CREATE TABLE Tmp_agents
240 (
241 "UUID" uuid NOT NULL,
242 "sessionID" uuid NOT NULL,
243 "secureSessionID" uuid NOT NULL,
244 "agentIP" varchar(16) NOT NULL,
245 "agentPort" int NOT NULL,
246 "agentOnline" smallint NOT NULL,
247 "loginTime" int NOT NULL,
248 "logoutTime" int NOT NULL,
249 "currentRegion" uuid NOT NULL,
250 "currentHandle" bigint NOT NULL,
251 "currentPos" varchar(64) NOT NULL
252 );
253
254INSERT INTO Tmp_agents ("UUID", "sessionID", "secureSessionID", "agentIP", "agentPort", "agentOnline", "loginTime", "logoutTime", "currentRegion", "currentHandle", "currentPos")
255 SELECT cast("UUID" as uuid), cast("sessionID" as uuid), cast("secureSessionID" as uuid), "agentIP", "agentPort", "agentOnline", "loginTime", "logoutTime", cast("currentRegion" as uuid), "currentHandle", "currentPos"
256 FROM agents ;
257
258DROP TABLE agents;
259
260alter table Tmp_agents rename to agents;
261
262ALTER TABLE agents ADD CONSTRAINT
263 PK__agents__65A475E749C3F6B7 PRIMARY KEY
264 (
265 "UUID"
266 ) ;
267
268CREATE INDEX session ON agents
269 (
270 "sessionID"
271 );
272
273CREATE INDEX ssession ON agents
274 (
275 "secureSessionID"
276 );
277
278COMMIT;
279
280
281:VERSION 8
282
283BEGIN TRANSACTION;
284
285CREATE TABLE Tmp_userfriends
286 (
287 "ownerID" uuid NOT NULL,
288 "friendID" uuid NOT NULL,
289 "friendPerms" int NOT NULL,
290 "datetimestamp" int NOT NULL
291 );
292
293INSERT INTO Tmp_userfriends ("ownerID", "friendID", "friendPerms", "datetimestamp")
294 SELECT cast("ownerID" as uuid), cast( "friendID" as uuid), "friendPerms", "datetimestamp"
295 FROM userfriends;
296
297DROP TABLE userfriends;
298
299alter table Tmp_userfriends rename to userfriends;
300
301CREATE INDEX IX_userfriends_ownerID ON userfriends
302 (
303 "ownerID"
304 );
305
306CREATE INDEX IX_userfriends_friendID ON userfriends
307 (
308 "friendID"
309 );
310
311COMMIT;
312
313
314:VERSION 9
315
316BEGIN TRANSACTION;
317
318CREATE TABLE Tmp_avatarappearance
319 (
320 "Owner" uuid NOT NULL,
321 "Serial" int NOT NULL,
322 "Visual_Params" bytea NOT NULL,
323 "Texture" bytea NOT NULL,
324 "Avatar_Height" double precision NOT NULL,
325 "Body_Item" uuid NOT NULL,
326 "Body_Asset" uuid NOT NULL,
327 "Skin_Item" uuid NOT NULL,
328 "Skin_Asset" uuid NOT NULL,
329 "Hair_Item" uuid NOT NULL,
330 "Hair_Asset" uuid NOT NULL,
331 "Eyes_Item" uuid NOT NULL,
332 "Eyes_Asset" uuid NOT NULL,
333 "Shirt_Item" uuid NOT NULL,
334 "Shirt_Asset" uuid NOT NULL,
335 "Pants_Item" uuid NOT NULL,
336 "Pants_Asset" uuid NOT NULL,
337 "Shoes_Item" uuid NOT NULL,
338 "Shoes_Asset" uuid NOT NULL,
339 "Socks_Item" uuid NOT NULL,
340 "Socks_Asset" uuid NOT NULL,
341 "Jacket_Item" uuid NOT NULL,
342 "Jacket_Asset" uuid NOT NULL,
343 "Gloves_Item" uuid NOT NULL,
344 "Gloves_Asset" uuid NOT NULL,
345 "Undershirt_Item" uuid NOT NULL,
346 "Undershirt_Asset" uuid NOT NULL,
347 "Underpants_Item" uuid NOT NULL,
348 "Underpants_Asset" uuid NOT NULL,
349 "Skirt_Item" uuid NOT NULL,
350 "Skirt_Asset" uuid NOT NULL
351 );
352
353INSERT INTO Tmp_avatarappearance ("Owner", "Serial", "Visual_Params", "Texture", "Avatar_Height", "Body_Item", "Body_Asset", "Skin_Item", "Skin_Asset", "Hair_Item", "Hair_Asset", "Eyes_Item", "Eyes_Asset", "Shirt_Item", "Shirt_Asset", "Pants_Item", "Pants_Asset", "Shoes_Item", "Shoes_Asset", "Socks_Item", "Socks_Asset", "Jacket_Item", "Jacket_Asset", "Gloves_Item", "Gloves_Asset", "Undershirt_Item", "Undershirt_Asset", "Underpants_Item", "Underpants_Asset", "Skirt_Item", "Skirt_Asset")
354 SELECT cast("Owner" as uuid), "Serial", "Visual_Params", "Texture", "Avatar_Height", cast("Body_Item" as uuid), cast("Body_Asset" as uuid), cast("Skin_Item" as uuid), cast("Skin_Asset" as uuid), cast("Hair_Item" as uuid), cast("Hair_Asset" as uuid), cast("Eyes_Item" as uuid), cast("Eyes_Asset" as uuid), cast("Shirt_Item" as uuid), cast("Shirt_Asset" as uuid), cast("Pants_Item" as uuid), cast("Pants_Asset" as uuid), cast("Shoes_Item" as uuid), cast("Shoes_Asset" as uuid), cast("Socks_Item" as uuid), cast("Socks_Asset" as uuid), cast("Jacket_Item" as uuid), cast("Jacket_Asset" as uuid), cast("Gloves_Item" as uuid), cast("Gloves_Asset" as uuid), cast("Undershirt_Item" as uuid), cast("Undershirt_Asset" as uuid), cast("Underpants_Item" as uuid), cast("Underpants_Asset" as uuid), cast("Skirt_Item" as uuid), cast("Skirt_Asset" as uuid)
355 FROM avatarappearance ;
356
357DROP TABLE avatarappearance;
358
359alter table Tmp_avatarappearance rename to avatarappearance;
360
361ALTER TABLE avatarappearance ADD CONSTRAINT
362 PK__avatarap__7DD115CC4E88ABD4 PRIMARY KEY
363 (
364 "Owner"
365 );
366
367COMMIT;
368
369
370:VERSION 10
371
372BEGIN TRANSACTION;
373
374CREATE TABLE Tmp_avatarattachments
375 (
376 "UUID" uuid NOT NULL,
377 "attachpoint" int NOT NULL,
378 item uuid NOT NULL,
379 asset uuid NOT NULL
380 );
381
382INSERT INTO Tmp_avatarattachments ("UUID", "attachpoint", item, asset)
383 SELECT cast("UUID" as uuid), "attachpoint", cast(item as uuid), cast(asset as uuid)
384 FROM avatarattachments ;
385
386DROP TABLE avatarattachments;
387
388alter table Tmp_avatarattachments rename to avatarattachments;
389
390CREATE INDEX IX_avatarattachments ON avatarattachments
391 (
392 "UUID"
393 );
394
395COMMIT;
396
397
398:VERSION 11
399
400BEGIN TRANSACTION;
401
402ALTER TABLE users ADD "scopeID" uuid not null default '00000000-0000-0000-0000-000000000000';
403
404COMMIT;
diff --git a/OpenSim/Data/PGSQL/Resources/XAssetStore.migrations b/OpenSim/Data/PGSQL/Resources/XAssetStore.migrations
new file mode 100644
index 0000000..325ed0d
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/XAssetStore.migrations
@@ -0,0 +1,27 @@
1# -----------------
2:VERSION 1
3
4BEGIN;
5
6CREATE TABLE XAssetsMeta (
7 "ID" char(36) NOT NULL,
8 "Hash" char(32) NOT NULL,
9 "Name" varchar(64) NOT NULL,
10 "Description" varchar(64) NOT NULL,
11 "AssetType" smallint NOT NULL,
12 "Local" smallint NOT NULL,
13 "Temporary" smallint NOT NULL,
14 "CreateTime" integer NOT NULL,
15 "AccessTime" integer NOT NULL,
16 "AssetFlags" integer NOT NULL,
17 "CreatorID" varchar(128) NOT NULL,
18 PRIMARY KEY ("ID")
19);
20
21CREATE TABLE XAssetsData (
22 "Hash" char(32) NOT NULL,
23 "Data" bytea NOT NULL,
24 PRIMARY KEY ("Hash")
25);
26
27COMMIT;
diff --git a/OpenSim/Data/PGSQL/Resources/os_groups_Store.migrations b/OpenSim/Data/PGSQL/Resources/os_groups_Store.migrations
new file mode 100644
index 0000000..4573f71
--- /dev/null
+++ b/OpenSim/Data/PGSQL/Resources/os_groups_Store.migrations
@@ -0,0 +1,94 @@
1:VERSION 1 # --------------------------
2
3BEGIN;
4
5CREATE TABLE os_groups_groups (
6 "GroupID" char(36) Primary Key NOT NULL default '',
7 "Location" varchar(255) NOT NULL default '',
8 "Name" varchar(255) NOT NULL default '',
9 "Charter" text NOT NULL,
10 "InsigniaID" char(36) NOT NULL default '',
11 "FounderID" char(36) NOT NULL default '',
12 "MembershipFee" integer NOT NULL default '0',
13 "OpenEnrollment" varchar(255) NOT NULL default '',
14 "ShowInList" integer NOT NULL default '0',
15 "AllowPublish" integer NOT NULL default '0',
16 "MaturePublish" integer NOT NULL default '0',
17 "OwnerRoleID" char(36) NOT NULL default ''
18);
19
20
21CREATE TABLE os_groups_membership (
22 "GroupID"char(36) NOT NULL default '',
23 "PrincipalID" VARCHAR(255) NOT NULL default '',
24 "SelectedRoleID" char(36) NOT NULL default '',
25 "Contribution" integer NOT NULL default '0',
26 "ListInProfile" integer NOT NULL default '1',
27 "AcceptNotices" integer NOT NULL default '1',
28 "AccessToken" char(36) NOT NULL default '',
29 constraint os_groupmemberpk primary key ("GroupID", "PrincipalID")
30);
31
32
33
34CREATE TABLE os_groups_roles (
35 "GroupID" char(36) NOT NULL default '',
36 "RoleID" char(36) NOT NULL default '',
37 "Name" varchar(255) NOT NULL default '',
38 "Description" varchar(255) NOT NULL default '',
39 "Title" varchar(255) NOT NULL default '',
40 "Powers" bigint NOT NULL default 0,
41 constraint os_grouprolepk PRIMARY KEY ("GroupID","RoleID")
42);
43
44
45CREATE TABLE os_groups_rolemembership (
46 "GroupID" char(36) NOT NULL default '',
47 "RoleID" char(36) NOT NULL default '',
48 "PrincipalID" VARCHAR(255) NOT NULL default '',
49 constraint os_grouprolememberpk PRIMARY KEY ("GroupID","RoleID","PrincipalID")
50);
51
52
53CREATE TABLE os_groups_invites (
54 "InviteID" char(36) NOT NULL default '',
55 "GroupID" char(36) NOT NULL default '',
56 "RoleID" char(36) NOT NULL default '',
57 "PrincipalID" VARCHAR(255) NOT NULL default '',
58 "TMStamp" timestamp NOT NULL default now(),
59 constraint os_groupinvitespk PRIMARY KEY ("InviteID")
60);
61-- UNIQUE KEY "PrincipalGroup" ("GroupID","PrincipalID")
62
63
64CREATE TABLE os_groups_notices (
65 "GroupID" char(36) NOT NULL default '',
66 "NoticeID" char(36) NOT NULL default '',
67 "TMStamp" integer NOT NULL default '0',
68 "FromName" varchar(255) NOT NULL default '',
69 "Subject" varchar(255) NOT NULL default '',
70 "Message" text NOT NULL,
71 "HasAttachment" integer NOT NULL default '0',
72 "AttachmentType" integer NOT NULL default '0',
73 "AttachmentName" varchar(128) NOT NULL default '',
74 "AttachmentItemID" char(36) NOT NULL default '',
75 "AttachmentOwnerID" varchar(255) NOT NULL default '',
76 constraint os_groupsnoticespk PRIMARY KEY ("NoticeID")
77);
78-- KEY "GroupID" ("GroupID"),
79-- KEY "TMStamp" ("TMStamp")
80
81CREATE TABLE os_groups_principals (
82 "PrincipalID" VARCHAR(255) NOT NULL default '',
83 "ActiveGroupID" char(36) NOT NULL default '',
84 constraint os_groupprincpk PRIMARY KEY ("PrincipalID")
85);
86
87COMMIT;
88
89:VERSION 2 # --------------------------
90
91BEGIN;
92
93
94COMMIT;
diff --git a/OpenSim/Data/Properties/AssemblyInfo.cs b/OpenSim/Data/Properties/AssemblyInfo.cs
index a85f473..9258e55 100644
--- a/OpenSim/Data/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.6.*")] 64[assembly : AssemblyVersion("0.8.0.*")]
65 65
diff --git a/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs b/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
index 992982c..3873eaf 100644
--- a/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
+++ b/OpenSim/Data/SQLite/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.6.*")] 64[assembly : AssemblyVersion("0.8.0.*")]
65 65
diff --git a/OpenSim/Data/SQLite/Resources/EstateStore.migrations b/OpenSim/Data/SQLite/Resources/EstateStore.migrations
index 62f6464..0aec49b 100644
--- a/OpenSim/Data/SQLite/Resources/EstateStore.migrations
+++ b/OpenSim/Data/SQLite/Resources/EstateStore.migrations
@@ -86,3 +86,12 @@ begin;
86alter table estate_settings add column DenyMinors tinyint not null default 0; 86alter table estate_settings add column DenyMinors tinyint not null default 0;
87 87
88commit; 88commit;
89
90:VERSION 9
91
92begin;
93alter table estate_settings add column AllowLandmark tinyint not null default '1';
94alter table estate_settings add column AllowParcelChanges tinyint not null default '1';
95alter table estate_settings add column AllowSetHome tinyint not null default '1';
96commit;
97
diff --git a/OpenSim/Data/SQLite/Resources/HGTravelStore.migrations b/OpenSim/Data/SQLite/Resources/HGTravelStore.migrations
new file mode 100644
index 0000000..02612ce
--- /dev/null
+++ b/OpenSim/Data/SQLite/Resources/HGTravelStore.migrations
@@ -0,0 +1,18 @@
1:VERSION 2 # --------------------------
2
3BEGIN;
4
5CREATE TABLE hg_traveling_data(
6 SessionID VARCHAR(36) NOT NULL,
7 UserID VARCHAR(36) NOT NULL,
8 GridExternalName VARCHAR(255) NOT NULL DEFAULT "",
9 ServiceToken VARCHAR(255) NOT NULL DEFAULT "",
10 ClientIPAddress VARCHAR(16) NOT NULL DEFAULT "",
11 MyIPAddress VARCHAR(16) NOT NULL DEFAULT "",
12 TMStamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
13 PRIMARY KEY(SessionID),
14 UNIQUE(UserID)
15);
16
17COMMIT;
18
diff --git a/OpenSim/Data/SQLite/Resources/RegionStore.migrations b/OpenSim/Data/SQLite/Resources/RegionStore.migrations
index c6f4b48..901068f 100644
--- a/OpenSim/Data/SQLite/Resources/RegionStore.migrations
+++ b/OpenSim/Data/SQLite/Resources/RegionStore.migrations
@@ -592,3 +592,23 @@ ALTER TABLE prims ADD COLUMN `Friction` double NOT NULL default '0.6';
592ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5'; 592ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5';
593 593
594COMMIT; 594COMMIT;
595
596:VERSION 29 #---------------- Keyframes
597
598BEGIN;
599
600ALTER TABLE prims ADD COLUMN `KeyframeMotion` blob;
601
602COMMIT;
603
604:VERSION 30 #---------------- Save Attachment info
605
606BEGIN;
607
608ALTER TABLE prims ADD COLUMN AttachedPosX double default '0';
609ALTER TABLE prims ADD COLUMN AttachedPosY double default '0';
610ALTER TABLE prims ADD COLUMN AttachedPosZ double default '0';
611ALTER TABLE primshapes ADD COLUMN LastAttachPoint int not null default '0';
612
613COMMIT;
614
diff --git a/OpenSim/Data/SQLite/Resources/UserProfiles.migrations b/OpenSim/Data/SQLite/Resources/UserProfiles.migrations
new file mode 100644
index 0000000..16581f6
--- /dev/null
+++ b/OpenSim/Data/SQLite/Resources/UserProfiles.migrations
@@ -0,0 +1,90 @@
1:VERSION 1 # -------------------------------
2
3begin;
4
5CREATE TABLE IF NOT EXISTS classifieds (
6 classifieduuid char(36) NOT NULL PRIMARY KEY,
7 creatoruuid char(36) NOT NULL,
8 creationdate int(20) NOT NULL,
9 expirationdate int(20) NOT NULL,
10 category varchar(20) NOT NULL,
11 name varchar(255) NOT NULL,
12 description text NOT NULL,
13 parceluuid char(36) NOT NULL,
14 parentestate int(11) NOT NULL,
15 snapshotuuid char(36) NOT NULL,
16 simname varchar(255) NOT NULL,
17 posglobal varchar(255) NOT NULL,
18 parcelname varchar(255) NOT NULL,
19 classifiedflags int(8) NOT NULL,
20 priceforlisting int(5) NOT NULL
21);
22
23commit;
24
25begin;
26
27CREATE TABLE IF NOT EXISTS usernotes (
28 useruuid varchar(36) NOT NULL,
29 targetuuid varchar(36) NOT NULL,
30 notes text NOT NULL,
31 UNIQUE (useruuid,targetuuid) ON CONFLICT REPLACE
32);
33
34commit;
35
36begin;
37
38CREATE TABLE IF NOT EXISTS userpicks (
39 pickuuid varchar(36) NOT NULL PRIMARY KEY,
40 creatoruuid varchar(36) NOT NULL,
41 toppick int NOT NULL,
42 parceluuid varchar(36) NOT NULL,
43 name varchar(255) NOT NULL,
44 description text NOT NULL,
45 snapshotuuid varchar(36) NOT NULL,
46 user varchar(255) NOT NULL,
47 originalname varchar(255) NOT NULL,
48 simname varchar(255) NOT NULL,
49 posglobal varchar(255) NOT NULL,
50 sortorder int(2) NOT NULL,
51 enabled int NOT NULL
52);
53
54commit;
55
56begin;
57
58CREATE TABLE IF NOT EXISTS userprofile (
59 useruuid varchar(36) NOT NULL PRIMARY KEY,
60 profilePartner varchar(36) NOT NULL,
61 profileAllowPublish binary(1) NOT NULL,
62 profileMaturePublish binary(1) NOT NULL,
63 profileURL varchar(255) NOT NULL,
64 profileWantToMask int(3) NOT NULL,
65 profileWantToText text NOT NULL,
66 profileSkillsMask int(3) NOT NULL,
67 profileSkillsText text NOT NULL,
68 profileLanguages text NOT NULL,
69 profileImage varchar(36) NOT NULL,
70 profileAboutText text NOT NULL,
71 profileFirstImage varchar(36) NOT NULL,
72 profileFirstText text NOT NULL
73);
74
75commit;
76
77:VERSION 2 # -------------------------------
78
79begin;
80
81CREATE TABLE IF NOT EXISTS userdata (
82 UserId char(36) NOT NULL,
83 TagId varchar(64) NOT NULL,
84 DataKey varchar(255),
85 DataVal varchar(255),
86 PRIMARY KEY (UserId,TagId)
87);
88
89commit;
90
diff --git a/OpenSim/Data/SQLite/SQLiteGridUserData.cs b/OpenSim/Data/SQLite/SQLiteGridUserData.cs
index 1bb5ed8..d8c52f8 100644
--- a/OpenSim/Data/SQLite/SQLiteGridUserData.cs
+++ b/OpenSim/Data/SQLite/SQLiteGridUserData.cs
@@ -56,6 +56,10 @@ namespace OpenSim.Data.SQLite
56 return ret[0]; 56 return ret[0];
57 } 57 }
58 58
59 public GridUserData[] GetAll(string userID)
60 {
61 return base.Get(String.Format("UserID LIKE '{0}%'", userID));
62 }
59 63
60 } 64 }
61} \ No newline at end of file 65} \ No newline at end of file
diff --git a/OpenSim/Data/SQLite/SQLiteHGTravelData.cs b/OpenSim/Data/SQLite/SQLiteHGTravelData.cs
new file mode 100644
index 0000000..db288b2
--- /dev/null
+++ b/OpenSim/Data/SQLite/SQLiteHGTravelData.cs
@@ -0,0 +1,82 @@
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.Data;
31using System.Reflection;
32using System.Threading;
33using log4net;
34using OpenMetaverse;
35using OpenSim.Framework;
36using Mono.Data.Sqlite;
37
38namespace OpenSim.Data.SQLite
39{
40 /// <summary>
41 /// A SQL Interface for user grid data
42 /// </summary>
43 public class SQLiteHGTravelData : SQLiteGenericTableHandler<HGTravelingData>, IHGTravelingData
44 {
45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 public SQLiteHGTravelData(string connectionString, string realm)
48 : base(connectionString, realm, "HGTravelStore") {}
49
50 public HGTravelingData Get(UUID sessionID)
51 {
52 HGTravelingData[] ret = Get("SessionID", sessionID.ToString());
53
54 if (ret.Length == 0)
55 return null;
56
57 return ret[0];
58 }
59
60 public HGTravelingData[] GetSessions(UUID userID)
61 {
62 return base.Get("UserID", userID.ToString());
63 }
64
65 public bool Delete(UUID sessionID)
66 {
67 return Delete("SessionID", sessionID.ToString());
68 }
69
70 public void DeleteOld()
71 {
72 using (SqliteCommand cmd = new SqliteCommand())
73 {
74 cmd.CommandText = String.Format("delete from {0} where TMStamp < datetime('now', '-2 day') ", m_Realm);
75
76 DoQuery(cmd);
77 }
78
79 }
80
81 }
82} \ No newline at end of file
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index 76f717d..4d6a80a 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -1236,6 +1236,10 @@ namespace OpenSim.Data.SQLite
1236 1236
1237 createCol(prims, "MediaURL", typeof(String)); 1237 createCol(prims, "MediaURL", typeof(String));
1238 1238
1239 createCol(prims, "AttachedPosX", typeof(Double));
1240 createCol(prims, "AttachedPosY", typeof(Double));
1241 createCol(prims, "AttachedPosZ", typeof(Double));
1242
1239 createCol(prims, "DynAttrs", typeof(String)); 1243 createCol(prims, "DynAttrs", typeof(String));
1240 1244
1241 createCol(prims, "PhysicsShapeType", typeof(Byte)); 1245 createCol(prims, "PhysicsShapeType", typeof(Byte));
@@ -1244,6 +1248,7 @@ namespace OpenSim.Data.SQLite
1244 createCol(prims, "Friction", typeof(Double)); 1248 createCol(prims, "Friction", typeof(Double));
1245 createCol(prims, "Restitution", typeof(Double)); 1249 createCol(prims, "Restitution", typeof(Double));
1246 1250
1251 createCol(prims, "KeyframeMotion", typeof(Byte[]));
1247 // Add in contraints 1252 // Add in contraints
1248 prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] }; 1253 prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] };
1249 1254
@@ -1723,6 +1728,12 @@ namespace OpenSim.Data.SQLite
1723 prim.MediaUrl = (string)row["MediaURL"]; 1728 prim.MediaUrl = (string)row["MediaURL"];
1724 } 1729 }
1725 1730
1731 prim.AttachedPos = new Vector3(
1732 Convert.ToSingle(row["AttachedPosX"]),
1733 Convert.ToSingle(row["AttachedPosY"]),
1734 Convert.ToSingle(row["AttachedPosZ"])
1735 );
1736
1726 if (!(row["DynAttrs"] is System.DBNull)) 1737 if (!(row["DynAttrs"] is System.DBNull))
1727 { 1738 {
1728 //m_log.DebugFormat("[SQLITE]: DynAttrs type [{0}]", row["DynAttrs"].GetType()); 1739 //m_log.DebugFormat("[SQLITE]: DynAttrs type [{0}]", row["DynAttrs"].GetType());
@@ -1739,6 +1750,20 @@ namespace OpenSim.Data.SQLite
1739 prim.Friction = Convert.ToSingle(row["Friction"]); 1750 prim.Friction = Convert.ToSingle(row["Friction"]);
1740 prim.Restitution = Convert.ToSingle(row["Restitution"]); 1751 prim.Restitution = Convert.ToSingle(row["Restitution"]);
1741 1752
1753
1754 if (!(row["KeyframeMotion"] is DBNull))
1755 {
1756 Byte[] data = (byte[])row["KeyframeMotion"];
1757 if (data.Length > 0)
1758 prim.KeyframeMotion = KeyframeMotion.FromData(null, data);
1759 else
1760 prim.KeyframeMotion = null;
1761 }
1762 else
1763 {
1764 prim.KeyframeMotion = null;
1765 }
1766
1742 return prim; 1767 return prim;
1743 } 1768 }
1744 1769
@@ -2161,7 +2186,11 @@ namespace OpenSim.Data.SQLite
2161 2186
2162 row["MediaURL"] = prim.MediaUrl; 2187 row["MediaURL"] = prim.MediaUrl;
2163 2188
2164 if (prim.DynAttrs.Count > 0) 2189 row["AttachedPosX"] = prim.AttachedPos.X;
2190 row["AttachedPosY"] = prim.AttachedPos.Y;
2191 row["AttachedPosZ"] = prim.AttachedPos.Z;
2192
2193 if (prim.DynAttrs.CountNamespaces > 0)
2165 row["DynAttrs"] = prim.DynAttrs.ToXml(); 2194 row["DynAttrs"] = prim.DynAttrs.ToXml();
2166 else 2195 else
2167 row["DynAttrs"] = null; 2196 row["DynAttrs"] = null;
@@ -2171,6 +2200,13 @@ namespace OpenSim.Data.SQLite
2171 row["GravityModifier"] = (double)prim.GravityModifier; 2200 row["GravityModifier"] = (double)prim.GravityModifier;
2172 row["Friction"] = (double)prim.Friction; 2201 row["Friction"] = (double)prim.Friction;
2173 row["Restitution"] = (double)prim.Restitution; 2202 row["Restitution"] = (double)prim.Restitution;
2203
2204 if (prim.KeyframeMotion != null)
2205 row["KeyframeMotion"] = prim.KeyframeMotion.Serialize();
2206 else
2207 row["KeyframeMotion"] = new Byte[0];
2208
2209
2174 } 2210 }
2175 2211
2176 /// <summary> 2212 /// <summary>
@@ -2422,6 +2458,7 @@ namespace OpenSim.Data.SQLite
2422 s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); 2458 s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]);
2423 s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); 2459 s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]);
2424 s.State = Convert.ToByte(row["State"]); 2460 s.State = Convert.ToByte(row["State"]);
2461 s.LastAttachPoint = Convert.ToByte(row["LastAttachPoint"]);
2425 2462
2426 byte[] textureEntry = (byte[])row["Texture"]; 2463 byte[] textureEntry = (byte[])row["Texture"];
2427 s.TextureEntry = textureEntry; 2464 s.TextureEntry = textureEntry;
@@ -2471,6 +2508,7 @@ namespace OpenSim.Data.SQLite
2471 row["ProfileCurve"] = s.ProfileCurve; 2508 row["ProfileCurve"] = s.ProfileCurve;
2472 row["ProfileHollow"] = s.ProfileHollow; 2509 row["ProfileHollow"] = s.ProfileHollow;
2473 row["State"] = s.State; 2510 row["State"] = s.State;
2511 row["LastAttachPoint"] = s.LastAttachPoint;
2474 2512
2475 row["Texture"] = s.TextureEntry; 2513 row["Texture"] = s.TextureEntry;
2476 row["ExtraParams"] = s.ExtraParams; 2514 row["ExtraParams"] = s.ExtraParams;
diff --git a/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs b/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs
new file mode 100644
index 0000000..84e56b1
--- /dev/null
+++ b/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs
@@ -0,0 +1,988 @@
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.Data;
31using System.Reflection;
32using log4net;
33#if CSharpSqlite
34using Community.CsharpSqlite.Sqlite;
35#else
36using Mono.Data.Sqlite;
37#endif
38using OpenMetaverse;
39using OpenMetaverse.StructuredData;
40using OpenSim.Framework;
41using OpenSim.Region.Framework.Interfaces;
42
43namespace OpenSim.Data.SQLite
44{
45 public class SQLiteUserProfilesData: IProfilesData
46 {
47 private static readonly ILog m_log =
48 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 private SqliteConnection m_connection;
51 private string m_connectionString;
52
53 private FieldInfo[] m_Fields;
54 private Dictionary<string, FieldInfo> m_FieldMap =
55 new Dictionary<string, FieldInfo>();
56
57 protected virtual Assembly Assembly
58 {
59 get { return GetType().Assembly; }
60 }
61
62 public SQLiteUserProfilesData()
63 {
64 }
65
66 public SQLiteUserProfilesData(string connectionString)
67 {
68 Initialise(connectionString);
69 }
70
71 public void Initialise(string connectionString)
72 {
73 if (Util.IsWindows())
74 Util.LoadArchSpecificWindowsDll("sqlite3.dll");
75
76 m_connectionString = connectionString;
77
78 m_log.Info("[PROFILES_DATA]: Sqlite - connecting: "+m_connectionString);
79
80 m_connection = new SqliteConnection(m_connectionString);
81 m_connection.Open();
82
83 Migration m = new Migration(m_connection, Assembly, "UserProfiles");
84 m.Update();
85 }
86
87 private string[] FieldList
88 {
89 get { return new List<string>(m_FieldMap.Keys).ToArray(); }
90 }
91
92 #region IProfilesData implementation
93 public OSDArray GetClassifiedRecords(UUID creatorId)
94 {
95 OSDArray data = new OSDArray();
96 string query = "SELECT classifieduuid, name FROM classifieds WHERE creatoruuid = :Id";
97 IDataReader reader = null;
98
99 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
100 {
101 cmd.CommandText = query;
102 cmd.Parameters.AddWithValue(":Id", creatorId);
103 reader = cmd.ExecuteReader();
104 }
105
106 while (reader.Read())
107 {
108 OSDMap n = new OSDMap();
109 UUID Id = UUID.Zero;
110 string Name = null;
111 try
112 {
113 UUID.TryParse(Convert.ToString( reader["classifieduuid"]), out Id);
114 Name = Convert.ToString(reader["name"]);
115 }
116 catch (Exception e)
117 {
118 m_log.DebugFormat("[PROFILES_DATA]" +
119 ": UserAccount exception {0}", e.Message);
120 }
121 n.Add("classifieduuid", OSD.FromUUID(Id));
122 n.Add("name", OSD.FromString(Name));
123 data.Add(n);
124 }
125
126 reader.Close();
127
128 return data;
129 }
130 public bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result)
131 {
132 string query = string.Empty;
133
134 query += "INSERT OR REPLACE INTO classifieds (";
135 query += "`classifieduuid`,";
136 query += "`creatoruuid`,";
137 query += "`creationdate`,";
138 query += "`expirationdate`,";
139 query += "`category`,";
140 query += "`name`,";
141 query += "`description`,";
142 query += "`parceluuid`,";
143 query += "`parentestate`,";
144 query += "`snapshotuuid`,";
145 query += "`simname`,";
146 query += "`posglobal`,";
147 query += "`parcelname`,";
148 query += "`classifiedflags`,";
149 query += "`priceforlisting`) ";
150 query += "VALUES (";
151 query += ":ClassifiedId,";
152 query += ":CreatorId,";
153 query += ":CreatedDate,";
154 query += ":ExpirationDate,";
155 query += ":Category,";
156 query += ":Name,";
157 query += ":Description,";
158 query += ":ParcelId,";
159 query += ":ParentEstate,";
160 query += ":SnapshotId,";
161 query += ":SimName,";
162 query += ":GlobalPos,";
163 query += ":ParcelName,";
164 query += ":Flags,";
165 query += ":ListingPrice ) ";
166
167 if(string.IsNullOrEmpty(ad.ParcelName))
168 ad.ParcelName = "Unknown";
169 if(ad.ParcelId == null)
170 ad.ParcelId = UUID.Zero;
171 if(string.IsNullOrEmpty(ad.Description))
172 ad.Description = "No Description";
173
174 DateTime epoch = new DateTime(1970, 1, 1);
175 DateTime now = DateTime.Now;
176 TimeSpan epochnow = now - epoch;
177 TimeSpan duration;
178 DateTime expiration;
179 TimeSpan epochexp;
180
181 if(ad.Flags == 2)
182 {
183 duration = new TimeSpan(7,0,0,0);
184 expiration = now.Add(duration);
185 epochexp = expiration - epoch;
186 }
187 else
188 {
189 duration = new TimeSpan(365,0,0,0);
190 expiration = now.Add(duration);
191 epochexp = expiration - epoch;
192 }
193 ad.CreationDate = (int)epochnow.TotalSeconds;
194 ad.ExpirationDate = (int)epochexp.TotalSeconds;
195
196 try {
197 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
198 {
199 cmd.CommandText = query;
200 cmd.Parameters.AddWithValue(":ClassifiedId", ad.ClassifiedId.ToString());
201 cmd.Parameters.AddWithValue(":CreatorId", ad.CreatorId.ToString());
202 cmd.Parameters.AddWithValue(":CreatedDate", ad.CreationDate.ToString());
203 cmd.Parameters.AddWithValue(":ExpirationDate", ad.ExpirationDate.ToString());
204 cmd.Parameters.AddWithValue(":Category", ad.Category.ToString());
205 cmd.Parameters.AddWithValue(":Name", ad.Name.ToString());
206 cmd.Parameters.AddWithValue(":Description", ad.Description.ToString());
207 cmd.Parameters.AddWithValue(":ParcelId", ad.ParcelId.ToString());
208 cmd.Parameters.AddWithValue(":ParentEstate", ad.ParentEstate.ToString());
209 cmd.Parameters.AddWithValue(":SnapshotId", ad.SnapshotId.ToString ());
210 cmd.Parameters.AddWithValue(":SimName", ad.SimName.ToString());
211 cmd.Parameters.AddWithValue(":GlobalPos", ad.GlobalPos.ToString());
212 cmd.Parameters.AddWithValue(":ParcelName", ad.ParcelName.ToString());
213 cmd.Parameters.AddWithValue(":Flags", ad.Flags.ToString());
214 cmd.Parameters.AddWithValue(":ListingPrice", ad.Price.ToString ());
215
216 cmd.ExecuteNonQuery();
217 }
218 }
219 catch (Exception e)
220 {
221 m_log.DebugFormat("[PROFILES_DATA]" +
222 ": ClassifiedesUpdate exception {0}", e.Message);
223 result = e.Message;
224 return false;
225 }
226 return true;
227 }
228 public bool DeleteClassifiedRecord(UUID recordId)
229 {
230 string query = string.Empty;
231
232 query += "DELETE FROM classifieds WHERE ";
233 query += "classifieduuid = :ClasifiedId";
234
235 try
236 {
237 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
238 {
239 cmd.CommandText = query;
240 cmd.Parameters.AddWithValue(":ClassifiedId", recordId.ToString());
241
242 cmd.ExecuteNonQuery();
243 }
244 }
245 catch (Exception e)
246 {
247 m_log.DebugFormat("[PROFILES_DATA]" +
248 ": DeleteClassifiedRecord exception {0}", e.Message);
249 return false;
250 }
251 return true;
252 }
253
254 public bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result)
255 {
256 IDataReader reader = null;
257 string query = string.Empty;
258
259 query += "SELECT * FROM classifieds WHERE ";
260 query += "classifieduuid = :AdId";
261
262 try
263 {
264 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
265 {
266 cmd.CommandText = query;
267 cmd.Parameters.AddWithValue(":AdId", ad.ClassifiedId.ToString());
268
269 using (reader = cmd.ExecuteReader())
270 {
271 if(reader.Read ())
272 {
273 ad.CreatorId = new UUID(reader["creatoruuid"].ToString());
274 ad.ParcelId = new UUID(reader["parceluuid"].ToString ());
275 ad.SnapshotId = new UUID(reader["snapshotuuid"].ToString ());
276 ad.CreationDate = Convert.ToInt32(reader["creationdate"]);
277 ad.ExpirationDate = Convert.ToInt32(reader["expirationdate"]);
278 ad.ParentEstate = Convert.ToInt32(reader["parentestate"]);
279 ad.Flags = (byte) Convert.ToUInt32(reader["classifiedflags"]);
280 ad.Category = Convert.ToInt32(reader["category"]);
281 ad.Price = Convert.ToInt16(reader["priceforlisting"]);
282 ad.Name = reader["name"].ToString();
283 ad.Description = reader["description"].ToString();
284 ad.SimName = reader["simname"].ToString();
285 ad.GlobalPos = reader["posglobal"].ToString();
286 ad.ParcelName = reader["parcelname"].ToString();
287 }
288 }
289 }
290 }
291 catch (Exception e)
292 {
293 m_log.DebugFormat("[PROFILES_DATA]" +
294 ": GetPickInfo exception {0}", e.Message);
295 }
296 return true;
297 }
298
299 public OSDArray GetAvatarPicks(UUID avatarId)
300 {
301 IDataReader reader = null;
302 string query = string.Empty;
303
304 query += "SELECT `pickuuid`,`name` FROM userpicks WHERE ";
305 query += "creatoruuid = :Id";
306 OSDArray data = new OSDArray();
307
308 try
309 {
310 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
311 {
312 cmd.CommandText = query;
313 cmd.Parameters.AddWithValue(":Id", avatarId.ToString());
314
315 using (reader = cmd.ExecuteReader())
316 {
317 while (reader.Read())
318 {
319 OSDMap record = new OSDMap();
320
321 record.Add("pickuuid",OSD.FromString((string)reader["pickuuid"]));
322 record.Add("name",OSD.FromString((string)reader["name"]));
323 data.Add(record);
324 }
325 }
326 }
327 }
328 catch (Exception e)
329 {
330 m_log.DebugFormat("[PROFILES_DATA]" +
331 ": GetAvatarPicks exception {0}", e.Message);
332 }
333 return data;
334 }
335 public UserProfilePick GetPickInfo(UUID avatarId, UUID pickId)
336 {
337 IDataReader reader = null;
338 string query = string.Empty;
339 UserProfilePick pick = new UserProfilePick();
340
341 query += "SELECT * FROM userpicks WHERE ";
342 query += "creatoruuid = :CreatorId AND ";
343 query += "pickuuid = :PickId";
344
345 try
346 {
347 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
348 {
349 cmd.CommandText = query;
350 cmd.Parameters.AddWithValue(":CreatorId", avatarId.ToString());
351 cmd.Parameters.AddWithValue(":PickId", pickId.ToString());
352
353 using (reader = cmd.ExecuteReader())
354 {
355
356 while (reader.Read())
357 {
358 string description = (string)reader["description"];
359
360 if (string.IsNullOrEmpty(description))
361 description = "No description given.";
362
363 UUID.TryParse((string)reader["pickuuid"], out pick.PickId);
364 UUID.TryParse((string)reader["creatoruuid"], out pick.CreatorId);
365 UUID.TryParse((string)reader["parceluuid"], out pick.ParcelId);
366 UUID.TryParse((string)reader["snapshotuuid"], out pick.SnapshotId);
367 pick.GlobalPos = (string)reader["posglobal"];
368 bool.TryParse((string)reader["toppick"].ToString(), out pick.TopPick);
369 bool.TryParse((string)reader["enabled"].ToString(), out pick.Enabled);
370 pick.Name = (string)reader["name"];
371 pick.Desc = description;
372 pick.User = (string)reader["user"];
373 pick.OriginalName = (string)reader["originalname"];
374 pick.SimName = (string)reader["simname"];
375 pick.SortOrder = (int)reader["sortorder"];
376 }
377 }
378 }
379 }
380 catch (Exception e)
381 {
382 m_log.DebugFormat("[PROFILES_DATA]" +
383 ": GetPickInfo exception {0}", e.Message);
384 }
385 return pick;
386 }
387
388 public bool UpdatePicksRecord(UserProfilePick pick)
389 {
390 string query = string.Empty;
391
392 query += "INSERT OR REPLACE INTO userpicks (";
393 query += "pickuuid, ";
394 query += "creatoruuid, ";
395 query += "toppick, ";
396 query += "parceluuid, ";
397 query += "name, ";
398 query += "description, ";
399 query += "snapshotuuid, ";
400 query += "user, ";
401 query += "originalname, ";
402 query += "simname, ";
403 query += "posglobal, ";
404 query += "sortorder, ";
405 query += "enabled ) ";
406 query += "VALUES (";
407 query += ":PickId,";
408 query += ":CreatorId,";
409 query += ":TopPick,";
410 query += ":ParcelId,";
411 query += ":Name,";
412 query += ":Desc,";
413 query += ":SnapshotId,";
414 query += ":User,";
415 query += ":Original,";
416 query += ":SimName,";
417 query += ":GlobalPos,";
418 query += ":SortOrder,";
419 query += ":Enabled) ";
420
421 try
422 {
423 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
424 {
425 int top_pick;
426 int.TryParse(pick.TopPick.ToString(), out top_pick);
427 int enabled;
428 int.TryParse(pick.Enabled.ToString(), out enabled);
429
430 cmd.CommandText = query;
431 cmd.Parameters.AddWithValue(":PickId", pick.PickId.ToString());
432 cmd.Parameters.AddWithValue(":CreatorId", pick.CreatorId.ToString());
433 cmd.Parameters.AddWithValue(":TopPick", top_pick);
434 cmd.Parameters.AddWithValue(":ParcelId", pick.ParcelId.ToString());
435 cmd.Parameters.AddWithValue(":Name", pick.Name.ToString());
436 cmd.Parameters.AddWithValue(":Desc", pick.Desc.ToString());
437 cmd.Parameters.AddWithValue(":SnapshotId", pick.SnapshotId.ToString());
438 cmd.Parameters.AddWithValue(":User", pick.User.ToString());
439 cmd.Parameters.AddWithValue(":Original", pick.OriginalName.ToString());
440 cmd.Parameters.AddWithValue(":SimName",pick.SimName.ToString());
441 cmd.Parameters.AddWithValue(":GlobalPos", pick.GlobalPos);
442 cmd.Parameters.AddWithValue(":SortOrder", pick.SortOrder.ToString ());
443 cmd.Parameters.AddWithValue(":Enabled", enabled);
444
445 cmd.ExecuteNonQuery();
446 }
447 }
448 catch (Exception e)
449 {
450 m_log.DebugFormat("[PROFILES_DATA]" +
451 ": UpdateAvatarNotes exception {0}", e.Message);
452 return false;
453 }
454 return true;
455 }
456
457 public bool DeletePicksRecord(UUID pickId)
458 {
459 string query = string.Empty;
460
461 query += "DELETE FROM userpicks WHERE ";
462 query += "pickuuid = :PickId";
463
464 try
465 {
466 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
467 {
468 cmd.CommandText = query;
469 cmd.Parameters.AddWithValue(":PickId", pickId.ToString());
470 cmd.ExecuteNonQuery();
471 }
472 }
473 catch (Exception e)
474 {
475 m_log.DebugFormat("[PROFILES_DATA]" +
476 ": DeleteUserPickRecord exception {0}", e.Message);
477 return false;
478 }
479 return true;
480 }
481
482 public bool GetAvatarNotes(ref UserProfileNotes notes)
483 {
484 IDataReader reader = null;
485 string query = string.Empty;
486
487 query += "SELECT `notes` FROM usernotes WHERE ";
488 query += "useruuid = :Id AND ";
489 query += "targetuuid = :TargetId";
490 OSDArray data = new OSDArray();
491
492 try
493 {
494 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
495 {
496 cmd.CommandText = query;
497 cmd.Parameters.AddWithValue(":Id", notes.UserId.ToString());
498 cmd.Parameters.AddWithValue(":TargetId", notes.TargetId.ToString());
499
500 using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
501 {
502 while (reader.Read())
503 {
504 notes.Notes = OSD.FromString((string)reader["notes"]);
505 }
506 }
507 }
508 }
509 catch (Exception e)
510 {
511 m_log.DebugFormat("[PROFILES_DATA]" +
512 ": GetAvatarNotes exception {0}", e.Message);
513 }
514 return true;
515 }
516
517 public bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result)
518 {
519 string query = string.Empty;
520 bool remove;
521
522 if(string.IsNullOrEmpty(note.Notes))
523 {
524 remove = true;
525 query += "DELETE FROM usernotes WHERE ";
526 query += "useruuid=:UserId AND ";
527 query += "targetuuid=:TargetId";
528 }
529 else
530 {
531 remove = false;
532 query += "INSERT OR REPLACE INTO usernotes VALUES ( ";
533 query += ":UserId,";
534 query += ":TargetId,";
535 query += ":Notes )";
536 }
537
538 try
539 {
540 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
541 {
542 cmd.CommandText = query;
543
544 if(!remove)
545 cmd.Parameters.AddWithValue(":Notes", note.Notes);
546 cmd.Parameters.AddWithValue(":TargetId", note.TargetId.ToString ());
547 cmd.Parameters.AddWithValue(":UserId", note.UserId.ToString());
548
549 cmd.ExecuteNonQuery();
550 }
551 }
552 catch (Exception e)
553 {
554 m_log.DebugFormat("[PROFILES_DATA]" +
555 ": UpdateAvatarNotes exception {0}", e.Message);
556 return false;
557 }
558 return true;
559 }
560
561 public bool GetAvatarProperties(ref UserProfileProperties props, ref string result)
562 {
563 IDataReader reader = null;
564 string query = string.Empty;
565
566 query += "SELECT * FROM userprofile WHERE ";
567 query += "useruuid = :Id";
568
569 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
570 {
571 cmd.CommandText = query;
572 cmd.Parameters.AddWithValue(":Id", props.UserId.ToString());
573
574
575 try
576 {
577 reader = cmd.ExecuteReader();
578 }
579 catch(Exception e)
580 {
581 m_log.DebugFormat("[PROFILES_DATA]" +
582 ": GetAvatarProperties exception {0}", e.Message);
583 result = e.Message;
584 return false;
585 }
586 if(reader != null && reader.Read())
587 {
588 m_log.DebugFormat("[PROFILES_DATA]" +
589 ": Getting data for {0}.", props.UserId);
590
591 props.WebUrl = (string)reader["profileURL"];
592 UUID.TryParse((string)reader["profileImage"], out props.ImageId);
593 props.AboutText = (string)reader["profileAboutText"];
594 UUID.TryParse((string)reader["profileFirstImage"], out props.FirstLifeImageId);
595 props.FirstLifeText = (string)reader["profileFirstText"];
596 UUID.TryParse((string)reader["profilePartner"], out props.PartnerId);
597 props.WantToMask = (int)reader["profileWantToMask"];
598 props.WantToText = (string)reader["profileWantToText"];
599 props.SkillsMask = (int)reader["profileSkillsMask"];
600 props.SkillsText = (string)reader["profileSkillsText"];
601 props.Language = (string)reader["profileLanguages"];
602 }
603 else
604 {
605 m_log.DebugFormat("[PROFILES_DATA]" +
606 ": No data for {0}", props.UserId);
607
608 props.WebUrl = string.Empty;
609 props.ImageId = UUID.Zero;
610 props.AboutText = string.Empty;
611 props.FirstLifeImageId = UUID.Zero;
612 props.FirstLifeText = string.Empty;
613 props.PartnerId = UUID.Zero;
614 props.WantToMask = 0;
615 props.WantToText = string.Empty;
616 props.SkillsMask = 0;
617 props.SkillsText = string.Empty;
618 props.Language = string.Empty;
619 props.PublishProfile = false;
620 props.PublishMature = false;
621
622 query = "INSERT INTO userprofile (";
623 query += "useruuid, ";
624 query += "profilePartner, ";
625 query += "profileAllowPublish, ";
626 query += "profileMaturePublish, ";
627 query += "profileURL, ";
628 query += "profileWantToMask, ";
629 query += "profileWantToText, ";
630 query += "profileSkillsMask, ";
631 query += "profileSkillsText, ";
632 query += "profileLanguages, ";
633 query += "profileImage, ";
634 query += "profileAboutText, ";
635 query += "profileFirstImage, ";
636 query += "profileFirstText) VALUES (";
637 query += ":userId, ";
638 query += ":profilePartner, ";
639 query += ":profileAllowPublish, ";
640 query += ":profileMaturePublish, ";
641 query += ":profileURL, ";
642 query += ":profileWantToMask, ";
643 query += ":profileWantToText, ";
644 query += ":profileSkillsMask, ";
645 query += ":profileSkillsText, ";
646 query += ":profileLanguages, ";
647 query += ":profileImage, ";
648 query += ":profileAboutText, ";
649 query += ":profileFirstImage, ";
650 query += ":profileFirstText)";
651
652 using (SqliteCommand put = (SqliteCommand)m_connection.CreateCommand())
653 {
654 put.CommandText = query;
655 put.Parameters.AddWithValue(":userId", props.UserId.ToString());
656 put.Parameters.AddWithValue(":profilePartner", props.PartnerId.ToString());
657 put.Parameters.AddWithValue(":profileAllowPublish", props.PublishProfile);
658 put.Parameters.AddWithValue(":profileMaturePublish", props.PublishMature);
659 put.Parameters.AddWithValue(":profileURL", props.WebUrl);
660 put.Parameters.AddWithValue(":profileWantToMask", props.WantToMask);
661 put.Parameters.AddWithValue(":profileWantToText", props.WantToText);
662 put.Parameters.AddWithValue(":profileSkillsMask", props.SkillsMask);
663 put.Parameters.AddWithValue(":profileSkillsText", props.SkillsText);
664 put.Parameters.AddWithValue(":profileLanguages", props.Language);
665 put.Parameters.AddWithValue(":profileImage", props.ImageId.ToString());
666 put.Parameters.AddWithValue(":profileAboutText", props.AboutText);
667 put.Parameters.AddWithValue(":profileFirstImage", props.FirstLifeImageId.ToString());
668 put.Parameters.AddWithValue(":profileFirstText", props.FirstLifeText);
669
670 put.ExecuteNonQuery();
671 }
672 }
673 }
674 return true;
675 }
676
677 public bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result)
678 {
679 string query = string.Empty;
680
681 query += "UPDATE userprofile SET ";
682 query += "profileURL=:profileURL, ";
683 query += "profileImage=:image, ";
684 query += "profileAboutText=:abouttext,";
685 query += "profileFirstImage=:firstlifeimage,";
686 query += "profileFirstText=:firstlifetext ";
687 query += "WHERE useruuid=:uuid";
688
689 try
690 {
691 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
692 {
693 cmd.CommandText = query;
694 cmd.Parameters.AddWithValue(":profileURL", props.WebUrl);
695 cmd.Parameters.AddWithValue(":image", props.ImageId.ToString());
696 cmd.Parameters.AddWithValue(":abouttext", props.AboutText);
697 cmd.Parameters.AddWithValue(":firstlifeimage", props.FirstLifeImageId.ToString());
698 cmd.Parameters.AddWithValue(":firstlifetext", props.FirstLifeText);
699 cmd.Parameters.AddWithValue(":uuid", props.UserId.ToString());
700
701 cmd.ExecuteNonQuery();
702 }
703 }
704 catch (Exception e)
705 {
706 m_log.DebugFormat("[PROFILES_DATA]" +
707 ": AgentPropertiesUpdate exception {0}", e.Message);
708
709 return false;
710 }
711 return true;
712 }
713
714 public bool UpdateAvatarInterests(UserProfileProperties up, ref string result)
715 {
716 string query = string.Empty;
717
718 query += "UPDATE userprofile SET ";
719 query += "profileWantToMask=:WantMask, ";
720 query += "profileWantToText=:WantText,";
721 query += "profileSkillsMask=:SkillsMask,";
722 query += "profileSkillsText=:SkillsText, ";
723 query += "profileLanguages=:Languages ";
724 query += "WHERE useruuid=:uuid";
725
726 try
727 {
728 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
729 {
730 cmd.CommandText = query;
731 cmd.Parameters.AddWithValue(":WantMask", up.WantToMask);
732 cmd.Parameters.AddWithValue(":WantText", up.WantToText);
733 cmd.Parameters.AddWithValue(":SkillsMask", up.SkillsMask);
734 cmd.Parameters.AddWithValue(":SkillsText", up.SkillsText);
735 cmd.Parameters.AddWithValue(":Languages", up.Language);
736 cmd.Parameters.AddWithValue(":uuid", up.UserId.ToString());
737
738 cmd.ExecuteNonQuery();
739 }
740 }
741 catch (Exception e)
742 {
743 m_log.DebugFormat("[PROFILES_DATA]" +
744 ": AgentInterestsUpdate exception {0}", e.Message);
745 result = e.Message;
746 return false;
747 }
748 return true;
749 }
750
751 /*
752 public bool UpdateUserPreferences(ref UserPreferences pref, ref string result)
753 {
754 string query = string.Empty;
755
756 query += "UPDATE usersettings SET ";
757 query += "imviaemail=:ImViaEmail, ";
758 query += "visible=:Visible ";
759 query += "WHERE useruuid=:uuid";
760
761 try
762 {
763 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
764 {
765 cmd.CommandText = query;
766 cmd.Parameters.AddWithValue(":ImViaEmail", pref.IMViaEmail);
767 cmd.Parameters.AddWithValue(":Visible", pref.Visible);
768 cmd.Parameters.AddWithValue(":uuid", pref.UserId.ToString());
769
770 cmd.ExecuteNonQuery();
771 }
772 }
773 catch (Exception e)
774 {
775 m_log.DebugFormat("[PROFILES_DATA]" +
776 ": AgentInterestsUpdate exception {0}", e.Message);
777 result = e.Message;
778 return false;
779 }
780 return true;
781 }
782
783 public bool GetUserPreferences(ref UserPreferences pref, ref string result)
784 {
785 IDataReader reader = null;
786 string query = string.Empty;
787
788 query += "SELECT imviaemail,visible,email FROM ";
789 query += "usersettings WHERE ";
790 query += "useruuid = :Id";
791
792 OSDArray data = new OSDArray();
793
794 try
795 {
796 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
797 {
798 cmd.CommandText = query;
799 cmd.Parameters.AddWithValue("?Id", pref.UserId.ToString());
800
801 using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
802 {
803 if(reader.Read())
804 {
805 bool.TryParse((string)reader["imviaemail"], out pref.IMViaEmail);
806 bool.TryParse((string)reader["visible"], out pref.Visible);
807 pref.EMail = (string)reader["email"];
808 }
809 else
810 {
811 query = "INSERT INTO usersettings VALUES ";
812 query += "(:Id,'false','false', :Email)";
813
814 using (SqliteCommand put = (SqliteCommand)m_connection.CreateCommand())
815 {
816 put.Parameters.AddWithValue(":Id", pref.UserId.ToString());
817 put.Parameters.AddWithValue(":Email", pref.EMail);
818 put.ExecuteNonQuery();
819
820 }
821 }
822 }
823 }
824 }
825 catch (Exception e)
826 {
827 m_log.DebugFormat("[PROFILES_DATA]" +
828 ": Get preferences exception {0}", e.Message);
829 result = e.Message;
830 return false;
831 }
832 return true;
833 }
834 */
835
836 public bool GetUserAppData(ref UserAppData props, ref string result)
837 {
838 IDataReader reader = null;
839 string query = string.Empty;
840
841 query += "SELECT * FROM `userdata` WHERE ";
842 query += "UserId = :Id AND ";
843 query += "TagId = :TagId";
844
845 try
846 {
847 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
848 {
849 cmd.CommandText = query;
850 cmd.Parameters.AddWithValue(":Id", props.UserId.ToString());
851 cmd.Parameters.AddWithValue (":TagId", props.TagId.ToString());
852
853 using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
854 {
855 if(reader.Read())
856 {
857 props.DataKey = (string)reader["DataKey"];
858 props.DataVal = (string)reader["DataVal"];
859 }
860 else
861 {
862 query += "INSERT INTO userdata VALUES ( ";
863 query += ":UserId,";
864 query += ":TagId,";
865 query += ":DataKey,";
866 query += ":DataVal) ";
867
868 using (SqliteCommand put = (SqliteCommand)m_connection.CreateCommand())
869 {
870 put.Parameters.AddWithValue(":Id", props.UserId.ToString());
871 put.Parameters.AddWithValue(":TagId", props.TagId.ToString());
872 put.Parameters.AddWithValue(":DataKey", props.DataKey.ToString());
873 put.Parameters.AddWithValue(":DataVal", props.DataVal.ToString());
874
875 put.ExecuteNonQuery();
876 }
877 }
878 }
879 }
880 }
881 catch (Exception e)
882 {
883 m_log.DebugFormat("[PROFILES_DATA]" +
884 ": Requst application data exception {0}", e.Message);
885 result = e.Message;
886 return false;
887 }
888 return true;
889 }
890 public bool SetUserAppData(UserAppData props, ref string result)
891 {
892 string query = string.Empty;
893
894 query += "UPDATE userdata SET ";
895 query += "TagId = :TagId, ";
896 query += "DataKey = :DataKey, ";
897 query += "DataVal = :DataVal WHERE ";
898 query += "UserId = :UserId AND ";
899 query += "TagId = :TagId";
900
901 try
902 {
903 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
904 {
905 cmd.CommandText = query;
906 cmd.Parameters.AddWithValue(":UserId", props.UserId.ToString());
907 cmd.Parameters.AddWithValue(":TagId", props.TagId.ToString ());
908 cmd.Parameters.AddWithValue(":DataKey", props.DataKey.ToString ());
909 cmd.Parameters.AddWithValue(":DataVal", props.DataKey.ToString ());
910
911 cmd.ExecuteNonQuery();
912 }
913 }
914 catch (Exception e)
915 {
916 m_log.DebugFormat("[PROFILES_DATA]" +
917 ": SetUserData exception {0}", e.Message);
918 return false;
919 }
920 return true;
921 }
922 public OSDArray GetUserImageAssets(UUID avatarId)
923 {
924 IDataReader reader = null;
925 OSDArray data = new OSDArray();
926 string query = "SELECT `snapshotuuid` FROM {0} WHERE `creatoruuid` = :Id";
927
928 // Get classified image assets
929
930
931 try
932 {
933 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
934 {
935 cmd.CommandText = query;
936 cmd.Parameters.AddWithValue(":Id", avatarId.ToString());
937
938 using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
939 {
940 while(reader.Read())
941 {
942 data.Add(new OSDString((string)reader["snapshotuuid"].ToString()));
943 }
944 }
945 }
946
947 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
948 {
949 cmd.CommandText = query;
950 cmd.Parameters.AddWithValue(":Id", avatarId.ToString());
951
952 using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
953 {
954 if(reader.Read())
955 {
956 data.Add(new OSDString((string)reader["snapshotuuid"].ToString ()));
957 }
958 }
959 }
960
961 query = "SELECT `profileImage`, `profileFirstImage` FROM `userprofile` WHERE `useruuid` = :Id";
962
963 using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand())
964 {
965 cmd.CommandText = query;
966 cmd.Parameters.AddWithValue(":Id", avatarId.ToString());
967
968 using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow))
969 {
970 if(reader.Read())
971 {
972 data.Add(new OSDString((string)reader["profileImage"].ToString ()));
973 data.Add(new OSDString((string)reader["profileFirstImage"].ToString ()));
974 }
975 }
976 }
977 }
978 catch (Exception e)
979 {
980 m_log.DebugFormat("[PROFILES_DATA]" +
981 ": GetAvatarNotes exception {0}", e.Message);
982 }
983 return data;
984 }
985 #endregion
986 }
987}
988
diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs
index ffcc584..f2fe494 100644
--- a/OpenSim/Framework/AgentCircuitData.cs
+++ b/OpenSim/Framework/AgentCircuitData.cs
@@ -128,7 +128,31 @@ namespace OpenSim.Framework
128 /// <summary> 128 /// <summary>
129 /// Viewer's version string as reported by the viewer at login 129 /// Viewer's version string as reported by the viewer at login
130 /// </summary> 130 /// </summary>
131 public string Viewer; 131 private string m_viewerInternal;
132
133 /// <summary>
134 /// Viewer's version string
135 /// </summary>
136 public string Viewer
137 {
138 set { m_viewerInternal = value; }
139
140 // Try to return consistent viewer string taking into account
141 // that viewers have chaagned how version is reported
142 // See http://opensimulator.org/mantis/view.php?id=6851
143 get
144 {
145 // Old style version string contains viewer name followed by a space followed by a version number
146 if (m_viewerInternal == null || m_viewerInternal.Contains(" "))
147 {
148 return m_viewerInternal;
149 }
150 else // New style version contains no spaces, just version number
151 {
152 return Channel + " " + m_viewerInternal;
153 }
154 }
155 }
132 156
133 /// <summary> 157 /// <summary>
134 /// The channel strinf sent by the viewer at login 158 /// The channel strinf sent by the viewer at login
diff --git a/OpenSim/Framework/Animation.cs b/OpenSim/Framework/Animation.cs
index 232f5a1..3425505 100644
--- a/OpenSim/Framework/Animation.cs
+++ b/OpenSim/Framework/Animation.cs
@@ -120,5 +120,24 @@ namespace OpenSim.Framework
120 sequenceNum = args["seq_num"].AsInteger(); 120 sequenceNum = args["seq_num"].AsInteger();
121 } 121 }
122 122
123 public override bool Equals(object obj)
124 {
125 Animation other = obj as Animation;
126 if (other != null)
127 {
128 return (other.AnimID.Equals(this.AnimID)
129 && other.SequenceNum == this.SequenceNum
130 && other.ObjectID.Equals(this.ObjectID) );
131 }
132 return base.Equals(obj);
133 }
134
135 public override string ToString()
136 {
137 return "AnimID=" + AnimID.ToString()
138 + "/seq=" + SequenceNum.ToString()
139 + "/objID=" + ObjectID.ToString();
140 }
141
123 } 142 }
124} 143}
diff --git a/OpenSim/Framework/AssemblyInfo.cs b/OpenSim/Framework/AssemblyInfo.cs
index d6b4e6a..287b988 100644
--- a/OpenSim/Framework/AssemblyInfo.cs
+++ b/OpenSim/Framework/AssemblyInfo.cs
@@ -59,4 +59,4 @@ using System.Runtime.InteropServices;
59// Revision 59// Revision
60// 60//
61 61
62[assembly : AssemblyVersion("0.7.6.*")] 62[assembly : AssemblyVersion("0.8.0.*")]
diff --git a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
index feffa26..11fece3 100644
--- a/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/AssetLoader/Filesystem/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/BasicDOSProtector.cs b/OpenSim/Framework/BasicDOSProtector.cs
new file mode 100644
index 0000000..89bfa94
--- /dev/null
+++ b/OpenSim/Framework/BasicDOSProtector.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 copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Reflection;
30using log4net;
31
32namespace OpenSim.Framework
33{
34
35 public class BasicDOSProtector
36 {
37 public enum ThrottleAction
38 {
39 DoThrottledMethod,
40 DoThrow
41 }
42 private readonly CircularBuffer<int> _generalRequestTimes; // General request checker
43 private readonly BasicDosProtectorOptions _options;
44 private readonly Dictionary<string, CircularBuffer<int>> _deeperInspection; // per client request checker
45 private readonly Dictionary<string, int> _tempBlocked; // blocked list
46 private readonly Dictionary<string, int> _sessions;
47 private readonly System.Timers.Timer _forgetTimer; // Cleanup timer
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 private readonly System.Threading.ReaderWriterLockSlim _blockLockSlim = new System.Threading.ReaderWriterLockSlim();
50 private readonly System.Threading.ReaderWriterLockSlim _sessionLockSlim = new System.Threading.ReaderWriterLockSlim();
51 public BasicDOSProtector(BasicDosProtectorOptions options)
52 {
53 _generalRequestTimes = new CircularBuffer<int>(options.MaxRequestsInTimeframe + 1, true);
54 _generalRequestTimes.Put(0);
55 _options = options;
56 _deeperInspection = new Dictionary<string, CircularBuffer<int>>();
57 _tempBlocked = new Dictionary<string, int>();
58 _sessions = new Dictionary<string, int>();
59 _forgetTimer = new System.Timers.Timer();
60 _forgetTimer.Elapsed += delegate
61 {
62 _forgetTimer.Enabled = false;
63
64 List<string> removes = new List<string>();
65 _blockLockSlim.EnterReadLock();
66 foreach (string str in _tempBlocked.Keys)
67 {
68 if (
69 Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(),
70 _tempBlocked[str]) > 0)
71 removes.Add(str);
72 }
73 _blockLockSlim.ExitReadLock();
74 lock (_deeperInspection)
75 {
76 _blockLockSlim.EnterWriteLock();
77 for (int i = 0; i < removes.Count; i++)
78 {
79 _tempBlocked.Remove(removes[i]);
80 _deeperInspection.Remove(removes[i]);
81 _sessions.Remove(removes[i]);
82 }
83 _blockLockSlim.ExitWriteLock();
84 }
85 foreach (string str in removes)
86 {
87 m_log.InfoFormat("[{0}] client: {1} is no longer blocked.",
88 _options.ReportingName, str);
89 }
90 _blockLockSlim.EnterReadLock();
91 if (_tempBlocked.Count > 0)
92 _forgetTimer.Enabled = true;
93 _blockLockSlim.ExitReadLock();
94 };
95
96 _forgetTimer.Interval = _options.ForgetTimeSpan.TotalMilliseconds;
97 }
98
99 /// <summary>
100 /// Given a string Key, Returns if that context is blocked
101 /// </summary>
102 /// <param name="key">A Key identifying the context</param>
103 /// <returns>bool Yes or No, True or False for blocked</returns>
104 public bool IsBlocked(string key)
105 {
106 bool ret = false;
107 _blockLockSlim.EnterReadLock();
108 ret = _tempBlocked.ContainsKey(key);
109 _blockLockSlim.ExitReadLock();
110 return ret;
111 }
112
113 /// <summary>
114 /// Process the velocity of this context
115 /// </summary>
116 /// <param name="key"></param>
117 /// <param name="endpoint"></param>
118 /// <returns></returns>
119 public bool Process(string key, string endpoint)
120 {
121 if (_options.MaxRequestsInTimeframe < 1 || _options.RequestTimeSpan.TotalMilliseconds < 1)
122 return true;
123
124 string clientstring = key;
125
126 _blockLockSlim.EnterReadLock();
127 if (_tempBlocked.ContainsKey(clientstring))
128 {
129 _blockLockSlim.ExitReadLock();
130
131 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod)
132 return false;
133 else
134 throw new System.Security.SecurityException("Throttled");
135 }
136
137 _blockLockSlim.ExitReadLock();
138
139 lock (_generalRequestTimes)
140 _generalRequestTimes.Put(Util.EnvironmentTickCount());
141
142 if (_options.MaxConcurrentSessions > 0)
143 {
144 int sessionscount = 0;
145
146 _sessionLockSlim.EnterReadLock();
147 if (_sessions.ContainsKey(key))
148 sessionscount = _sessions[key];
149 _sessionLockSlim.ExitReadLock();
150
151 if (sessionscount > _options.MaxConcurrentSessions)
152 {
153 // Add to blocking and cleanup methods
154 lock (_deeperInspection)
155 {
156 _blockLockSlim.EnterWriteLock();
157 if (!_tempBlocked.ContainsKey(clientstring))
158 {
159 _tempBlocked.Add(clientstring,
160 Util.EnvironmentTickCount() +
161 (int) _options.ForgetTimeSpan.TotalMilliseconds);
162 _forgetTimer.Enabled = true;
163 m_log.WarnFormat("[{0}]: client: {1} is blocked for {2} milliseconds based on concurrency, X-ForwardedForAllowed status is {3}, endpoint:{4}", _options.ReportingName, clientstring, _options.ForgetTimeSpan.TotalMilliseconds, _options.AllowXForwardedFor, endpoint);
164
165 }
166 else
167 _tempBlocked[clientstring] = Util.EnvironmentTickCount() +
168 (int) _options.ForgetTimeSpan.TotalMilliseconds;
169 _blockLockSlim.ExitWriteLock();
170
171 }
172
173
174 }
175 else
176 ProcessConcurrency(key, endpoint);
177 }
178 if (_generalRequestTimes.Size == _generalRequestTimes.Capacity &&
179 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _generalRequestTimes.Get()) <
180 _options.RequestTimeSpan.TotalMilliseconds))
181 {
182 //Trigger deeper inspection
183 if (DeeperInspection(key, endpoint))
184 return true;
185 if (_options.ThrottledAction == ThrottleAction.DoThrottledMethod)
186 return false;
187 else
188 throw new System.Security.SecurityException("Throttled");
189 }
190 return true;
191 }
192 private void ProcessConcurrency(string key, string endpoint)
193 {
194 _sessionLockSlim.EnterWriteLock();
195 if (_sessions.ContainsKey(key))
196 _sessions[key] = _sessions[key] + 1;
197 else
198 _sessions.Add(key,1);
199 _sessionLockSlim.ExitWriteLock();
200 }
201 public void ProcessEnd(string key, string endpoint)
202 {
203 _sessionLockSlim.EnterWriteLock();
204 if (_sessions.ContainsKey(key))
205 {
206 _sessions[key]--;
207 if (_sessions[key] <= 0)
208 _sessions.Remove(key);
209 }
210 else
211 _sessions.Add(key, 1);
212
213 _sessionLockSlim.ExitWriteLock();
214 }
215
216 /// <summary>
217 /// At this point, the rate limiting code needs to track 'per user' velocity.
218 /// </summary>
219 /// <param name="key">Context Key, string representing a rate limiting context</param>
220 /// <param name="endpoint"></param>
221 /// <returns></returns>
222 private bool DeeperInspection(string key, string endpoint)
223 {
224 lock (_deeperInspection)
225 {
226 string clientstring = key;
227
228
229 if (_deeperInspection.ContainsKey(clientstring))
230 {
231 _deeperInspection[clientstring].Put(Util.EnvironmentTickCount());
232 if (_deeperInspection[clientstring].Size == _deeperInspection[clientstring].Capacity &&
233 (Util.EnvironmentTickCountSubtract(Util.EnvironmentTickCount(), _deeperInspection[clientstring].Get()) <
234 _options.RequestTimeSpan.TotalMilliseconds))
235 {
236 //Looks like we're over the limit
237 _blockLockSlim.EnterWriteLock();
238 if (!_tempBlocked.ContainsKey(clientstring))
239 _tempBlocked.Add(clientstring, Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds);
240 else
241 _tempBlocked[clientstring] = Util.EnvironmentTickCount() + (int)_options.ForgetTimeSpan.TotalMilliseconds;
242 _blockLockSlim.ExitWriteLock();
243
244 m_log.WarnFormat("[{0}]: client: {1} is blocked for {2} milliseconds, X-ForwardedForAllowed status is {3}, endpoint:{4}", _options.ReportingName, clientstring, _options.ForgetTimeSpan.TotalMilliseconds, _options.AllowXForwardedFor, endpoint);
245
246 return false;
247 }
248 //else
249 // return true;
250 }
251 else
252 {
253 _deeperInspection.Add(clientstring, new CircularBuffer<int>(_options.MaxRequestsInTimeframe + 1, true));
254 _deeperInspection[clientstring].Put(Util.EnvironmentTickCount());
255 _forgetTimer.Enabled = true;
256 }
257
258 }
259 return true;
260 }
261
262 }
263
264
265 public class BasicDosProtectorOptions
266 {
267 public int MaxRequestsInTimeframe;
268 public TimeSpan RequestTimeSpan;
269 public TimeSpan ForgetTimeSpan;
270 public bool AllowXForwardedFor;
271 public string ReportingName = "BASICDOSPROTECTOR";
272 public BasicDOSProtector.ThrottleAction ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod;
273 public int MaxConcurrentSessions;
274 }
275}
diff --git a/OpenSim/Framework/BlockingQueue.cs b/OpenSim/Framework/BlockingQueue.cs
index 3658161..3e90fac 100644
--- a/OpenSim/Framework/BlockingQueue.cs
+++ b/OpenSim/Framework/BlockingQueue.cs
@@ -58,7 +58,7 @@ namespace OpenSim.Framework
58 { 58 {
59 lock (m_queueSync) 59 lock (m_queueSync)
60 { 60 {
61 if (m_queue.Count < 1 && m_pqueue.Count < 1) 61 while (m_queue.Count < 1 && m_pqueue.Count < 1)
62 { 62 {
63 Monitor.Wait(m_queueSync); 63 Monitor.Wait(m_queueSync);
64 } 64 }
@@ -76,9 +76,10 @@ namespace OpenSim.Framework
76 { 76 {
77 lock (m_queueSync) 77 lock (m_queueSync)
78 { 78 {
79 if (m_queue.Count < 1 && m_pqueue.Count < 1) 79 bool success = true;
80 while (m_queue.Count < 1 && m_pqueue.Count < 1 && success)
80 { 81 {
81 Monitor.Wait(m_queueSync, msTimeout); 82 success = Monitor.Wait(m_queueSync, msTimeout);
82 } 83 }
83 84
84 if (m_pqueue.Count > 0) 85 if (m_pqueue.Count > 0)
@@ -89,8 +90,17 @@ namespace OpenSim.Framework
89 } 90 }
90 } 91 }
91 92
93 /// <summary>
94 /// Indicate whether this queue contains the given item.
95 /// </summary>
96 /// <remarks>
97 /// This method is not thread-safe. Do not rely on the result without consistent external locking.
98 /// </remarks>
92 public bool Contains(T item) 99 public bool Contains(T item)
93 { 100 {
101 if (m_queue.Count < 1 && m_pqueue.Count < 1)
102 return false;
103
94 lock (m_queueSync) 104 lock (m_queueSync)
95 { 105 {
96 if (m_pqueue.Contains(item)) 106 if (m_pqueue.Contains(item))
@@ -99,16 +109,28 @@ namespace OpenSim.Framework
99 } 109 }
100 } 110 }
101 111
112 /// <summary>
113 /// Return a count of the number of requests on this queue.
114 /// </summary>
115 /// <remarks>
116 /// This method is not thread-safe. Do not rely on the result without consistent external locking.
117 /// </remarks>
102 public int Count() 118 public int Count()
103 { 119 {
104 lock (m_queueSync) 120 return m_queue.Count + m_pqueue.Count;
105 {
106 return m_queue.Count+m_pqueue.Count;
107 }
108 } 121 }
109 122
123 /// <summary>
124 /// Return the array of items on this queue.
125 /// </summary>
126 /// <remarks>
127 /// This method is not thread-safe. Do not rely on the result without consistent external locking.
128 /// </remarks>
110 public T[] GetQueueArray() 129 public T[] GetQueueArray()
111 { 130 {
131 if (m_queue.Count < 1 && m_pqueue.Count < 1)
132 return new T[0];
133
112 lock (m_queueSync) 134 lock (m_queueSync)
113 { 135 {
114 return m_queue.ToArray(); 136 return m_queue.ToArray();
diff --git a/OpenSim/Framework/CachedTextureEventArg.cs b/OpenSim/Framework/CachedTextureEventArg.cs
new file mode 100644
index 0000000..239fc56
--- /dev/null
+++ b/OpenSim/Framework/CachedTextureEventArg.cs
@@ -0,0 +1,46 @@
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.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Framework
33{
34 public class CachedTextureRequestArg
35 {
36 public int BakedTextureIndex;
37 public UUID WearableHashID;
38 }
39
40 public class CachedTextureResponseArg
41 {
42 public int BakedTextureIndex;
43 public UUID BakedTextureID;
44 public String HostName;
45 }
46}
diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs
index 8c32734..2a8e67d 100644
--- a/OpenSim/Framework/ChildAgentDataUpdate.cs
+++ b/OpenSim/Framework/ChildAgentDataUpdate.cs
@@ -171,9 +171,10 @@ namespace OpenSim.Framework
171 /// Soon to be decommissioned 171 /// Soon to be decommissioned
172 /// </summary> 172 /// </summary>
173 /// <param name="cAgent"></param> 173 /// <param name="cAgent"></param>
174 public void CopyFrom(ChildAgentDataUpdate cAgent) 174 public void CopyFrom(ChildAgentDataUpdate cAgent, UUID sid)
175 { 175 {
176 AgentID = new UUID(cAgent.AgentID); 176 AgentID = new UUID(cAgent.AgentID);
177 SessionID = sid;
177 178
178 // next: ??? 179 // next: ???
179 Size = new Vector3(); 180 Size = new Vector3();
@@ -291,7 +292,13 @@ namespace OpenSim.Framework
291 public Vector3 AtAxis; 292 public Vector3 AtAxis;
292 public Vector3 LeftAxis; 293 public Vector3 LeftAxis;
293 public Vector3 UpAxis; 294 public Vector3 UpAxis;
294 public bool ChangedGrid; 295
296 /// <summary>
297 /// Signal on a V2 teleport that Scene.IncomingChildAgentDataUpdate(AgentData ad) should wait for the
298 /// scene presence to become root (triggered when the viewer sends a CompleteAgentMovement UDP packet after
299 /// establishing the connection triggered by it's receipt of a TeleportFinish EQ message).
300 /// </summary>
301 public bool SenderWantsToWaitForRoot;
295 302
296 public float Far; 303 public float Far;
297 public float Aspect; 304 public float Aspect;
@@ -362,8 +369,9 @@ namespace OpenSim.Framework
362 args["left_axis"] = OSD.FromString(LeftAxis.ToString()); 369 args["left_axis"] = OSD.FromString(LeftAxis.ToString());
363 args["up_axis"] = OSD.FromString(UpAxis.ToString()); 370 args["up_axis"] = OSD.FromString(UpAxis.ToString());
364 371
365 372 //backwards compatibility
366 args["changed_grid"] = OSD.FromBoolean(ChangedGrid); 373 args["changed_grid"] = OSD.FromBoolean(SenderWantsToWaitForRoot);
374 args["wait_for_root"] = OSD.FromBoolean(SenderWantsToWaitForRoot);
367 args["far"] = OSD.FromReal(Far); 375 args["far"] = OSD.FromReal(Far);
368 args["aspect"] = OSD.FromReal(Aspect); 376 args["aspect"] = OSD.FromReal(Aspect);
369 377
@@ -536,8 +544,8 @@ namespace OpenSim.Framework
536 if (args["up_axis"] != null) 544 if (args["up_axis"] != null)
537 Vector3.TryParse(args["up_axis"].AsString(), out AtAxis); 545 Vector3.TryParse(args["up_axis"].AsString(), out AtAxis);
538 546
539 if (args["changed_grid"] != null) 547 if (args.ContainsKey("wait_for_root") && args["wait_for_root"] != null)
540 ChangedGrid = args["changed_grid"].AsBoolean(); 548 SenderWantsToWaitForRoot = args["wait_for_root"].AsBoolean();
541 549
542 if (args["far"] != null) 550 if (args["far"] != null)
543 Far = (float)(args["far"].AsReal()); 551 Far = (float)(args["far"].AsReal());
diff --git a/OpenSim/Framework/CircularBuffer.cs b/OpenSim/Framework/CircularBuffer.cs
new file mode 100644
index 0000000..e919337
--- /dev/null
+++ b/OpenSim/Framework/CircularBuffer.cs
@@ -0,0 +1,312 @@
1/*
2Copyright (c) 2012, Alex Regueiro
3All rights reserved.
4Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
5following conditions are met:
6
7Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
9in the documentation and/or other materials provided with the distribution.
10
11THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
12BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
13IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
14OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
15OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
16OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
17POSSIBILITY OF SUCH DAMAGE.
18*/
19using System;
20using System.Collections;
21using System.Collections.Generic;
22using System.Threading;
23
24namespace OpenSim.Framework
25{
26 public class CircularBuffer<T> : ICollection<T>, IEnumerable<T>, ICollection, IEnumerable
27 {
28 private int capacity;
29 private int size;
30 private int head;
31 private int tail;
32 private T[] buffer;
33
34 [NonSerialized()]
35 private object syncRoot;
36
37 public CircularBuffer(int capacity)
38 : this(capacity, false)
39 {
40 }
41
42 public CircularBuffer(int capacity, bool allowOverflow)
43 {
44 if (capacity < 0)
45 throw new ArgumentException("Needs to have at least 1","capacity");
46
47 this.capacity = capacity;
48 size = 0;
49 head = 0;
50 tail = 0;
51 buffer = new T[capacity];
52 AllowOverflow = allowOverflow;
53 }
54
55 public bool AllowOverflow
56 {
57 get;
58 set;
59 }
60
61 public int Capacity
62 {
63 get { return capacity; }
64 set
65 {
66 if (value == capacity)
67 return;
68
69 if (value < size)
70 throw new ArgumentOutOfRangeException("value","Capacity is too small.");
71
72 var dst = new T[value];
73 if (size > 0)
74 CopyTo(dst);
75 buffer = dst;
76
77 capacity = value;
78 }
79 }
80
81 public int Size
82 {
83 get { return size; }
84 }
85
86 public bool Contains(T item)
87 {
88 int bufferIndex = head;
89 var comparer = EqualityComparer<T>.Default;
90 for (int i = 0; i < size; i++, bufferIndex++)
91 {
92 if (bufferIndex == capacity)
93 bufferIndex = 0;
94
95 if (item == null && buffer[bufferIndex] == null)
96 return true;
97 else if ((buffer[bufferIndex] != null) &&
98 comparer.Equals(buffer[bufferIndex], item))
99 return true;
100 }
101
102 return false;
103 }
104
105 public void Clear()
106 {
107 size = 0;
108 head = 0;
109 tail = 0;
110 }
111
112 public int Put(T[] src)
113 {
114 return Put(src, 0, src.Length);
115 }
116
117 public int Put(T[] src, int offset, int count)
118 {
119 if (!AllowOverflow && count > capacity - size)
120 throw new InvalidOperationException("Buffer Overflow");
121
122 int srcIndex = offset;
123 for (int i = 0; i < count; i++, tail++, srcIndex++)
124 {
125 if (tail == capacity)
126 tail = 0;
127 buffer[tail] = src[srcIndex];
128 }
129 size = Math.Min(size + count, capacity);
130 return count;
131 }
132
133 public void Put(T item)
134 {
135 if (!AllowOverflow && size == capacity)
136 throw new InvalidOperationException("Buffer Overflow");
137
138 buffer[tail] = item;
139 if (++tail == capacity)
140 tail = 0;
141 size++;
142 }
143
144 public void Skip(int count)
145 {
146 head += count;
147 if (head >= capacity)
148 head -= capacity;
149 }
150
151 public T[] Get(int count)
152 {
153 var dst = new T[count];
154 Get(dst);
155 return dst;
156 }
157
158 public int Get(T[] dst)
159 {
160 return Get(dst, 0, dst.Length);
161 }
162
163 public int Get(T[] dst, int offset, int count)
164 {
165 int realCount = Math.Min(count, size);
166 int dstIndex = offset;
167 for (int i = 0; i < realCount; i++, head++, dstIndex++)
168 {
169 if (head == capacity)
170 head = 0;
171 dst[dstIndex] = buffer[head];
172 }
173 size -= realCount;
174 return realCount;
175 }
176
177 public T Get()
178 {
179 if (size == 0)
180 throw new InvalidOperationException("Buffer Empty");
181
182 var item = buffer[head];
183 if (++head == capacity)
184 head = 0;
185 size--;
186 return item;
187 }
188
189 public void CopyTo(T[] array)
190 {
191 CopyTo(array, 0);
192 }
193
194 public void CopyTo(T[] array, int arrayIndex)
195 {
196 CopyTo(0, array, arrayIndex, size);
197 }
198
199 public void CopyTo(int index, T[] array, int arrayIndex, int count)
200 {
201 if (count > size)
202 throw new ArgumentOutOfRangeException("count", "Count Too Large");
203
204 int bufferIndex = head;
205 for (int i = 0; i < count; i++, bufferIndex++, arrayIndex++)
206 {
207 if (bufferIndex == capacity)
208 bufferIndex = 0;
209 array[arrayIndex] = buffer[bufferIndex];
210 }
211 }
212
213 public IEnumerator<T> GetEnumerator()
214 {
215 int bufferIndex = head;
216 for (int i = 0; i < size; i++, bufferIndex++)
217 {
218 if (bufferIndex == capacity)
219 bufferIndex = 0;
220
221 yield return buffer[bufferIndex];
222 }
223 }
224
225 public T[] GetBuffer()
226 {
227 return buffer;
228 }
229
230 public T[] ToArray()
231 {
232 var dst = new T[size];
233 CopyTo(dst);
234 return dst;
235 }
236
237 #region ICollection<T> Members
238
239 int ICollection<T>.Count
240 {
241 get { return Size; }
242 }
243
244 bool ICollection<T>.IsReadOnly
245 {
246 get { return false; }
247 }
248
249 void ICollection<T>.Add(T item)
250 {
251 Put(item);
252 }
253
254 bool ICollection<T>.Remove(T item)
255 {
256 if (size == 0)
257 return false;
258
259 Get();
260 return true;
261 }
262
263 #endregion
264
265 #region IEnumerable<T> Members
266
267 IEnumerator<T> IEnumerable<T>.GetEnumerator()
268 {
269 return GetEnumerator();
270 }
271
272 #endregion
273
274 #region ICollection Members
275
276 int ICollection.Count
277 {
278 get { return Size; }
279 }
280
281 bool ICollection.IsSynchronized
282 {
283 get { return false; }
284 }
285
286 object ICollection.SyncRoot
287 {
288 get
289 {
290 if (syncRoot == null)
291 Interlocked.CompareExchange(ref syncRoot, new object(), null);
292 return syncRoot;
293 }
294 }
295
296 void ICollection.CopyTo(Array array, int arrayIndex)
297 {
298 CopyTo((T[])array, arrayIndex);
299 }
300
301 #endregion
302
303 #region IEnumerable Members
304
305 IEnumerator IEnumerable.GetEnumerator()
306 {
307 return (IEnumerator)GetEnumerator();
308 }
309
310 #endregion
311 }
312}
diff --git a/OpenSim/Framework/ClientInfo.cs b/OpenSim/Framework/ClientInfo.cs
index 62acb70..9021315 100644
--- a/OpenSim/Framework/ClientInfo.cs
+++ b/OpenSim/Framework/ClientInfo.cs
@@ -33,12 +33,13 @@ namespace OpenSim.Framework
33{ 33{
34 public class ClientInfo 34 public class ClientInfo
35 { 35 {
36 public AgentCircuitData agentcircuit; 36 public readonly DateTime StartedTime = DateTime.Now;
37 public AgentCircuitData agentcircuit = null;
37 38
38 public Dictionary<uint, byte[]> needAck; 39 public Dictionary<uint, byte[]> needAck;
39 40
40 public List<byte[]> out_packets; 41 public List<byte[]> out_packets = new List<byte[]>();
41 public Dictionary<uint, uint> pendingAcks; 42 public Dictionary<uint, uint> pendingAcks = new Dictionary<uint,uint>();
42 public EndPoint proxyEP; 43 public EndPoint proxyEP;
43 44
44 public uint sequence; 45 public uint sequence;
@@ -53,5 +54,9 @@ namespace OpenSim.Framework
53 public int assetThrottle; 54 public int assetThrottle;
54 public int textureThrottle; 55 public int textureThrottle;
55 public int totalThrottle; 56 public int totalThrottle;
57
58 public Dictionary<string, int> SyncRequests = new Dictionary<string,int>();
59 public Dictionary<string, int> AsyncRequests = new Dictionary<string,int>();
60 public Dictionary<string, int> GenericRequests = new Dictionary<string,int>();
56 } 61 }
57} 62}
diff --git a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
index df8eb52..09611fa 100644
--- a/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Communications/Properties/AssemblyInfo.cs
@@ -61,5 +61,5 @@ using System.Runtime.InteropServices;
61// You can specify all the values or you can default the Revision and Build Numbers 61// You can specify all the values or you can default the Revision and Build Numbers
62// by using the '*' as shown below: 62// by using the '*' as shown below:
63 63
64[assembly : AssemblyVersion("0.7.6.*")] 64[assembly : AssemblyVersion("0.8.0.*")]
65 65
diff --git a/OpenSim/Framework/ConfigSettings.cs b/OpenSim/Framework/ConfigSettings.cs
index 002a371..108a3e4 100644
--- a/OpenSim/Framework/ConfigSettings.cs
+++ b/OpenSim/Framework/ConfigSettings.cs
@@ -31,7 +31,6 @@ namespace OpenSim.Framework
31 { 31 {
32 public string PhysicsEngine { get; set; } 32 public string PhysicsEngine { get; set; }
33 public string MeshEngineName { get; set; } 33 public string MeshEngineName { get; set; }
34 public string StorageDll { get; set; }
35 public string ClientstackDll { get; set; } 34 public string ClientstackDll { get; set; }
36 public string LibrariesXMLFile { get; set; } 35 public string LibrariesXMLFile { get; set; }
37 36
diff --git a/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs b/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
index 3ef9682..05a2e0e 100644
--- a/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Configuration/HTTP/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs b/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
index cbdffeb..d928a94 100644
--- a/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Configuration/XML/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs b/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs
index 43162fc..3152a7d 100644
--- a/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs
+++ b/OpenSim/Framework/Configuration/XML/XmlConfiguration.cs
@@ -121,7 +121,7 @@ namespace OpenSim.Framework.Configuration.XML
121 121
122 public void Commit() 122 public void Commit()
123 { 123 {
124 if (fileName == null || fileName == String.Empty) 124 if (string.IsNullOrEmpty(fileName))
125 return; 125 return;
126 126
127 if (!Directory.Exists(Util.configDir())) 127 if (!Directory.Exists(Util.configDir()))
diff --git a/OpenSim/Framework/Console/AssemblyInfo.cs b/OpenSim/Framework/Console/AssemblyInfo.cs
index c618454..ba59025 100644
--- a/OpenSim/Framework/Console/AssemblyInfo.cs
+++ b/OpenSim/Framework/Console/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.7.6.*")] 58[assembly : AssemblyVersion("0.8.0.*")]
diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs
index 97a86a8..794bfaf 100644
--- a/OpenSim/Framework/Console/ConsoleUtil.cs
+++ b/OpenSim/Framework/Console/ConsoleUtil.cs
@@ -156,12 +156,32 @@ namespace OpenSim.Framework.Console
156 } 156 }
157 157
158 /// <summary> 158 /// <summary>
159 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 159 /// Convert a console integer to an int, automatically complaining if a console is given.
160 /// </summary> 160 /// </summary>
161 /// <param name='console'>Can be null if no console is available.</param> 161 /// <param name='console'>Can be null if no console is available.</param>
162 /// <param name='rawConsoleVector'>/param> 162 /// <param name='rawConsoleVector'>/param>
163 /// <param name='vector'></param> 163 /// <param name='vector'></param>
164 /// <returns></returns> 164 /// <returns></returns>
165 public static bool TryParseConsoleBool(ICommandConsole console, string rawConsoleString, out bool b)
166 {
167 if (!bool.TryParse(rawConsoleString, out b))
168 {
169 if (console != null)
170 console.OutputFormat("ERROR: {0} is not a true or false value", rawConsoleString);
171
172 return false;
173 }
174
175 return true;
176 }
177
178 /// <summary>
179 /// Convert a console integer to an int, automatically complaining if a console is given.
180 /// </summary>
181 /// <param name='console'>Can be null if no console is available.</param>
182 /// <param name='rawConsoleInt'>/param>
183 /// <param name='i'></param>
184 /// <returns></returns>
165 public static bool TryParseConsoleInt(ICommandConsole console, string rawConsoleInt, out int i) 185 public static bool TryParseConsoleInt(ICommandConsole console, string rawConsoleInt, out int i)
166 { 186 {
167 if (!int.TryParse(rawConsoleInt, out i)) 187 if (!int.TryParse(rawConsoleInt, out i))
@@ -174,6 +194,31 @@ namespace OpenSim.Framework.Console
174 194
175 return true; 195 return true;
176 } 196 }
197
198 /// <summary>
199 /// Convert a console integer to a natural int, automatically complaining if a console is given.
200 /// </summary>
201 /// <param name='console'>Can be null if no console is available.</param>
202 /// <param name='rawConsoleInt'>/param>
203 /// <param name='i'></param>
204 /// <returns></returns>
205 public static bool TryParseConsoleNaturalInt(ICommandConsole console, string rawConsoleInt, out int i)
206 {
207 if (TryParseConsoleInt(console, rawConsoleInt, out i))
208 {
209 if (i < 0)
210 {
211 if (console != null)
212 console.OutputFormat("ERROR: {0} is not a positive integer", rawConsoleInt);
213
214 return false;
215 }
216
217 return true;
218 }
219
220 return false;
221 }
177 222
178 /// <summary> 223 /// <summary>
179 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 224 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
diff --git a/OpenSim/Framework/Console/LocalConsole.cs b/OpenSim/Framework/Console/LocalConsole.cs
index d41481f..a967db6 100644
--- a/OpenSim/Framework/Console/LocalConsole.cs
+++ b/OpenSim/Framework/Console/LocalConsole.cs
@@ -426,6 +426,21 @@ namespace OpenSim.Framework.Console
426 System.Console.Write("{0}", prompt); 426 System.Console.Write("{0}", prompt);
427 427
428 break; 428 break;
429 case ConsoleKey.Delete:
430 if (m_cursorXPosition == m_commandLine.Length)
431 break;
432
433 m_commandLine.Remove(m_cursorXPosition, 1);
434
435 SetCursorLeft(0);
436 m_cursorYPosition = SetCursorTop(m_cursorYPosition);
437
438 if (m_echo)
439 System.Console.Write("{0}{1} ", prompt, m_commandLine);
440 else
441 System.Console.Write("{0}", prompt);
442
443 break;
429 case ConsoleKey.End: 444 case ConsoleKey.End:
430 m_cursorXPosition = m_commandLine.Length; 445 m_cursorXPosition = m_commandLine.Length;
431 break; 446 break;
diff --git a/OpenSim/Framework/Console/RemoteConsole.cs b/OpenSim/Framework/Console/RemoteConsole.cs
index 3e3c2b3..8ad7b0d 100644
--- a/OpenSim/Framework/Console/RemoteConsole.cs
+++ b/OpenSim/Framework/Console/RemoteConsole.cs
@@ -234,7 +234,7 @@ namespace OpenSim.Framework.Console
234 string uri = "/ReadResponses/" + sessionID.ToString() + "/"; 234 string uri = "/ReadResponses/" + sessionID.ToString() + "/";
235 235
236 m_Server.AddPollServiceHTTPHandler( 236 m_Server.AddPollServiceHTTPHandler(
237 uri, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, sessionID,25000)); // 25 secs timeout 237 uri, new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, sessionID,25000)); // 25 secs timeout
238 238
239 XmlDocument xmldoc = new XmlDocument(); 239 XmlDocument xmldoc = new XmlDocument();
240 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration, 240 XmlNode xmlnode = xmldoc.CreateNode(XmlNodeType.XmlDeclaration,
diff --git a/OpenSim/Framework/Constants.cs b/OpenSim/Framework/Constants.cs
index a2eb5ee..3ba264c 100644
--- a/OpenSim/Framework/Constants.cs
+++ b/OpenSim/Framework/Constants.cs
@@ -30,9 +30,18 @@ namespace OpenSim.Framework
30{ 30{
31 public class Constants 31 public class Constants
32 { 32 {
33 // 'RegionSize' is the legacy region size.
34 // DO NOT USE THIS FOR ANY NEW CODE. Use Scene.RegionInfo.RegionSize[XYZ] as a region might not
35 // be the legacy region size.
33 public const uint RegionSize = 256; 36 public const uint RegionSize = 256;
34 public const uint RegionHeight = 4096; 37 public const uint RegionHeight = 4096;
35 public const byte TerrainPatchSize = 16; 38 // This could be a parameters but, really, a region of greater than this is pretty unmanageable
39 public const uint MaximumRegionSize = 8192;
40
41 // Since terrain is stored in 16x16 heights, regions must be a multiple of this number and that is the minimum
42 public const int MinRegionSize = 16;
43 public const int TerrainPatchSize = 16;
44
36 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f"; 45 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f";
37 46
38 public enum EstateAccessCodex : uint 47 public enum EstateAccessCodex : uint
diff --git a/OpenSim/Framework/DAMap.cs b/OpenSim/Framework/DAMap.cs
index df4a6bc..4995a92 100644
--- a/OpenSim/Framework/DAMap.cs
+++ b/OpenSim/Framework/DAMap.cs
@@ -29,10 +29,12 @@ using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.IO; 31using System.IO;
32using System.Reflection;
32using System.Text; 33using System.Text;
33using System.Xml; 34using System.Xml;
34using System.Xml.Schema; 35using System.Xml.Schema;
35using System.Xml.Serialization; 36using System.Xml.Serialization;
37using log4net;
36using OpenMetaverse; 38using OpenMetaverse;
37using OpenMetaverse.StructuredData; 39using OpenMetaverse.StructuredData;
38 40
@@ -48,13 +50,20 @@ namespace OpenSim.Framework
48 /// within their data store. However, avoid storing large amounts of data because that 50 /// within their data store. However, avoid storing large amounts of data because that
49 /// would slow down database access. 51 /// would slow down database access.
50 /// </remarks> 52 /// </remarks>
51 public class DAMap : IDictionary<string, OSDMap>, IXmlSerializable 53 public class DAMap : IXmlSerializable
52 { 54 {
53 private static readonly int MIN_STORE_NAME_LENGTH = 4; 55// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 56
55 protected OSDMap m_map; 57 private static readonly int MIN_NAMESPACE_LENGTH = 4;
56 58
57 public DAMap() { m_map = new OSDMap(); } 59 private OSDMap m_map = new OSDMap();
60
61 // WARNING: this is temporary for experimentation only, it will be removed!!!!
62 public OSDMap TopLevelMap
63 {
64 get { return m_map; }
65 set { m_map = value; }
66 }
58 67
59 public XmlSchema GetSchema() { return null; } 68 public XmlSchema GetSchema() { return null; }
60 69
@@ -64,39 +73,34 @@ namespace OpenSim.Framework
64 map.ReadXml(rawXml); 73 map.ReadXml(rawXml);
65 return map; 74 return map;
66 } 75 }
67 76
77 public void ReadXml(XmlReader reader)
78 {
79 ReadXml(reader.ReadInnerXml());
80 }
81
68 public void ReadXml(string rawXml) 82 public void ReadXml(string rawXml)
69 { 83 {
70 // System.Console.WriteLine("Trying to deserialize [{0}]", rawXml); 84 // System.Console.WriteLine("Trying to deserialize [{0}]", rawXml);
71 85
72 lock (this) 86 lock (this)
87 {
73 m_map = (OSDMap)OSDParser.DeserializeLLSDXml(rawXml); 88 m_map = (OSDMap)OSDParser.DeserializeLLSDXml(rawXml);
89 SanitiseMap(this);
90 }
74 } 91 }
75 92
76 // WARNING: this is temporary for experimentation only, it will be removed!!!! 93 public void WriteXml(XmlWriter writer)
77 public OSDMap TopLevelMap
78 { 94 {
79 get { return m_map; } 95 writer.WriteRaw(ToXml());
80 set { m_map = value; }
81 } 96 }
82
83 97
84 public void ReadXml(XmlReader reader)
85 {
86 ReadXml(reader.ReadInnerXml());
87 }
88
89 public string ToXml() 98 public string ToXml()
90 { 99 {
91 lock (this) 100 lock (this)
92 return OSDParser.SerializeLLSDXmlString(m_map); 101 return OSDParser.SerializeLLSDXmlString(m_map);
93 } 102 }
94 103
95 public void WriteXml(XmlWriter writer)
96 {
97 writer.WriteRaw(ToXml());
98 }
99
100 public void CopyFrom(DAMap other) 104 public void CopyFrom(DAMap other)
101 { 105 {
102 // Deep copy 106 // Deep copy
@@ -104,7 +108,7 @@ namespace OpenSim.Framework
104 string data = null; 108 string data = null;
105 lock (other) 109 lock (other)
106 { 110 {
107 if (other.Count > 0) 111 if (other.CountNamespaces > 0)
108 { 112 {
109 data = OSDParser.SerializeLLSDXmlString(other.m_map); 113 data = OSDParser.SerializeLLSDXmlString(other.m_map);
110 } 114 }
@@ -120,59 +124,132 @@ namespace OpenSim.Framework
120 } 124 }
121 125
122 /// <summary> 126 /// <summary>
123 /// Returns the number of data stores. 127 /// Sanitise the map to remove any namespaces or stores that are not OSDMap.
124 /// </summary> 128 /// </summary>
125 public int Count { get { lock (this) { return m_map.Count; } } } 129 /// <param name='map'>
126 130 /// </param>
127 public bool IsReadOnly { get { return false; } } 131 public static void SanitiseMap(DAMap daMap)
128 132 {
133 List<string> keysToRemove = null;
134
135 OSDMap namespacesMap = daMap.m_map;
136
137 foreach (string key in namespacesMap.Keys)
138 {
139// Console.WriteLine("Processing ns {0}", key);
140 if (!(namespacesMap[key] is OSDMap))
141 {
142 if (keysToRemove == null)
143 keysToRemove = new List<string>();
144
145 keysToRemove.Add(key);
146 }
147 }
148
149 if (keysToRemove != null)
150 {
151 foreach (string key in keysToRemove)
152 {
153// Console.WriteLine ("Removing bad ns {0}", key);
154 namespacesMap.Remove(key);
155 }
156 }
157
158 foreach (OSD nsOsd in namespacesMap.Values)
159 {
160 OSDMap nsOsdMap = (OSDMap)nsOsd;
161 keysToRemove = null;
162
163 foreach (string key in nsOsdMap.Keys)
164 {
165 if (!(nsOsdMap[key] is OSDMap))
166 {
167 if (keysToRemove == null)
168 keysToRemove = new List<string>();
169
170 keysToRemove.Add(key);
171 }
172 }
173
174 if (keysToRemove != null)
175 foreach (string key in keysToRemove)
176 nsOsdMap.Remove(key);
177 }
178 }
179
129 /// <summary> 180 /// <summary>
130 /// Returns the names of the data stores. 181 /// Get the number of namespaces
131 /// </summary> 182 /// </summary>
132 public ICollection<string> Keys { get { lock (this) { return m_map.Keys; } } } 183 public int CountNamespaces { get { lock (this) { return m_map.Count; } } }
133 184
134 /// <summary> 185 /// <summary>
135 /// Returns all the data stores. 186 /// Get the number of stores.
136 /// </summary> 187 /// </summary>
137 public ICollection<OSDMap> Values 188 public int CountStores
138 { 189 {
139 get 190 get
140 { 191 {
192 int count = 0;
193
141 lock (this) 194 lock (this)
142 { 195 {
143 List<OSDMap> stores = new List<OSDMap>(m_map.Count); 196 foreach (OSD osdNamespace in m_map)
144 foreach (OSD llsd in m_map.Values) 197 {
145 stores.Add((OSDMap)llsd); 198 count += ((OSDMap)osdNamespace).Count;
146 return stores; 199 }
147 } 200 }
201
202 return count;
148 } 203 }
149 } 204 }
150 205
151 /// <summary> 206 /// <summary>
152 /// Gets or sets one data store. 207 /// Retrieve a Dynamic Attribute store
153 /// </summary> 208 /// </summary>
154 /// <param name="key">Store name</param> 209 /// <param name="ns">namespace for the store - use "OpenSim" for in-core modules</param>
155 /// <returns></returns> 210 /// <param name="storeName">name of the store within the namespace</param>
156 public OSDMap this[string key] 211 /// <returns>an OSDMap representing the stored data, or null if not found</returns>
157 { 212 public OSDMap GetStore(string ns, string storeName)
158 get 213 {
159 { 214 OSD namespaceOsd;
160 OSD llsd; 215
161 216 lock (this)
162 lock (this) 217 {
218 if (m_map.TryGetValue(ns, out namespaceOsd))
163 { 219 {
164 if (m_map.TryGetValue(key, out llsd)) 220 OSD store;
165 return (OSDMap)llsd; 221
166 else 222 if (((OSDMap)namespaceOsd).TryGetValue(storeName, out store))
167 return null; 223 return (OSDMap)store;
168 } 224 }
169 } 225 }
170 226
171 set 227 return null;
228 }
229
230 /// <summary>
231 /// Saves a Dynamic attribute store
232 /// </summary>
233 /// <param name="ns">namespace for the store - use "OpenSim" for in-core modules</param>
234 /// <param name="storeName">name of the store within the namespace</param>
235 /// <param name="store">an OSDMap representing the data to store</param>
236 public void SetStore(string ns, string storeName, OSDMap store)
237 {
238 ValidateNamespace(ns);
239 OSDMap nsMap;
240
241 lock (this)
172 { 242 {
173 ValidateKey(key); 243 if (!m_map.ContainsKey(ns))
174 lock (this) 244 {
175 m_map[key] = value; 245 nsMap = new OSDMap();
246 m_map[ns] = nsMap;
247 }
248
249 nsMap = (OSDMap)m_map[ns];
250
251// m_log.DebugFormat("[DA MAP]: Setting store to {0}:{1}", ns, storeName);
252 nsMap[storeName] = store;
176 } 253 }
177 } 254 }
178 255
@@ -180,54 +257,46 @@ namespace OpenSim.Framework
180 /// Validate the key used for storing separate data stores. 257 /// Validate the key used for storing separate data stores.
181 /// </summary> 258 /// </summary>
182 /// <param name='key'></param> 259 /// <param name='key'></param>
183 public static void ValidateKey(string key) 260 public static void ValidateNamespace(string ns)
184 { 261 {
185 if (key.Length < MIN_STORE_NAME_LENGTH) 262 if (ns.Length < MIN_NAMESPACE_LENGTH)
186 throw new Exception("Minimum store name length is " + MIN_STORE_NAME_LENGTH); 263 throw new Exception("Minimum namespace length is " + MIN_NAMESPACE_LENGTH);
187 } 264 }
188 265
189 public bool ContainsKey(string key) 266 public bool ContainsStore(string ns, string storeName)
190 { 267 {
191 lock (this) 268 OSD namespaceOsd;
192 return m_map.ContainsKey(key);
193 }
194 269
195 public void Add(string key, OSDMap store)
196 {
197 ValidateKey(key);
198 lock (this)
199 m_map.Add(key, store);
200 }
201
202 public void Add(KeyValuePair<string, OSDMap> kvp)
203 {
204 ValidateKey(kvp.Key);
205 lock (this) 270 lock (this)
206 m_map.Add(kvp.Key, kvp.Value); 271 {
207 } 272 if (m_map.TryGetValue(ns, out namespaceOsd))
273 {
274 return ((OSDMap)namespaceOsd).ContainsKey(storeName);
275 }
276 }
208 277
209 public bool Remove(string key) 278 return false;
210 { 279 }
211 lock (this)
212 return m_map.Remove(key);
213 }
214 280
215 public bool TryGetValue(string key, out OSDMap store) 281 public bool TryGetStore(string ns, string storeName, out OSDMap store)
216 { 282 {
283 OSD namespaceOsd;
284
217 lock (this) 285 lock (this)
218 { 286 {
219 OSD llsd; 287 if (m_map.TryGetValue(ns, out namespaceOsd))
220 if (m_map.TryGetValue(key, out llsd))
221 {
222 store = (OSDMap)llsd;
223 return true;
224 }
225 else
226 { 288 {
227 store = null; 289 OSD storeOsd;
228 return false; 290
291 bool result = ((OSDMap)namespaceOsd).TryGetValue(storeName, out storeOsd);
292 store = (OSDMap)storeOsd;
293
294 return result;
229 } 295 }
230 } 296 }
297
298 store = null;
299 return false;
231 } 300 }
232 301
233 public void Clear() 302 public void Clear()
@@ -235,39 +304,25 @@ namespace OpenSim.Framework
235 lock (this) 304 lock (this)
236 m_map.Clear(); 305 m_map.Clear();
237 } 306 }
238
239 public bool Contains(KeyValuePair<string, OSDMap> kvp)
240 {
241 lock (this)
242 return m_map.ContainsKey(kvp.Key);
243 }
244
245 public void CopyTo(KeyValuePair<string, OSDMap>[] array, int index)
246 {
247 throw new NotImplementedException();
248 }
249 307
250 public bool Remove(KeyValuePair<string, OSDMap> kvp) 308 public bool RemoveStore(string ns, string storeName)
251 { 309 {
252 lock (this) 310 OSD namespaceOsd;
253 return m_map.Remove(kvp.Key);
254 }
255 311
256 public System.Collections.IDictionaryEnumerator GetEnumerator()
257 {
258 lock (this) 312 lock (this)
259 return m_map.GetEnumerator(); 313 {
260 } 314 if (m_map.TryGetValue(ns, out namespaceOsd))
315 {
316 OSDMap namespaceOsdMap = (OSDMap)namespaceOsd;
317 namespaceOsdMap.Remove(storeName);
261 318
262 IEnumerator<KeyValuePair<string, OSDMap>> IEnumerable<KeyValuePair<string, OSDMap>>.GetEnumerator() 319 // Don't keep empty namespaces around
263 { 320 if (namespaceOsdMap.Count <= 0)
264 return null; 321 m_map.Remove(ns);
265 } 322 }
323 }
266 324
267 IEnumerator IEnumerable.GetEnumerator() 325 return false;
268 { 326 }
269 lock (this)
270 return m_map.GetEnumerator();
271 }
272 } 327 }
273} \ No newline at end of file 328} \ No newline at end of file
diff --git a/OpenSim/Framework/DOMap.cs b/OpenSim/Framework/DOMap.cs
index 755e129..f5b650b 100644
--- a/OpenSim/Framework/DOMap.cs
+++ b/OpenSim/Framework/DOMap.cs
@@ -42,22 +42,22 @@ namespace OpenSim.Framework
42 /// This class stores and retrieves dynamic objects. 42 /// This class stores and retrieves dynamic objects.
43 /// </summary> 43 /// </summary>
44 /// <remarks> 44 /// <remarks>
45 /// Experimental - DO NOT USE. 45 /// Experimental - DO NOT USE. Does not yet have namespace support.
46 /// </remarks> 46 /// </remarks>
47 public class DOMap 47 public class DOMap
48 { 48 {
49 private IDictionary<string, object> m_map; 49 private IDictionary<string, object> m_map;
50 50
51 public void Add(string key, object dynObj) 51 public void Add(string ns, string objName, object dynObj)
52 { 52 {
53 DAMap.ValidateKey(key); 53 DAMap.ValidateNamespace(ns);
54 54
55 lock (this) 55 lock (this)
56 { 56 {
57 if (m_map == null) 57 if (m_map == null)
58 m_map = new Dictionary<string, object>(); 58 m_map = new Dictionary<string, object>();
59 59
60 m_map.Add(key, dynObj); 60 m_map.Add(objName, dynObj);
61 } 61 }
62 } 62 }
63 63
diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs
index e03750b..5ddbd61 100644
--- a/OpenSim/Framework/EstateSettings.cs
+++ b/OpenSim/Framework/EstateSettings.cs
@@ -430,6 +430,5 @@ namespace OpenSim.Framework
430 { 430 {
431 return l_EstateGroups.Contains(groupID); 431 return l_EstateGroups.Contains(groupID);
432 } 432 }
433
434 } 433 }
435} 434}
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index ad3471a..22cc79d 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -65,6 +65,7 @@ namespace OpenSim.Framework
65 public delegate void NetworkStats(int inPackets, int outPackets, int unAckedBytes); 65 public delegate void NetworkStats(int inPackets, int outPackets, int unAckedBytes);
66 66
67 public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 AvSize, WearableCacheItem[] CacheItems); 67 public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 AvSize, WearableCacheItem[] CacheItems);
68 public delegate void CachedTextureRequest(IClientAPI remoteClient, int serial, List<CachedTextureRequestArg> cachedTextureRequest);
68 69
69 public delegate void StartAnim(IClientAPI remoteClient, UUID animID); 70 public delegate void StartAnim(IClientAPI remoteClient, UUID animID);
70 71
@@ -789,6 +790,7 @@ namespace OpenSim.Framework
789 event EstateChangeInfo OnEstateChangeInfo; 790 event EstateChangeInfo OnEstateChangeInfo;
790 event EstateManageTelehub OnEstateManageTelehub; 791 event EstateManageTelehub OnEstateManageTelehub;
791 // [Obsolete("LLClientView Specific.")] 792 // [Obsolete("LLClientView Specific.")]
793 event CachedTextureRequest OnCachedTextureRequest;
792 event SetAppearance OnSetAppearance; 794 event SetAppearance OnSetAppearance;
793 // [Obsolete("LLClientView Specific - Replace and rename OnAvatarUpdate. Difference from SetAppearance?")] 795 // [Obsolete("LLClientView Specific - Replace and rename OnAvatarUpdate. Difference from SetAppearance?")]
794 event AvatarNowWearing OnAvatarNowWearing; 796 event AvatarNowWearing OnAvatarNowWearing;
@@ -832,6 +834,8 @@ namespace OpenSim.Framework
832 /// </remarks> 834 /// </remarks>
833 event UpdateAgent OnAgentUpdate; 835 event UpdateAgent OnAgentUpdate;
834 836
837 event UpdateAgent OnAgentCameraUpdate;
838
835 event AgentRequestSit OnAgentRequestSit; 839 event AgentRequestSit OnAgentRequestSit;
836 event AgentSit OnAgentSit; 840 event AgentSit OnAgentSit;
837 event AvatarPickerRequest OnAvatarPickerRequest; 841 event AvatarPickerRequest OnAvatarPickerRequest;
@@ -1100,14 +1104,15 @@ namespace OpenSim.Framework
1100 /// <param name="textureEntry"></param> 1104 /// <param name="textureEntry"></param>
1101 void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry); 1105 void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry);
1102 1106
1107 void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures);
1108
1103 void SendStartPingCheck(byte seq); 1109 void SendStartPingCheck(byte seq);
1104 1110
1105 /// <summary> 1111 /// <summary>
1106 /// Tell the client that an object has been deleted 1112 /// Tell the client that an object has been deleted
1107 /// </summary> 1113 /// </summary>
1108 /// <param name="regionHandle"></param>
1109 /// <param name="localID"></param> 1114 /// <param name="localID"></param>
1110 void SendKillObject(ulong regionHandle, List<uint> localID); 1115 void SendKillObject(List<uint> localID);
1111 1116
1112 void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); 1117 void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs);
1113 void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); 1118 void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args);
@@ -1486,7 +1491,7 @@ namespace OpenSim.Framework
1486 void SendChangeUserRights(UUID agentID, UUID friendID, int rights); 1491 void SendChangeUserRights(UUID agentID, UUID friendID, int rights);
1487 void SendTextBoxRequest(string message, int chatChannel, string objectname, UUID ownerID, string ownerFirstName, string ownerLastName, UUID objectId); 1492 void SendTextBoxRequest(string message, int chatChannel, string objectname, UUID ownerID, string ownerFirstName, string ownerLastName, UUID objectId);
1488 1493
1489 void StopFlying(ISceneEntity presence); 1494 void SendAgentTerseUpdate(ISceneEntity presence);
1490 1495
1491 void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data); 1496 void SendPlacesReply(UUID queryID, UUID transactionID, PlacesReplyData[] data);
1492 } 1497 }
diff --git a/OpenSim/Framework/IImprovedAssetCache.cs b/OpenSim/Framework/IImprovedAssetCache.cs
index a0b8b55..a853e90 100644
--- a/OpenSim/Framework/IImprovedAssetCache.cs
+++ b/OpenSim/Framework/IImprovedAssetCache.cs
@@ -31,10 +31,34 @@ namespace OpenSim.Framework
31{ 31{
32 public interface IImprovedAssetCache 32 public interface IImprovedAssetCache
33 { 33 {
34 /// <summary>
35 /// Cache the specified asset.
36 /// </summary>
37 /// <param name='asset'></param>
34 void Cache(AssetBase asset); 38 void Cache(AssetBase asset);
39
40 /// <summary>
41 /// Get an asset by its id.
42 /// </summary>
43 /// <param name='id'></param>
44 /// <returns>null if the asset does not exist.</returns>
35 AssetBase Get(string id); 45 AssetBase Get(string id);
46
47 /// <summary>
48 /// Check whether an asset with the specified id exists in the cache.
49 /// </summary>
50 /// <param name='id'></param>
36 bool Check(string id); 51 bool Check(string id);
52
53 /// <summary>
54 /// Expire an asset from the cache.
55 /// </summary>
56 /// <param name='id'></param>
37 void Expire(string id); 57 void Expire(string id);
58
59 /// <summary>
60 /// Clear the cache.
61 /// </summary>
38 void Clear(); 62 void Clear();
39 } 63 }
40} 64} \ No newline at end of file
diff --git a/OpenSim/Framework/IPeople.cs b/OpenSim/Framework/IPeople.cs
new file mode 100644
index 0000000..b88e103
--- /dev/null
+++ b/OpenSim/Framework/IPeople.cs
@@ -0,0 +1,47 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31
32namespace OpenSim.Framework
33{
34 public class UserData
35 {
36 public UUID Id { get; set; }
37 public string FirstName { get; set; }
38 public string LastName { get; set; }
39 public string HomeURL { get; set; }
40 public Dictionary<string, object> ServerURLs { get; set; }
41 }
42
43 public interface IPeople
44 {
45 List<UserData> GetUserData(string query, int page_size, int page_number);
46 }
47} \ No newline at end of file
diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs
index 87ec99e..e1b6d1e 100644
--- a/OpenSim/Framework/IScene.cs
+++ b/OpenSim/Framework/IScene.cs
@@ -86,24 +86,26 @@ namespace OpenSim.Framework
86 event restart OnRestart; 86 event restart OnRestart;
87 87
88 /// <summary> 88 /// <summary>
89 /// Add a new client and create a presence for it. All clients except initial login clients will starts off as a child agent 89 /// Add a new agent with an attached client. All agents except initial login clients will starts off as a child agent
90 /// - the later agent crossing will promote it to a root agent. 90 /// - the later agent crossing will promote it to a root agent.
91 /// </summary> 91 /// </summary>
92 /// <param name="client"></param> 92 /// <param name="client"></param>
93 /// <param name="type">The type of agent to add.</param> 93 /// <param name="type">The type of agent to add.</param>
94 /// <returns> 94 /// <returns>
95 /// The scene agent if the new client was added or if an agent that already existed.</returns> 95 /// The scene agent if the new client was added or if an agent that already existed.</returns>
96 ISceneAgent AddNewClient(IClientAPI client, PresenceType type); 96 ISceneAgent AddNewAgent(IClientAPI client, PresenceType type);
97 97
98 /// <summary> 98 /// <summary>
99 /// Remove the given client from the scene. 99 /// Tell a single agent to disconnect from the region.
100 /// </summary> 100 /// </summary>
101 /// <param name="agentID"></param> 101 /// <param name="agentID"></param>
102 /// <param name="closeChildAgents">Close the neighbour child agents associated with this client.</param> 102 /// <param name="force">
103 void RemoveClient(UUID agentID, bool closeChildAgents); 103 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
104 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
105 /// </param>
106 bool CloseAgent(UUID agentID, bool force);
104 107
105 void Restart(); 108 void Restart();
106 //RegionInfo OtherRegionUp(RegionInfo thisRegion);
107 109
108 string GetSimulatorVersion(); 110 string GetSimulatorVersion();
109 111
@@ -136,5 +138,10 @@ namespace OpenSim.Framework
136 ISceneObject DeserializeObject(string representation); 138 ISceneObject DeserializeObject(string representation);
137 139
138 bool CheckClient(UUID agentID, System.Net.IPEndPoint ep); 140 bool CheckClient(UUID agentID, System.Net.IPEndPoint ep);
141
142 /// <summary>
143 /// Start the scene and associated scripts within it.
144 /// </summary>
145 void Start();
139 } 146 }
140} 147} \ No newline at end of file
diff --git a/OpenSim/Framework/InventoryItemBase.cs b/OpenSim/Framework/InventoryItemBase.cs
index 3d45e76..558dfd0 100644
--- a/OpenSim/Framework/InventoryItemBase.cs
+++ b/OpenSim/Framework/InventoryItemBase.cs
@@ -122,7 +122,7 @@ namespace OpenSim.Framework
122 { 122 {
123 get 123 get
124 { 124 {
125 if (m_creatorData != null && m_creatorData != string.Empty) 125 if (!string.IsNullOrEmpty(m_creatorData))
126 return m_creatorId + ';' + m_creatorData; 126 return m_creatorId + ';' + m_creatorData;
127 else 127 else
128 return m_creatorId; 128 return m_creatorId;
diff --git a/OpenSim/Framework/Location.cs b/OpenSim/Framework/Location.cs
index 9504e03..0b88834 100644
--- a/OpenSim/Framework/Location.cs
+++ b/OpenSim/Framework/Location.cs
@@ -33,10 +33,10 @@ namespace OpenSim.Framework
33 [Serializable] 33 [Serializable]
34 public class Location : ICloneable 34 public class Location : ICloneable
35 { 35 {
36 private readonly int m_x; 36 private readonly uint m_x;
37 private readonly int m_y; 37 private readonly uint m_y;
38 38
39 public Location(int x, int y) 39 public Location(uint x, uint y)
40 { 40 {
41 m_x = x; 41 m_x = x;
42 m_y = y; 42 m_y = y;
@@ -44,21 +44,21 @@ namespace OpenSim.Framework
44 44
45 public Location(ulong regionHandle) 45 public Location(ulong regionHandle)
46 { 46 {
47 m_x = (int) regionHandle; 47 m_x = (uint)(regionHandle >> 32);
48 m_y = (int) (regionHandle >> 32); 48 m_y = (uint)(regionHandle & (ulong)uint.MaxValue);
49 } 49 }
50 50
51 public ulong RegionHandle 51 public ulong RegionHandle
52 { 52 {
53 get { return Utils.UIntsToLong((uint)m_x, (uint)m_y); } 53 get { return Utils.UIntsToLong(m_x, m_y); }
54 } 54 }
55 55
56 public int X 56 public uint X
57 { 57 {
58 get { return m_x; } 58 get { return m_x; }
59 } 59 }
60 60
61 public int Y 61 public uint Y
62 { 62 {
63 get { return m_y; } 63 get { return m_y; }
64 } 64 }
diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
index 23dba09..96536e8 100644
--- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.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 *
@@ -44,16 +44,16 @@ namespace OpenSim.Framework.Monitoring
44 sb.Append("MEMORY STATISTICS"); 44 sb.Append("MEMORY STATISTICS");
45 sb.Append(Environment.NewLine); 45 sb.Append(Environment.NewLine);
46 sb.AppendFormat( 46 sb.AppendFormat(
47 "Allocated to OpenSim objects: {0} MB\n", 47 "Heap allocated to OpenSim : {0} MB\n",
48 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); 48 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
49 49
50 sb.AppendFormat( 50 sb.AppendFormat(
51 "OpenSim last object memory churn : {0} MB/s\n", 51 "Last heap allocation rate : {0} MB/s\n",
52 Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3)); 52 Math.Round((MemoryWatchdog.LastHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
53 53
54 sb.AppendFormat( 54 sb.AppendFormat(
55 "OpenSim average object memory churn : {0} MB/s\n", 55 "Average heap allocation rate: {0} MB/s\n",
56 Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); 56 Math.Round((MemoryWatchdog.AverageHeapAllocationRate * 1000) / 1024.0 / 1024, 3));
57 57
58 Process myprocess = Process.GetCurrentProcess(); 58 Process myprocess = Process.GetCurrentProcess();
59 if (!myprocess.HasExited) 59 if (!myprocess.HasExited)
diff --git a/OpenSim/Framework/Monitoring/Checks/Check.cs b/OpenSim/Framework/Monitoring/Checks/Check.cs
new file mode 100644
index 0000000..594386a
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/Checks/Check.cs
@@ -0,0 +1,118 @@
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.Text;
30
31namespace OpenSim.Framework.Monitoring
32{
33 public class Check
34 {
35// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
36
37 public static readonly char[] DisallowedShortNameCharacters = { '.' };
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 /// <summary>
55 /// Action used to check whether alert should go off.
56 /// </summary>
57 /// <remarks>
58 /// Should return true if check passes. False otherwise.
59 /// </remarks>
60 public Func<Check, bool> CheckFunc { get; private set; }
61
62 /// <summary>
63 /// Message from the last failure, if any. If there is no message or no failure then will be null.
64 /// </summary>
65 /// <remarks>
66 /// Should be set by the CheckFunc when applicable.
67 /// </remarks>
68 public string LastFailureMessage { get; set; }
69
70 public StatVerbosity Verbosity { get; private set; }
71 public string ShortName { get; private set; }
72 public string Name { get; private set; }
73 public string Description { get; private set; }
74
75 public Check(
76 string shortName,
77 string name,
78 string description,
79 string category,
80 string container,
81 Func<Check, bool> checkFunc,
82 StatVerbosity verbosity)
83 {
84 if (ChecksManager.SubCommands.Contains(category))
85 throw new Exception(
86 string.Format("Alert cannot be in category '{0}' since this is reserved for a subcommand", category));
87
88 foreach (char c in DisallowedShortNameCharacters)
89 {
90 if (shortName.IndexOf(c) != -1)
91 throw new Exception(string.Format("Alert name {0} cannot contain character {1}", shortName, c));
92 }
93
94 ShortName = shortName;
95 Name = name;
96 Description = description;
97 Category = category;
98 Container = container;
99 CheckFunc = checkFunc;
100 Verbosity = verbosity;
101 }
102
103 public bool CheckIt()
104 {
105 return CheckFunc(this);
106 }
107
108 public virtual string ToConsoleString()
109 {
110 return string.Format(
111 "{0}.{1}.{2} - {3}",
112 Category,
113 Container,
114 ShortName,
115 Description);
116 }
117 }
118} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/ChecksManager.cs b/OpenSim/Framework/Monitoring/ChecksManager.cs
new file mode 100644
index 0000000..e4a7f8c
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/ChecksManager.cs
@@ -0,0 +1,262 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using System.Text;
33using log4net;
34
35namespace OpenSim.Framework.Monitoring
36{
37 /// <summary>
38 /// Static class used to register/deregister checks on runtime conditions.
39 /// </summary>
40 public static class ChecksManager
41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 // Subcommand used to list other stats.
45 public const string ListSubCommand = "list";
46
47 // All subcommands
48 public static HashSet<string> SubCommands = new HashSet<string> { ListSubCommand };
49
50 /// <summary>
51 /// Checks categorized by category/container/shortname
52 /// </summary>
53 /// <remarks>
54 /// Do not add or remove directly from this dictionary.
55 /// </remarks>
56 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Check>>> RegisteredChecks
57 = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Check>>>();
58
59 public static void RegisterConsoleCommands(ICommandConsole console)
60 {
61 console.Commands.AddCommand(
62 "General",
63 false,
64 "show checks",
65 "show checks",
66 "Show checks configured for this server",
67 "If no argument is specified then info on all checks will be shown.\n"
68 + "'list' argument will show check categories.\n"
69 + "THIS FACILITY IS EXPERIMENTAL",
70 HandleShowchecksCommand);
71 }
72
73 public static void HandleShowchecksCommand(string module, string[] cmd)
74 {
75 ICommandConsole con = MainConsole.Instance;
76
77 if (cmd.Length > 2)
78 {
79 foreach (string name in cmd.Skip(2))
80 {
81 string[] components = name.Split('.');
82
83 string categoryName = components[0];
84// string containerName = components.Length > 1 ? components[1] : null;
85
86 if (categoryName == ListSubCommand)
87 {
88 con.Output("check categories available are:");
89
90 foreach (string category in RegisteredChecks.Keys)
91 con.OutputFormat(" {0}", category);
92 }
93// else
94// {
95// SortedDictionary<string, SortedDictionary<string, Check>> category;
96// if (!Registeredchecks.TryGetValue(categoryName, out category))
97// {
98// con.OutputFormat("No such category as {0}", categoryName);
99// }
100// else
101// {
102// if (String.IsNullOrEmpty(containerName))
103// {
104// OutputConfiguredToConsole(con, category);
105// }
106// else
107// {
108// SortedDictionary<string, Check> container;
109// if (category.TryGetValue(containerName, out container))
110// {
111// OutputContainerChecksToConsole(con, container);
112// }
113// else
114// {
115// con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
116// }
117// }
118// }
119// }
120 }
121 }
122 else
123 {
124 OutputAllChecksToConsole(con);
125 }
126 }
127
128 /// <summary>
129 /// Registers a statistic.
130 /// </summary>
131 /// <param name='stat'></param>
132 /// <returns></returns>
133 public static bool RegisterCheck(Check check)
134 {
135 SortedDictionary<string, SortedDictionary<string, Check>> category = null, newCategory;
136 SortedDictionary<string, Check> container = null, newContainer;
137
138 lock (RegisteredChecks)
139 {
140 // Check name is not unique across category/container/shortname key.
141 // XXX: For now just return false. This is to avoid problems in regression tests where all tests
142 // in a class are run in the same instance of the VM.
143 if (TryGetCheckParents(check, out category, out container))
144 return false;
145
146 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
147 // This means that we don't need to lock or copy them on iteration, which will be a much more
148 // common operation after startup.
149 if (container != null)
150 newContainer = new SortedDictionary<string, Check>(container);
151 else
152 newContainer = new SortedDictionary<string, Check>();
153
154 if (category != null)
155 newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>(category);
156 else
157 newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>();
158
159 newContainer[check.ShortName] = check;
160 newCategory[check.Container] = newContainer;
161 RegisteredChecks[check.Category] = newCategory;
162 }
163
164 return true;
165 }
166
167 /// <summary>
168 /// Deregister an check
169 /// </summary>>
170 /// <param name='stat'></param>
171 /// <returns></returns>
172 public static bool DeregisterCheck(Check check)
173 {
174 SortedDictionary<string, SortedDictionary<string, Check>> category = null, newCategory;
175 SortedDictionary<string, Check> container = null, newContainer;
176
177 lock (RegisteredChecks)
178 {
179 if (!TryGetCheckParents(check, out category, out container))
180 return false;
181
182 newContainer = new SortedDictionary<string, Check>(container);
183 newContainer.Remove(check.ShortName);
184
185 newCategory = new SortedDictionary<string, SortedDictionary<string, Check>>(category);
186 newCategory.Remove(check.Container);
187
188 newCategory[check.Container] = newContainer;
189 RegisteredChecks[check.Category] = newCategory;
190
191 return true;
192 }
193 }
194
195 public static bool TryGetCheckParents(
196 Check check,
197 out SortedDictionary<string, SortedDictionary<string, Check>> category,
198 out SortedDictionary<string, Check> container)
199 {
200 category = null;
201 container = null;
202
203 lock (RegisteredChecks)
204 {
205 if (RegisteredChecks.TryGetValue(check.Category, out category))
206 {
207 if (category.TryGetValue(check.Container, out container))
208 {
209 if (container.ContainsKey(check.ShortName))
210 return true;
211 }
212 }
213 }
214
215 return false;
216 }
217
218 public static void CheckChecks()
219 {
220 lock (RegisteredChecks)
221 {
222 foreach (SortedDictionary<string, SortedDictionary<string, Check>> category in RegisteredChecks.Values)
223 {
224 foreach (SortedDictionary<string, Check> container in category.Values)
225 {
226 foreach (Check check in container.Values)
227 {
228 if (!check.CheckIt())
229 m_log.WarnFormat(
230 "[CHECKS MANAGER]: Check {0}.{1}.{2} failed with message {3}", check.Category, check.Container, check.ShortName, check.LastFailureMessage);
231 }
232 }
233 }
234 }
235 }
236
237 private static void OutputAllChecksToConsole(ICommandConsole con)
238 {
239 foreach (var category in RegisteredChecks.Values)
240 {
241 OutputCategoryChecksToConsole(con, category);
242 }
243 }
244
245 private static void OutputCategoryChecksToConsole(
246 ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Check>> category)
247 {
248 foreach (var container in category.Values)
249 {
250 OutputContainerChecksToConsole(con, container);
251 }
252 }
253
254 private static void OutputContainerChecksToConsole(ICommandConsole con, SortedDictionary<string, Check> container)
255 {
256 foreach (Check check in container.Values)
257 {
258 con.Output(check.ToConsoleString());
259 }
260 }
261 }
262} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
index c6010cd..c474622 100644
--- a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
+++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
@@ -60,17 +60,17 @@ namespace OpenSim.Framework.Monitoring
60 private static bool m_enabled; 60 private static bool m_enabled;
61 61
62 /// <summary> 62 /// <summary>
63 /// Last memory churn in bytes per millisecond. 63 /// Average heap allocation rate in bytes per millisecond.
64 /// </summary> 64 /// </summary>
65 public static double AverageMemoryChurn 65 public static double AverageHeapAllocationRate
66 { 66 {
67 get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } 67 get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; }
68 } 68 }
69 69
70 /// <summary> 70 /// <summary>
71 /// Average memory churn in bytes per millisecond. 71 /// Last heap allocation in bytes
72 /// </summary> 72 /// </summary>
73 public static double LastMemoryChurn 73 public static double LastHeapAllocationRate
74 { 74 {
75 get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; } 75 get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; }
76 } 76 }
diff --git a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
index 36678bb..07971bf 100644
--- a/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Monitoring/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
new file mode 100644
index 0000000..ac0f0bc
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs
@@ -0,0 +1,349 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Diagnostics;
31using System.Linq;
32using System.Net.NetworkInformation;
33using System.Text;
34using System.Threading;
35using log4net;
36using Nini.Config;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework;
39
40namespace OpenSim.Framework.Monitoring
41{
42 public class ServerStatsCollector
43 {
44 private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
45 private readonly string LogHeader = "[SERVER STATS]";
46
47 public bool Enabled = false;
48 private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>();
49
50 public readonly string CategoryServer = "server";
51
52 public readonly string ContainerThreadpool = "threadpool";
53 public readonly string ContainerProcessor = "processor";
54 public readonly string ContainerMemory = "memory";
55 public readonly string ContainerNetwork = "network";
56 public readonly string ContainerProcess = "process";
57
58 public string NetworkInterfaceTypes = "Ethernet";
59
60 readonly int performanceCounterSampleInterval = 500;
61// int lastperformanceCounterSampleTime = 0;
62
63 private class PerfCounterControl
64 {
65 public PerformanceCounter perfCounter;
66 public int lastFetch;
67 public string name;
68 public PerfCounterControl(PerformanceCounter pPc)
69 : this(pPc, String.Empty)
70 {
71 }
72 public PerfCounterControl(PerformanceCounter pPc, string pName)
73 {
74 perfCounter = pPc;
75 lastFetch = 0;
76 name = pName;
77 }
78 }
79
80 PerfCounterControl processorPercentPerfCounter = null;
81
82 // IRegionModuleBase.Initialize
83 public void Initialise(IConfigSource source)
84 {
85 IConfig cfg = source.Configs["Monitoring"];
86
87 if (cfg != null)
88 Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
89
90 if (Enabled)
91 {
92 NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
93 }
94 }
95
96 public void Start()
97 {
98 if (RegisteredStats.Count == 0)
99 RegisterServerStats();
100 }
101
102 public void Close()
103 {
104 if (RegisteredStats.Count > 0)
105 {
106 foreach (Stat stat in RegisteredStats.Values)
107 {
108 StatsManager.DeregisterStat(stat);
109 stat.Dispose();
110 }
111 RegisteredStats.Clear();
112 }
113 }
114
115 private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act)
116 {
117 MakeStat(pName, pDesc, pUnit, pContainer, act, MeasuresOfInterest.None);
118 }
119
120 private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act, MeasuresOfInterest moi)
121 {
122 string desc = pDesc;
123 if (desc == null)
124 desc = pName;
125 Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, moi, act, StatVerbosity.Debug);
126 StatsManager.RegisterStat(stat);
127 RegisteredStats.Add(pName, stat);
128 }
129
130 public void RegisterServerStats()
131 {
132// lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
133 PerformanceCounter tempPC;
134 Stat tempStat;
135 string tempName;
136
137 try
138 {
139 tempName = "CPUPercent";
140 tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
141 processorPercentPerfCounter = new PerfCounterControl(tempPC);
142 // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
143 tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
144 StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); },
145 StatVerbosity.Info);
146 StatsManager.RegisterStat(tempStat);
147 RegisteredStats.Add(tempName, tempStat);
148
149 MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,
150 (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
151
152 MakeStat("UserProcessorTime", null, "sec", ContainerProcessor,
153 (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
154
155 MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor,
156 (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
157
158 MakeStat("Threads", null, "threads", ContainerProcessor,
159 (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
160 }
161 catch (Exception e)
162 {
163 m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e);
164 }
165
166 MakeStat("BuiltinThreadpoolWorkerThreadsAvailable", null, "threads", ContainerThreadpool,
167 s =>
168 {
169 int workerThreads, iocpThreads;
170 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
171 s.Value = workerThreads;
172 });
173
174 MakeStat("BuiltinThreadpoolIOCPThreadsAvailable", null, "threads", ContainerThreadpool,
175 s =>
176 {
177 int workerThreads, iocpThreads;
178 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
179 s.Value = iocpThreads;
180 });
181
182 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool && Util.GetSmartThreadPoolInfo() != null)
183 {
184 MakeStat("STPMaxThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxThreads);
185 MakeStat("STPMinThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MinThreads);
186 MakeStat("STPConcurrency", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().MaxConcurrentWorkItems);
187 MakeStat("STPActiveThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().ActiveThreads);
188 MakeStat("STPInUseThreads", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().InUseThreads);
189 MakeStat("STPWorkItemsWaiting", null, "threads", ContainerThreadpool, s => s.Value = Util.GetSmartThreadPoolInfo().WaitingCallbacks);
190 }
191
192 MakeStat(
193 "HTTPRequestsMade",
194 "Number of outbound HTTP requests made",
195 "requests",
196 ContainerNetwork,
197 s => s.Value = WebUtil.RequestNumber,
198 MeasuresOfInterest.AverageChangeOverTime);
199
200 try
201 {
202 List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
203
204 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
205 foreach (NetworkInterface nic in nics)
206 {
207 if (nic.OperationalStatus != OperationalStatus.Up)
208 continue;
209
210 string nicInterfaceType = nic.NetworkInterfaceType.ToString();
211 if (!okInterfaceTypes.Contains(nicInterfaceType))
212 {
213 m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.",
214 LogHeader, nic.Name, nicInterfaceType);
215 m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}",
216 LogHeader, NetworkInterfaceTypes);
217 continue;
218 }
219
220 if (nic.Supports(NetworkInterfaceComponent.IPv4))
221 {
222 IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
223 if (nicStats != null)
224 {
225 MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork,
226 (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
227 MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork,
228 (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
229 MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork,
230 (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
231 }
232 }
233 // TODO: add IPv6 (it may actually happen someday)
234 }
235 }
236 catch (Exception e)
237 {
238 m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
239 }
240
241 MakeStat("ProcessMemory", null, "MB", ContainerMemory,
242 (s) => { s.Value = Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d, 3); });
243 MakeStat("HeapMemory", null, "MB", ContainerMemory,
244 (s) => { s.Value = Math.Round(GC.GetTotalMemory(false) / 1024d / 1024d, 3); });
245 MakeStat("LastHeapAllocationRate", null, "MB/sec", ContainerMemory,
246 (s) => { s.Value = Math.Round(MemoryWatchdog.LastHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
247 MakeStat("AverageHeapAllocationRate", null, "MB/sec", ContainerMemory,
248 (s) => { s.Value = Math.Round(MemoryWatchdog.AverageHeapAllocationRate * 1000d / 1024d / 1024d, 3); });
249 }
250
251 // Notes on performance counters:
252 // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx
253 // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
254 // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
255 private delegate double PerfCounterNextValue();
256 private void GetNextValue(Stat stat, PerfCounterControl perfControl)
257 {
258 GetNextValue(stat, perfControl, 1.0);
259 }
260 private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
261 {
262 if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
263 {
264 if (perfControl != null && perfControl.perfCounter != null)
265 {
266 try
267 {
268 // Kludge for factor to run double duty. If -1, subtract the value from one
269 if (factor == -1)
270 stat.Value = 1 - perfControl.perfCounter.NextValue();
271 else
272 stat.Value = perfControl.perfCounter.NextValue() / factor;
273 }
274 catch (Exception e)
275 {
276 m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
277 }
278 perfControl.lastFetch = Util.EnvironmentTickCount();
279 }
280 }
281 }
282
283 // Lookup the nic that goes with this stat and set the value by using a fetch action.
284 // Not sure about closure with delegates inside delegates.
285 private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
286 private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor)
287 {
288 // Get the one nic that has the name of this stat
289 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
290 (network) => network.Name == stat.Description);
291 try
292 {
293 foreach (NetworkInterface nic in nics)
294 {
295 IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
296 if (intrStats != null)
297 {
298 double newVal = Math.Round(getter(intrStats) / factor, 3);
299 stat.Value = newVal;
300 }
301 break;
302 }
303 }
304 catch
305 {
306 // There are times interfaces go away so we just won't update the stat for this
307 m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
308 }
309 }
310 }
311
312 public class ServerStatsAggregator : Stat
313 {
314 public ServerStatsAggregator(
315 string shortName,
316 string name,
317 string description,
318 string unitName,
319 string category,
320 string container
321 )
322 : base(
323 shortName,
324 name,
325 description,
326 unitName,
327 category,
328 container,
329 StatType.Push,
330 MeasuresOfInterest.None,
331 null,
332 StatVerbosity.Info)
333 {
334 }
335 public override string ToConsoleString()
336 {
337 StringBuilder sb = new StringBuilder();
338
339 return sb.ToString();
340 }
341
342 public override OSDMap ToOSDMap()
343 {
344 OSDMap ret = new OSDMap();
345
346 return ret;
347 }
348 }
349}
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
index 6a68322..f6f458d 100644
--- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
30using System.Text; 31using System.Text;
31using OpenMetaverse; 32using OpenMetaverse;
32using OpenMetaverse.StructuredData; 33using OpenMetaverse.StructuredData;
@@ -39,8 +40,6 @@ namespace OpenSim.Framework.Monitoring
39 /// </summary> 40 /// </summary>
40 public class SimExtraStatsCollector : BaseStatsCollector 41 public class SimExtraStatsCollector : BaseStatsCollector
41 { 42 {
42 private long abnormalClientThreadTerminations;
43
44// private long assetsInCache; 43// private long assetsInCache;
45// private long texturesInCache; 44// private long texturesInCache;
46// private long assetCacheMemoryUsage; 45// private long assetCacheMemoryUsage;
@@ -73,11 +72,6 @@ namespace OpenSim.Framework.Monitoring
73 private volatile float activeScripts; 72 private volatile float activeScripts;
74 private volatile float scriptLinesPerSecond; 73 private volatile float scriptLinesPerSecond;
75 74
76 /// <summary>
77 /// Number of times that a client thread terminated because of an exception
78 /// </summary>
79 public long AbnormalClientThreadTerminations { get { return abnormalClientThreadTerminations; } }
80
81// /// <summary> 75// /// <summary>
82// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the 76// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the
83// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these 77// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these
@@ -166,11 +160,6 @@ namespace OpenSim.Framework.Monitoring
166 private IDictionary<UUID, PacketQueueStatsCollector> packetQueueStatsCollectors 160 private IDictionary<UUID, PacketQueueStatsCollector> packetQueueStatsCollectors
167 = new Dictionary<UUID, PacketQueueStatsCollector>(); 161 = new Dictionary<UUID, PacketQueueStatsCollector>();
168 162
169 public void AddAbnormalClientThreadTermination()
170 {
171 abnormalClientThreadTerminations++;
172 }
173
174// public void AddAsset(AssetBase asset) 163// public void AddAsset(AssetBase asset)
175// { 164// {
176// assetsInCache++; 165// assetsInCache++;
@@ -324,10 +313,12 @@ Asset service request failures: {3}" + Environment.NewLine,
324 sb.Append(Environment.NewLine); 313 sb.Append(Environment.NewLine);
325 sb.Append("CONNECTION STATISTICS"); 314 sb.Append("CONNECTION STATISTICS");
326 sb.Append(Environment.NewLine); 315 sb.Append(Environment.NewLine);
327 sb.Append( 316
328 string.Format( 317 List<Stat> stats = StatsManager.GetStatsFromEachContainer("clientstack", "ClientLogoutsDueToNoReceives");
329 "Abnormal client thread terminations: {0}" + Environment.NewLine, 318
330 abnormalClientThreadTerminations)); 319 sb.AppendFormat(
320 "Client logouts due to no data receive timeout: {0}\n\n",
321 stats != null ? stats.Sum(s => s.Value).ToString() : "unknown");
331 322
332// sb.Append(Environment.NewLine); 323// sb.Append(Environment.NewLine);
333// sb.Append("INVENTORY STATISTICS"); 324// sb.Append("INVENTORY STATISTICS");
@@ -338,7 +329,7 @@ Asset service request failures: {3}" + Environment.NewLine,
338// InventoryServiceRetrievalFailures)); 329// InventoryServiceRetrievalFailures));
339 330
340 sb.Append(Environment.NewLine); 331 sb.Append(Environment.NewLine);
341 sb.Append("FRAME STATISTICS"); 332 sb.Append("SAMPLE FRAME STATISTICS");
342 sb.Append(Environment.NewLine); 333 sb.Append(Environment.NewLine);
343 sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS"); 334 sb.Append("Dilatn SimFPS PhyFPS AgntUp RootAg ChldAg Prims AtvPrm AtvScr ScrLPS");
344 sb.Append(Environment.NewLine); 335 sb.Append(Environment.NewLine);
diff --git a/OpenSim/Framework/Monitoring/Stats/CounterStat.cs b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
index caea30d..318cf1c 100755
--- a/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/CounterStat.cs
@@ -34,142 +34,6 @@ using OpenMetaverse.StructuredData;
34 34
35namespace OpenSim.Framework.Monitoring 35namespace OpenSim.Framework.Monitoring
36{ 36{
37// Create a time histogram of events. The histogram is built in a wrap-around
38// array of equally distributed buckets.
39// For instance, a minute long histogram of second sized buckets would be:
40// new EventHistogram(60, 1000)
41public class EventHistogram
42{
43 private int m_timeBase;
44 private int m_numBuckets;
45 private int m_bucketMilliseconds;
46 private int m_lastBucket;
47 private int m_totalHistogramMilliseconds;
48 private long[] m_histogram;
49 private object histoLock = new object();
50
51 public EventHistogram(int numberOfBuckets, int millisecondsPerBucket)
52 {
53 m_numBuckets = numberOfBuckets;
54 m_bucketMilliseconds = millisecondsPerBucket;
55 m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds;
56
57 m_histogram = new long[m_numBuckets];
58 Zero();
59 m_lastBucket = 0;
60 m_timeBase = Util.EnvironmentTickCount();
61 }
62
63 public void Event()
64 {
65 this.Event(1);
66 }
67
68 // Record an event at time 'now' in the histogram.
69 public void Event(int cnt)
70 {
71 lock (histoLock)
72 {
73 // The time as displaced from the base of the histogram
74 int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase);
75
76 // If more than the total time of the histogram, we just start over
77 if (bucketTime > m_totalHistogramMilliseconds)
78 {
79 Zero();
80 m_lastBucket = 0;
81 m_timeBase = Util.EnvironmentTickCount();
82 }
83 else
84 {
85 // To which bucket should we add this event?
86 int bucket = bucketTime / m_bucketMilliseconds;
87
88 // Advance m_lastBucket to the new bucket. Zero any buckets skipped over.
89 while (bucket != m_lastBucket)
90 {
91 // Zero from just after the last bucket to the new bucket or the end
92 for (int jj = m_lastBucket + 1; jj <= Math.Min(bucket, m_numBuckets - 1); jj++)
93 {
94 m_histogram[jj] = 0;
95 }
96 m_lastBucket = bucket;
97 // If the new bucket is off the end, wrap around to the beginning
98 if (bucket > m_numBuckets)
99 {
100 bucket -= m_numBuckets;
101 m_lastBucket = 0;
102 m_histogram[m_lastBucket] = 0;
103 m_timeBase += m_totalHistogramMilliseconds;
104 }
105 }
106 }
107 m_histogram[m_lastBucket] += cnt;
108 }
109 }
110
111 // Get a copy of the current histogram
112 public long[] GetHistogram()
113 {
114 long[] ret = new long[m_numBuckets];
115 lock (histoLock)
116 {
117 int indx = m_lastBucket + 1;
118 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
119 {
120 if (indx >= m_numBuckets)
121 indx = 0;
122 ret[ii] = m_histogram[indx];
123 }
124 }
125 return ret;
126 }
127
128 public OSDMap GetHistogramAsOSDMap()
129 {
130 OSDMap ret = new OSDMap();
131
132 ret.Add("Buckets", OSD.FromInteger(m_numBuckets));
133 ret.Add("BucketMilliseconds", OSD.FromInteger(m_bucketMilliseconds));
134 ret.Add("TotalMilliseconds", OSD.FromInteger(m_totalHistogramMilliseconds));
135
136 // Compute a number for the first bucket in the histogram.
137 // This will allow readers to know how this histogram relates to any previously read histogram.
138 int baseBucketNum = (m_timeBase / m_bucketMilliseconds) + m_lastBucket + 1;
139 ret.Add("BaseNumber", OSD.FromInteger(baseBucketNum));
140
141 ret.Add("Values", GetHistogramAsOSDArray());
142
143 return ret;
144 }
145 // Get a copy of the current histogram
146 public OSDArray GetHistogramAsOSDArray()
147 {
148 OSDArray ret = new OSDArray(m_numBuckets);
149 lock (histoLock)
150 {
151 int indx = m_lastBucket + 1;
152 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
153 {
154 if (indx >= m_numBuckets)
155 indx = 0;
156 ret[ii] = OSD.FromLong(m_histogram[indx]);
157 }
158 }
159 return ret;
160 }
161
162 // Zero out the histogram
163 public void Zero()
164 {
165 lock (histoLock)
166 {
167 for (int ii = 0; ii < m_numBuckets; ii++)
168 m_histogram[ii] = 0;
169 }
170 }
171}
172
173// A statistic that wraps a counter. 37// A statistic that wraps a counter.
174// Built this way mostly so histograms and history can be created. 38// Built this way mostly so histograms and history can be created.
175public class CounterStat : Stat 39public class CounterStat : Stat
@@ -224,5 +88,32 @@ public class CounterStat : Stat
224 } 88 }
225 } 89 }
226 } 90 }
91
92 // CounterStat is a basic stat plus histograms
93 public override OSDMap ToOSDMap()
94 {
95 // Get the foundational instance
96 OSDMap map = base.ToOSDMap();
97
98 map["StatType"] = "CounterStat";
99
100 // If there are any histograms, add a new field that is an array of histograms as OSDMaps
101 if (m_histograms.Count > 0)
102 {
103 lock (counterLock)
104 {
105 if (m_histograms.Count > 0)
106 {
107 OSDArray histos = new OSDArray();
108 foreach (EventHistogram histo in m_histograms.Values)
109 {
110 histos.Add(histo.GetHistogramAsOSDMap());
111 }
112 map.Add("Histograms", histos);
113 }
114 }
115 }
116 return map;
117 }
227} 118}
228} 119}
diff --git a/OpenSim/Framework/Monitoring/Stats/EventHistogram.cs b/OpenSim/Framework/Monitoring/Stats/EventHistogram.cs
new file mode 100755
index 0000000..f51f322
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/Stats/EventHistogram.cs
@@ -0,0 +1,173 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenMetaverse.StructuredData;
34
35namespace OpenSim.Framework.Monitoring
36{
37// Create a time histogram of events. The histogram is built in a wrap-around
38// array of equally distributed buckets.
39// For instance, a minute long histogram of second sized buckets would be:
40// new EventHistogram(60, 1000)
41public class EventHistogram
42{
43 private int m_timeBase;
44 private int m_numBuckets;
45 private int m_bucketMilliseconds;
46 private int m_lastBucket;
47 private int m_totalHistogramMilliseconds;
48 private long[] m_histogram;
49 private object histoLock = new object();
50
51 public EventHistogram(int numberOfBuckets, int millisecondsPerBucket)
52 {
53 m_numBuckets = numberOfBuckets;
54 m_bucketMilliseconds = millisecondsPerBucket;
55 m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds;
56
57 m_histogram = new long[m_numBuckets];
58 Zero();
59 m_lastBucket = 0;
60 m_timeBase = Util.EnvironmentTickCount();
61 }
62
63 public void Event()
64 {
65 this.Event(1);
66 }
67
68 // Record an event at time 'now' in the histogram.
69 public void Event(int cnt)
70 {
71 lock (histoLock)
72 {
73 // The time as displaced from the base of the histogram
74 int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase);
75
76 // If more than the total time of the histogram, we just start over
77 if (bucketTime > m_totalHistogramMilliseconds)
78 {
79 Zero();
80 m_lastBucket = 0;
81 m_timeBase = Util.EnvironmentTickCount();
82 }
83 else
84 {
85 // To which bucket should we add this event?
86 int bucket = bucketTime / m_bucketMilliseconds;
87
88 // Advance m_lastBucket to the new bucket. Zero any buckets skipped over.
89 while (bucket != m_lastBucket)
90 {
91 // Zero from just after the last bucket to the new bucket or the end
92 for (int jj = m_lastBucket + 1; jj <= Math.Min(bucket, m_numBuckets - 1); jj++)
93 {
94 m_histogram[jj] = 0;
95 }
96 m_lastBucket = bucket;
97 // If the new bucket is off the end, wrap around to the beginning
98 if (bucket > m_numBuckets)
99 {
100 bucket -= m_numBuckets;
101 m_lastBucket = 0;
102 m_histogram[m_lastBucket] = 0;
103 m_timeBase += m_totalHistogramMilliseconds;
104 }
105 }
106 }
107 m_histogram[m_lastBucket] += cnt;
108 }
109 }
110
111 // Get a copy of the current histogram
112 public long[] GetHistogram()
113 {
114 long[] ret = new long[m_numBuckets];
115 lock (histoLock)
116 {
117 int indx = m_lastBucket + 1;
118 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
119 {
120 if (indx >= m_numBuckets)
121 indx = 0;
122 ret[ii] = m_histogram[indx];
123 }
124 }
125 return ret;
126 }
127
128 public OSDMap GetHistogramAsOSDMap()
129 {
130 OSDMap ret = new OSDMap();
131
132 ret.Add("Buckets", OSD.FromInteger(m_numBuckets));
133 ret.Add("BucketMilliseconds", OSD.FromInteger(m_bucketMilliseconds));
134 ret.Add("TotalMilliseconds", OSD.FromInteger(m_totalHistogramMilliseconds));
135
136 // Compute a number for the first bucket in the histogram.
137 // This will allow readers to know how this histogram relates to any previously read histogram.
138 int baseBucketNum = (m_timeBase / m_bucketMilliseconds) + m_lastBucket + 1;
139 ret.Add("BaseNumber", OSD.FromInteger(baseBucketNum));
140
141 ret.Add("Values", GetHistogramAsOSDArray());
142
143 return ret;
144 }
145 // Get a copy of the current histogram
146 public OSDArray GetHistogramAsOSDArray()
147 {
148 OSDArray ret = new OSDArray(m_numBuckets);
149 lock (histoLock)
150 {
151 int indx = m_lastBucket + 1;
152 for (int ii = 0; ii < m_numBuckets; ii++, indx++)
153 {
154 if (indx >= m_numBuckets)
155 indx = 0;
156 ret[ii] = OSD.FromLong(m_histogram[indx]);
157 }
158 }
159 return ret;
160 }
161
162 // Zero out the histogram
163 public void Zero()
164 {
165 lock (histoLock)
166 {
167 for (int ii = 0; ii < m_numBuckets; ii++)
168 m_histogram[ii] = 0;
169 }
170 }
171}
172
173}
diff --git a/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs b/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs
index 60bed55..55ddf06 100644
--- a/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/PercentageStat.cs
@@ -29,6 +29,8 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31 31
32using OpenMetaverse.StructuredData;
33
32namespace OpenSim.Framework.Monitoring 34namespace OpenSim.Framework.Monitoring
33{ 35{
34 public class PercentageStat : Stat 36 public class PercentageStat : Stat
@@ -84,5 +86,19 @@ namespace OpenSim.Framework.Monitoring
84 86
85 return sb.ToString(); 87 return sb.ToString();
86 } 88 }
89
90 // PercentageStat is a basic stat plus percent calc
91 public override OSDMap ToOSDMap()
92 {
93 // Get the foundational instance
94 OSDMap map = base.ToOSDMap();
95
96 map["StatType"] = "PercentageStat";
97
98 map.Add("Antecedent", OSD.FromLong(Antecedent));
99 map.Add("Consequent", OSD.FromLong(Consequent));
100
101 return map;
102 }
87 } 103 }
88} \ No newline at end of file 104} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/Stats/Stat.cs b/OpenSim/Framework/Monitoring/Stats/Stat.cs
index 2e7665f..e095801 100644
--- a/OpenSim/Framework/Monitoring/Stats/Stat.cs
+++ b/OpenSim/Framework/Monitoring/Stats/Stat.cs
@@ -27,8 +27,10 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
30using System.Text; 32using System.Text;
31 33using log4net;
32using OpenMetaverse.StructuredData; 34using OpenMetaverse.StructuredData;
33 35
34namespace OpenSim.Framework.Monitoring 36namespace OpenSim.Framework.Monitoring
@@ -38,6 +40,10 @@ namespace OpenSim.Framework.Monitoring
38 /// </summary> 40 /// </summary>
39 public class Stat : IDisposable 41 public class Stat : IDisposable
40 { 42 {
43// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 public static readonly char[] DisallowedShortNameCharacters = { '.' };
46
41 /// <summary> 47 /// <summary>
42 /// Category of this stat (e.g. cache, scene, etc). 48 /// Category of this stat (e.g. cache, scene, etc).
43 /// </summary> 49 /// </summary>
@@ -95,7 +101,7 @@ namespace OpenSim.Framework.Monitoring
95 /// <remarks> 101 /// <remarks>
96 /// Will be null if no measures of interest require samples. 102 /// Will be null if no measures of interest require samples.
97 /// </remarks> 103 /// </remarks>
98 private static Queue<double> m_samples; 104 private Queue<double> m_samples;
99 105
100 /// <summary> 106 /// <summary>
101 /// Maximum number of statistical samples. 107 /// Maximum number of statistical samples.
@@ -162,6 +168,12 @@ namespace OpenSim.Framework.Monitoring
162 throw new Exception( 168 throw new Exception(
163 string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category)); 169 string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
164 170
171 foreach (char c in DisallowedShortNameCharacters)
172 {
173 if (shortName.IndexOf(c) != -1)
174 throw new Exception(string.Format("Stat name {0} cannot contain character {1}", shortName, c));
175 }
176
165 ShortName = shortName; 177 ShortName = shortName;
166 Name = name; 178 Name = name;
167 Description = description; 179 Description = description;
@@ -204,6 +216,8 @@ namespace OpenSim.Framework.Monitoring
204 if (m_samples.Count >= m_maxSamples) 216 if (m_samples.Count >= m_maxSamples)
205 m_samples.Dequeue(); 217 m_samples.Dequeue();
206 218
219// m_log.DebugFormat("[STAT]: Recording value {0} for {1}", newValue, Name);
220
207 m_samples.Enqueue(newValue); 221 m_samples.Enqueue(newValue);
208 } 222 }
209 } 223 }
@@ -211,7 +225,13 @@ namespace OpenSim.Framework.Monitoring
211 public virtual string ToConsoleString() 225 public virtual string ToConsoleString()
212 { 226 {
213 StringBuilder sb = new StringBuilder(); 227 StringBuilder sb = new StringBuilder();
214 sb.AppendFormat("{0}.{1}.{2} : {3} {4}", Category, Container, ShortName, Value, UnitName); 228 sb.AppendFormat(
229 "{0}.{1}.{2} : {3}{4}",
230 Category,
231 Container,
232 ShortName,
233 Value,
234 string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName));
215 235
216 AppendMeasuresOfInterest(sb); 236 AppendMeasuresOfInterest(sb);
217 237
@@ -221,6 +241,8 @@ namespace OpenSim.Framework.Monitoring
221 public virtual OSDMap ToOSDMap() 241 public virtual OSDMap ToOSDMap()
222 { 242 {
223 OSDMap ret = new OSDMap(); 243 OSDMap ret = new OSDMap();
244 ret.Add("StatType", "Stat"); // used by overloading classes to denote type of stat
245
224 ret.Add("Category", OSD.FromString(Category)); 246 ret.Add("Category", OSD.FromString(Category));
225 ret.Add("Container", OSD.FromString(Container)); 247 ret.Add("Container", OSD.FromString(Container));
226 ret.Add("ShortName", OSD.FromString(ShortName)); 248 ret.Add("ShortName", OSD.FromString(ShortName));
@@ -229,31 +251,74 @@ namespace OpenSim.Framework.Monitoring
229 ret.Add("UnitName", OSD.FromString(UnitName)); 251 ret.Add("UnitName", OSD.FromString(UnitName));
230 ret.Add("Value", OSD.FromReal(Value)); 252 ret.Add("Value", OSD.FromReal(Value));
231 253
254 double lastChangeOverTime, averageChangeOverTime;
255 if (ComputeMeasuresOfInterest(out lastChangeOverTime, out averageChangeOverTime))
256 {
257 ret.Add("LastChangeOverTime", OSD.FromReal(lastChangeOverTime));
258 ret.Add("AverageChangeOverTime", OSD.FromReal(averageChangeOverTime));
259 }
260
232 return ret; 261 return ret;
233 } 262 }
234 263
235 protected void AppendMeasuresOfInterest(StringBuilder sb) 264 // Compute the averages over time and return same.
265 // Return 'true' if averages were actually computed. 'false' if no average info.
266 public bool ComputeMeasuresOfInterest(out double lastChangeOverTime, out double averageChangeOverTime)
236 { 267 {
237 if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime) 268 bool ret = false;
238 == MeasuresOfInterest.AverageChangeOverTime) 269 lastChangeOverTime = 0;
270 averageChangeOverTime = 0;
271
272 if ((MeasuresOfInterest & MeasuresOfInterest.AverageChangeOverTime) == MeasuresOfInterest.AverageChangeOverTime)
239 { 273 {
240 double totalChange = 0; 274 double totalChange = 0;
275 double? penultimateSample = null;
241 double? lastSample = null; 276 double? lastSample = null;
242 277
243 lock (m_samples) 278 lock (m_samples)
244 { 279 {
280 // m_log.DebugFormat(
281 // "[STAT]: Samples for {0} are {1}",
282 // Name, string.Join(",", m_samples.Select(s => s.ToString()).ToArray()));
283
245 foreach (double s in m_samples) 284 foreach (double s in m_samples)
246 { 285 {
247 if (lastSample != null) 286 if (lastSample != null)
248 totalChange += s - (double)lastSample; 287 totalChange += s - (double)lastSample;
249 288
289 penultimateSample = lastSample;
250 lastSample = s; 290 lastSample = s;
251 } 291 }
252 } 292 }
253 293
294 if (lastSample != null && penultimateSample != null)
295 {
296 lastChangeOverTime
297 = ((double)lastSample - (double)penultimateSample) / (Watchdog.WATCHDOG_INTERVAL_MS / 1000);
298 }
299
254 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1; 300 int divisor = m_samples.Count <= 1 ? 1 : m_samples.Count - 1;
255 301
256 sb.AppendFormat(", {0:0.##}{1}/s", totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000), UnitName); 302 averageChangeOverTime = totalChange / divisor / (Watchdog.WATCHDOG_INTERVAL_MS / 1000);
303 ret = true;
304 }
305
306 return ret;
307 }
308
309 protected void AppendMeasuresOfInterest(StringBuilder sb)
310 {
311 double lastChangeOverTime = 0;
312 double averageChangeOverTime = 0;
313
314 if (ComputeMeasuresOfInterest(out lastChangeOverTime, out averageChangeOverTime))
315 {
316 sb.AppendFormat(
317 ", {0:0.##}{1}/s, {2:0.##}{3}/s",
318 lastChangeOverTime,
319 string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName),
320 averageChangeOverTime,
321 string.IsNullOrEmpty(UnitName) ? "" : string.Format(" {0}", UnitName));
257 } 322 }
258 } 323 }
259 } 324 }
diff --git a/OpenSim/Framework/Monitoring/StatsLogger.cs b/OpenSim/Framework/Monitoring/StatsLogger.cs
new file mode 100644
index 0000000..1e4fa11
--- /dev/null
+++ b/OpenSim/Framework/Monitoring/StatsLogger.cs
@@ -0,0 +1,108 @@
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.Reflection;
30using System.Timers;
31using log4net;
32
33namespace OpenSim.Framework.Monitoring
34{
35 /// <summary>
36 /// Provides a means to continuously log stats for debugging purposes.
37 /// </summary>
38 public static class StatsLogger
39 {
40 private static readonly ILog m_statsLog = LogManager.GetLogger("special.StatsLogger");
41
42 private static Timer m_loggingTimer;
43 private static int m_statsLogIntervalMs = 5000;
44
45 public static void RegisterConsoleCommands(ICommandConsole console)
46 {
47 console.Commands.AddCommand(
48 "Debug",
49 false,
50 "debug stats record",
51 "debug stats record start|stop",
52 "Control whether stats are being regularly recorded to a separate file.",
53 "For debug purposes. Experimental.",
54 HandleStatsRecordCommand);
55 }
56
57 public static void HandleStatsRecordCommand(string module, string[] cmd)
58 {
59 ICommandConsole con = MainConsole.Instance;
60
61 if (cmd.Length != 4)
62 {
63 con.Output("Usage: debug stats record start|stop");
64 return;
65 }
66
67 if (cmd[3] == "start")
68 {
69 Start();
70 con.OutputFormat("Now recording all stats to file every {0}ms", m_statsLogIntervalMs);
71 }
72 else if (cmd[3] == "stop")
73 {
74 Stop();
75 con.Output("Stopped recording stats to file.");
76 }
77 }
78
79 public static void Start()
80 {
81 if (m_loggingTimer != null)
82 Stop();
83
84 m_loggingTimer = new Timer(m_statsLogIntervalMs);
85 m_loggingTimer.AutoReset = false;
86 m_loggingTimer.Elapsed += Log;
87 m_loggingTimer.Start();
88 }
89
90 public static void Stop()
91 {
92 if (m_loggingTimer != null)
93 {
94 m_loggingTimer.Stop();
95 }
96 }
97
98 private static void Log(object sender, ElapsedEventArgs e)
99 {
100 m_statsLog.InfoFormat("*** STATS REPORT AT {0} ***", DateTime.Now);
101
102 foreach (string report in StatsManager.GetAllStatsReports())
103 m_statsLog.Info(report);
104
105 m_loggingTimer.Start();
106 }
107 }
108} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 24db6d4..05ee4c5 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -26,15 +26,20 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
29using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Linq;
30using System.Text; 32using System.Text;
31 33
34using OpenSim.Framework;
35using OpenMetaverse.StructuredData;
36
32namespace OpenSim.Framework.Monitoring 37namespace OpenSim.Framework.Monitoring
33{ 38{
34 /// <summary> 39 /// <summary>
35 /// Singleton used to provide access to statistics reporters 40 /// Static class used to register/deregister/fetch statistics
36 /// </summary> 41 /// </summary>
37 public class StatsManager 42 public static class StatsManager
38 { 43 {
39 // Subcommand used to list other stats. 44 // Subcommand used to list other stats.
40 public const string AllSubCommand = "all"; 45 public const string AllSubCommand = "all";
@@ -54,13 +59,13 @@ namespace OpenSim.Framework.Monitoring
54 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats 59 public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
55 = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>(); 60 = new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>();
56 61
57 private static AssetStatsCollector assetStats; 62// private static AssetStatsCollector assetStats;
58 private static UserStatsCollector userStats; 63// private static UserStatsCollector userStats;
59 private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); 64// private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
60 65
61 public static AssetStatsCollector AssetStats { get { return assetStats; } } 66// public static AssetStatsCollector AssetStats { get { return assetStats; } }
62 public static UserStatsCollector UserStats { get { return userStats; } } 67// public static UserStatsCollector UserStats { get { return userStats; } }
63 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } 68 public static SimExtraStatsCollector SimExtraStats { get; set; }
64 69
65 public static void RegisterConsoleCommands(ICommandConsole console) 70 public static void RegisterConsoleCommands(ICommandConsole console)
66 { 71 {
@@ -68,14 +73,18 @@ namespace OpenSim.Framework.Monitoring
68 "General", 73 "General",
69 false, 74 false,
70 "show stats", 75 "show stats",
71 "show stats [list|all|<category>]", 76 "show stats [list|all|(<category>[.<container>])+",
72 "Show statistical information for this server", 77 "Show statistical information for this server",
73 "If no final argument is specified then legacy statistics information is currently shown.\n" 78 "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" 79 + "'list' argument will show statistic categories.\n"
75 + "If all is specified then all registered statistics are shown.\n" 80 + "'all' will show all statistics.\n"
76 + "If a category name is specified then only statistics from that category are shown.\n" 81 + "A <category> name will show statistics from that category.\n"
82 + "A <category>.<container> name will show statistics from that category in that container.\n"
83 + "More than one name can be given separated by spaces.\n"
77 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", 84 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
78 HandleShowStatsCommand); 85 HandleShowStatsCommand);
86
87 StatsLogger.RegisterConsoleCommands(console);
79 } 88 }
80 89
81 public static void HandleShowStatsCommand(string module, string[] cmd) 90 public static void HandleShowStatsCommand(string module, string[] cmd)
@@ -84,43 +93,47 @@ namespace OpenSim.Framework.Monitoring
84 93
85 if (cmd.Length > 2) 94 if (cmd.Length > 2)
86 { 95 {
87 var categoryName = cmd[2]; 96 foreach (string name in cmd.Skip(2))
88 var containerName = cmd.Length > 3 ? cmd[3] : String.Empty;
89
90 if (categoryName == AllSubCommand)
91 { 97 {
92 foreach (var category in RegisteredStats.Values) 98 string[] components = name.Split('.');
99
100 string categoryName = components[0];
101 string containerName = components.Length > 1 ? components[1] : null;
102
103 if (categoryName == AllSubCommand)
93 { 104 {
94 OutputCategoryStatsToConsole(con, category); 105 OutputAllStatsToConsole(con);
95 } 106 }
96 } 107 else if (categoryName == ListSubCommand)
97 else if (categoryName == ListSubCommand)
98 {
99 con.Output("Statistic categories available are:");
100 foreach (string category in RegisteredStats.Keys)
101 con.OutputFormat(" {0}", category);
102 }
103 else
104 {
105 SortedDictionary<string, SortedDictionary<string, Stat>> category;
106 if (!RegisteredStats.TryGetValue(categoryName, out category))
107 { 108 {
108 con.OutputFormat("No such category as {0}", categoryName); 109 con.Output("Statistic categories available are:");
110 foreach (string category in RegisteredStats.Keys)
111 con.OutputFormat(" {0}", category);
109 } 112 }
110 else 113 else
111 { 114 {
112 if (String.IsNullOrEmpty(containerName)) 115 SortedDictionary<string, SortedDictionary<string, Stat>> category;
113 OutputCategoryStatsToConsole(con, category); 116 if (!RegisteredStats.TryGetValue(categoryName, out category))
117 {
118 con.OutputFormat("No such category as {0}", categoryName);
119 }
114 else 120 else
115 { 121 {
116 SortedDictionary<string, Stat> container; 122 if (String.IsNullOrEmpty(containerName))
117 if (category.TryGetValue(containerName, out container))
118 { 123 {
119 OutputContainerStatsToConsole(con, container); 124 OutputCategoryStatsToConsole(con, category);
120 } 125 }
121 else 126 else
122 { 127 {
123 con.OutputFormat("No such container {0} in category {1}", containerName, categoryName); 128 SortedDictionary<string, Stat> container;
129 if (category.TryGetValue(containerName, out container))
130 {
131 OutputContainerStatsToConsole(con, container);
132 }
133 else
134 {
135 con.OutputFormat("No such container {0} in category {1}", containerName, categoryName);
136 }
124 } 137 }
125 } 138 }
126 } 139 }
@@ -129,51 +142,187 @@ namespace OpenSim.Framework.Monitoring
129 else 142 else
130 { 143 {
131 // Legacy 144 // Legacy
132 con.Output(SimExtraStats.Report()); 145 if (SimExtraStats != null)
146 con.Output(SimExtraStats.Report());
147 else
148 OutputAllStatsToConsole(con);
133 } 149 }
134 } 150 }
135 151
152 public static List<string> GetAllStatsReports()
153 {
154 List<string> reports = new List<string>();
155
156 foreach (var category in RegisteredStats.Values)
157 reports.AddRange(GetCategoryStatsReports(category));
158
159 return reports;
160 }
161
162 private static void OutputAllStatsToConsole(ICommandConsole con)
163 {
164 foreach (string report in GetAllStatsReports())
165 con.Output(report);
166 }
167
168 private static List<string> GetCategoryStatsReports(
169 SortedDictionary<string, SortedDictionary<string, Stat>> category)
170 {
171 List<string> reports = new List<string>();
172
173 foreach (var container in category.Values)
174 reports.AddRange(GetContainerStatsReports(container));
175
176 return reports;
177 }
178
136 private static void OutputCategoryStatsToConsole( 179 private static void OutputCategoryStatsToConsole(
137 ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category) 180 ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category)
138 { 181 {
139 foreach (var container in category.Values) 182 foreach (string report in GetCategoryStatsReports(category))
140 { 183 con.Output(report);
141 OutputContainerStatsToConsole(con, container);
142 }
143 } 184 }
144 185
145 private static void OutputContainerStatsToConsole( ICommandConsole con, SortedDictionary<string, Stat> container) 186 private static List<string> GetContainerStatsReports(SortedDictionary<string, Stat> container)
146 { 187 {
188 List<string> reports = new List<string>();
189
147 foreach (Stat stat in container.Values) 190 foreach (Stat stat in container.Values)
148 { 191 reports.Add(stat.ToConsoleString());
149 con.Output(stat.ToConsoleString()); 192
150 } 193 return reports;
151 } 194 }
152 195
153 /// <summary> 196 private static void OutputContainerStatsToConsole(
154 /// Start collecting statistics related to assets. 197 ICommandConsole con, SortedDictionary<string, Stat> container)
155 /// Should only be called once. 198 {
156 /// </summary> 199 foreach (string report in GetContainerStatsReports(container))
157 public static AssetStatsCollector StartCollectingAssetStats() 200 con.Output(report);
201 }
202
203 // Creates an OSDMap of the format:
204 // { categoryName: {
205 // containerName: {
206 // statName: {
207 // "Name": name,
208 // "ShortName": shortName,
209 // ...
210 // },
211 // statName: {
212 // "Name": name,
213 // "ShortName": shortName,
214 // ...
215 // },
216 // ...
217 // },
218 // containerName: {
219 // ...
220 // },
221 // ...
222 // },
223 // categoryName: {
224 // ...
225 // },
226 // ...
227 // }
228 // The passed in parameters will filter the categories, containers and stats returned. If any of the
229 // parameters are either EmptyOrNull or the AllSubCommand value, all of that type will be returned.
230 // Case matters.
231 public static OSDMap GetStatsAsOSDMap(string pCategoryName, string pContainerName, string pStatName)
158 { 232 {
159 assetStats = new AssetStatsCollector(); 233 OSDMap map = new OSDMap();
234
235 foreach (string catName in RegisteredStats.Keys)
236 {
237 // Do this category if null spec, "all" subcommand or category name matches passed parameter.
238 // Skip category if none of the above.
239 if (!(String.IsNullOrEmpty(pCategoryName) || pCategoryName == AllSubCommand || pCategoryName == catName))
240 continue;
160 241
161 return assetStats; 242 OSDMap contMap = new OSDMap();
243 foreach (string contName in RegisteredStats[catName].Keys)
244 {
245 if (!(string.IsNullOrEmpty(pContainerName) || pContainerName == AllSubCommand || pContainerName == contName))
246 continue;
247
248 OSDMap statMap = new OSDMap();
249
250 SortedDictionary<string, Stat> theStats = RegisteredStats[catName][contName];
251 foreach (string statName in theStats.Keys)
252 {
253 if (!(String.IsNullOrEmpty(pStatName) || pStatName == AllSubCommand || pStatName == statName))
254 continue;
255
256 statMap.Add(statName, theStats[statName].ToOSDMap());
257 }
258
259 contMap.Add(contName, statMap);
260 }
261 map.Add(catName, contMap);
262 }
263
264 return map;
162 } 265 }
163 266
164 /// <summary> 267 public static Hashtable HandleStatsRequest(Hashtable request)
165 /// Start collecting statistics related to users.
166 /// Should only be called once.
167 /// </summary>
168 public static UserStatsCollector StartCollectingUserStats()
169 { 268 {
170 userStats = new UserStatsCollector(); 269 Hashtable responsedata = new Hashtable();
270// string regpath = request["uri"].ToString();
271 int response_code = 200;
272 string contenttype = "text/json";
273
274 string pCategoryName = StatsManager.AllSubCommand;
275 string pContainerName = StatsManager.AllSubCommand;
276 string pStatName = StatsManager.AllSubCommand;
277
278 if (request.ContainsKey("cat")) pCategoryName = request["cat"].ToString();
279 if (request.ContainsKey("cont")) pContainerName = request["cat"].ToString();
280 if (request.ContainsKey("stat")) pStatName = request["cat"].ToString();
281
282 string strOut = StatsManager.GetStatsAsOSDMap(pCategoryName, pContainerName, pStatName).ToString();
283
284 // If requestor wants it as a callback function, build response as a function rather than just the JSON string.
285 if (request.ContainsKey("callback"))
286 {
287 strOut = request["callback"].ToString() + "(" + strOut + ");";
288 }
171 289
172 return userStats; 290 // m_log.DebugFormat("{0} StatFetch: uri={1}, cat={2}, cont={3}, stat={4}, resp={5}",
291 // LogHeader, regpath, pCategoryName, pContainerName, pStatName, strOut);
292
293 responsedata["int_response_code"] = response_code;
294 responsedata["content_type"] = contenttype;
295 responsedata["keepalive"] = false;
296 responsedata["str_response_string"] = strOut;
297 responsedata["access_control_allow_origin"] = "*";
298
299 return responsedata;
173 } 300 }
174 301
302// /// <summary>
303// /// Start collecting statistics related to assets.
304// /// Should only be called once.
305// /// </summary>
306// public static AssetStatsCollector StartCollectingAssetStats()
307// {
308// assetStats = new AssetStatsCollector();
309//
310// return assetStats;
311// }
312//
313// /// <summary>
314// /// Start collecting statistics related to users.
315// /// Should only be called once.
316// /// </summary>
317// public static UserStatsCollector StartCollectingUserStats()
318// {
319// userStats = new UserStatsCollector();
320//
321// return userStats;
322// }
323
175 /// <summary> 324 /// <summary>
176 /// Registers a statistic. 325 /// Register a statistic.
177 /// </summary> 326 /// </summary>
178 /// <param name='stat'></param> 327 /// <param name='stat'></param>
179 /// <returns></returns> 328 /// <returns></returns>
@@ -187,7 +336,7 @@ namespace OpenSim.Framework.Monitoring
187 // Stat name is not unique across category/container/shortname key. 336 // Stat name is not unique across category/container/shortname key.
188 // XXX: For now just return false. This is to avoid problems in regression tests where all tests 337 // XXX: For now just return false. This is to avoid problems in regression tests where all tests
189 // in a class are run in the same instance of the VM. 338 // in a class are run in the same instance of the VM.
190 if (TryGetStat(stat, out category, out container)) 339 if (TryGetStatParents(stat, out category, out container))
191 return false; 340 return false;
192 341
193 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed. 342 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
@@ -223,7 +372,7 @@ namespace OpenSim.Framework.Monitoring
223 372
224 lock (RegisteredStats) 373 lock (RegisteredStats)
225 { 374 {
226 if (!TryGetStat(stat, out category, out container)) 375 if (!TryGetStatParents(stat, out category, out container))
227 return false; 376 return false;
228 377
229 newContainer = new SortedDictionary<string, Stat>(container); 378 newContainer = new SortedDictionary<string, Stat>(container);
@@ -239,12 +388,67 @@ namespace OpenSim.Framework.Monitoring
239 } 388 }
240 } 389 }
241 390
242 public static bool TryGetStats(string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats) 391 public static bool TryGetStat(string category, string container, string statShortName, out Stat stat)
243 { 392 {
244 return RegisteredStats.TryGetValue(category, out stats); 393 stat = null;
394 SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
395
396 lock (RegisteredStats)
397 {
398 if (!TryGetStatsForCategory(category, out categoryStats))
399 return false;
400
401 SortedDictionary<string, Stat> containerStats;
402
403 if (!categoryStats.TryGetValue(container, out containerStats))
404 return false;
405
406 return containerStats.TryGetValue(statShortName, out stat);
407 }
408 }
409
410 public static bool TryGetStatsForCategory(
411 string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats)
412 {
413 lock (RegisteredStats)
414 return RegisteredStats.TryGetValue(category, out stats);
415 }
416
417 /// <summary>
418 /// Get the same stat for each container in a given category.
419 /// </summary>
420 /// <returns>
421 /// The stats if there were any to fetch. Otherwise null.
422 /// </returns>
423 /// <param name='category'></param>
424 /// <param name='statShortName'></param>
425 public static List<Stat> GetStatsFromEachContainer(string category, string statShortName)
426 {
427 SortedDictionary<string, SortedDictionary<string, Stat>> categoryStats;
428
429 lock (RegisteredStats)
430 {
431 if (!RegisteredStats.TryGetValue(category, out categoryStats))
432 return null;
433
434 List<Stat> stats = null;
435
436 foreach (SortedDictionary<string, Stat> containerStats in categoryStats.Values)
437 {
438 if (containerStats.ContainsKey(statShortName))
439 {
440 if (stats == null)
441 stats = new List<Stat>();
442
443 stats.Add(containerStats[statShortName]);
444 }
445 }
446
447 return stats;
448 }
245 } 449 }
246 450
247 public static bool TryGetStat( 451 public static bool TryGetStatParents(
248 Stat stat, 452 Stat stat,
249 out SortedDictionary<string, SortedDictionary<string, Stat>> category, 453 out SortedDictionary<string, SortedDictionary<string, Stat>> category,
250 out SortedDictionary<string, Stat> container) 454 out SortedDictionary<string, Stat> container)
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index 69d2db5..32724ec 100644
--- a/OpenSim/Framework/Monitoring/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -380,6 +380,7 @@ namespace OpenSim.Framework.Monitoring
380 if (MemoryWatchdog.Enabled) 380 if (MemoryWatchdog.Enabled)
381 MemoryWatchdog.Update(); 381 MemoryWatchdog.Update();
382 382
383 ChecksManager.CheckChecks();
383 StatsManager.RecordStats(); 384 StatsManager.RecordStats();
384 385
385 m_watchdogTimer.Start(); 386 m_watchdogTimer.Start();
diff --git a/OpenSim/Framework/PermissionsUtil.cs b/OpenSim/Framework/PermissionsUtil.cs
new file mode 100644
index 0000000..d785a78
--- /dev/null
+++ b/OpenSim/Framework/PermissionsUtil.cs
@@ -0,0 +1,87 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text;
32using log4net;
33
34namespace OpenSim.Framework
35{
36 public static class PermissionsUtil
37 {
38 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39
40 /// <summary>
41 /// Logs permissions flags. Useful when debugging permission problems.
42 /// </summary>
43 /// <param name="message"></param>
44 public static void LogPermissions(String name, String message, uint basePerm, uint curPerm, uint nextPerm)
45 {
46 m_log.DebugFormat("Permissions of \"{0}\" at \"{1}\": Base {2} ({3:X4}), Current {4} ({5:X4}), NextOwner {6} ({7:X4})",
47 name, message,
48 PermissionsToString(basePerm), basePerm, PermissionsToString(curPerm), curPerm, PermissionsToString(nextPerm), nextPerm);
49 }
50
51 /// <summary>
52 /// Converts a permissions bit-mask to a string (e.g., "MCT").
53 /// </summary>
54 private static string PermissionsToString(uint perms)
55 {
56 string str = "";
57 if ((perms & (int)PermissionMask.Modify) != 0)
58 str += "M";
59 if ((perms & (int)PermissionMask.Copy) != 0)
60 str += "C";
61 if ((perms & (int)PermissionMask.Transfer) != 0)
62 str += "T";
63 if (str == "")
64 str = ".";
65 return str;
66 }
67
68 /// <summary>
69 /// Applies an object's folded permissions to its regular permissions.
70 /// </summary>
71 /// <param name="foldedPerms">The folded permissions. Only the lowest 7 bits are examined.</param>
72 /// <param name="mainPerms">The permissions variable to modify.</param>
73 public static void ApplyFoldedPermissions(uint foldedPerms, ref uint mainPerms)
74 {
75 if ((foldedPerms & 7) == 0)
76 return; // assume that if the folded permissions are 0 then this means that they weren't actually recorded
77
78 if ((foldedPerms & ((uint)PermissionMask.Copy >> 13)) == 0)
79 mainPerms &= ~(uint)PermissionMask.Copy;
80 if ((foldedPerms & ((uint)PermissionMask.Transfer >> 13)) == 0)
81 mainPerms &= ~(uint)PermissionMask.Transfer;
82 if ((foldedPerms & ((uint)PermissionMask.Modify >> 13)) == 0)
83 mainPerms &= ~(uint)PermissionMask.Modify;
84 }
85
86 }
87}
diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs
index df928dc..6a12a45 100644
--- a/OpenSim/Framework/PrimitiveBaseShape.cs
+++ b/OpenSim/Framework/PrimitiveBaseShape.cs
@@ -105,6 +105,7 @@ namespace OpenSim.Framework
105 private ushort _profileHollow; 105 private ushort _profileHollow;
106 private Vector3 _scale; 106 private Vector3 _scale;
107 private byte _state; 107 private byte _state;
108 private byte _lastattach;
108 private ProfileShape _profileShape; 109 private ProfileShape _profileShape;
109 private HollowShape _hollowShape; 110 private HollowShape _hollowShape;
110 111
@@ -207,6 +208,7 @@ namespace OpenSim.Framework
207 PCode = (byte)prim.PrimData.PCode; 208 PCode = (byte)prim.PrimData.PCode;
208 209
209 State = prim.PrimData.State; 210 State = prim.PrimData.State;
211 LastAttachPoint = prim.PrimData.State;
210 PathBegin = Primitive.PackBeginCut(prim.PrimData.PathBegin); 212 PathBegin = Primitive.PackBeginCut(prim.PrimData.PathBegin);
211 PathEnd = Primitive.PackEndCut(prim.PrimData.PathEnd); 213 PathEnd = Primitive.PackEndCut(prim.PrimData.PathEnd);
212 PathScaleX = Primitive.PackPathScale(prim.PrimData.PathScaleX); 214 PathScaleX = Primitive.PackPathScale(prim.PrimData.PathScaleX);
@@ -583,6 +585,15 @@ namespace OpenSim.Framework
583 } 585 }
584 } 586 }
585 587
588 public byte LastAttachPoint {
589 get {
590 return _lastattach;
591 }
592 set {
593 _lastattach = value;
594 }
595 }
596
586 public ProfileShape ProfileShape { 597 public ProfileShape ProfileShape {
587 get { 598 get {
588 return _profileShape; 599 return _profileShape;
diff --git a/OpenSim/Framework/RegionFlags.cs b/OpenSim/Framework/RegionFlags.cs
index a3089b0..7c6569e 100644
--- a/OpenSim/Framework/RegionFlags.cs
+++ b/OpenSim/Framework/RegionFlags.cs
@@ -48,6 +48,7 @@ namespace OpenSim.Framework
48 NoMove = 64, // Don't allow moving this region 48 NoMove = 64, // Don't allow moving this region
49 Reservation = 128, // This is an inactive reservation 49 Reservation = 128, // This is an inactive reservation
50 Authenticate = 256, // Require authentication 50 Authenticate = 256, // Require authentication
51 Hyperlink = 512 // Record represents a HG link 51 Hyperlink = 512, // Record represents a HG link
52 DefaultHGRegion = 1024 // Record represents a default region for hypergrid teleports only.
52 } 53 }
53} \ No newline at end of file 54} \ No newline at end of file
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index 24ec181..ae2ff63 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -100,6 +100,7 @@ namespace OpenSim.Framework
100 public class RegionInfo 100 public class RegionInfo
101 { 101 {
102 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 102 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
103 private static readonly string LogHeader = "[REGION INFO]";
103 104
104 public bool commFailTF = false; 105 public bool commFailTF = false;
105 public ConfigurationMember configMember; 106 public ConfigurationMember configMember;
@@ -139,16 +140,20 @@ namespace OpenSim.Framework
139 public bool m_allow_alternate_ports; 140 public bool m_allow_alternate_ports;
140 protected string m_externalHostName; 141 protected string m_externalHostName;
141 protected IPEndPoint m_internalEndPoint; 142 protected IPEndPoint m_internalEndPoint;
142 protected uint? m_regionLocX;
143 protected uint? m_regionLocY;
144 protected uint m_remotingPort; 143 protected uint m_remotingPort;
145 public UUID RegionID = UUID.Zero; 144 public UUID RegionID = UUID.Zero;
146 public string RemotingAddress; 145 public string RemotingAddress;
147 public UUID ScopeID = UUID.Zero; 146 public UUID ScopeID = UUID.Zero;
148 private UUID m_maptileStaticUUID = UUID.Zero; 147 private UUID m_maptileStaticUUID = UUID.Zero;
149 148
150 private Dictionary<String, String> m_otherSettings = new Dictionary<string, string>(); 149 public uint WorldLocX = 0;
150 public uint WorldLocY = 0;
151 public uint WorldLocZ = 0;
152 public uint RegionSizeX = Constants.RegionSize;
153 public uint RegionSizeY = Constants.RegionSize;
154 public uint RegionSizeZ = Constants.RegionHeight;
151 155
156 private Dictionary<String, String> m_otherSettings = new Dictionary<string, string>();
152 157
153 // Apparently, we're applying the same estatesettings regardless of whether it's local or remote. 158 // Apparently, we're applying the same estatesettings regardless of whether it's local or remote.
154 159
@@ -233,11 +238,12 @@ namespace OpenSim.Framework
233 m_serverURI = string.Empty; 238 m_serverURI = string.Empty;
234 } 239 }
235 240
236 public RegionInfo(uint regionLocX, uint regionLocY, IPEndPoint internalEndPoint, string externalUri) 241 public RegionInfo(uint legacyRegionLocX, uint legacyRegionLocY, IPEndPoint internalEndPoint, string externalUri)
237 { 242 {
238 m_regionLocX = regionLocX; 243 RegionLocX = legacyRegionLocX;
239 m_regionLocY = regionLocY; 244 RegionLocY = legacyRegionLocY;
240 245 RegionSizeX = Constants.RegionSize;
246 RegionSizeY = Constants.RegionSize;
241 m_internalEndPoint = internalEndPoint; 247 m_internalEndPoint = internalEndPoint;
242 m_externalHostName = externalUri; 248 m_externalHostName = externalUri;
243 m_serverURI = string.Empty; 249 m_serverURI = string.Empty;
@@ -451,25 +457,42 @@ namespace OpenSim.Framework
451 457
452 /// <summary> 458 /// <summary>
453 /// The x co-ordinate of this region in map tiles (e.g. 1000). 459 /// The x co-ordinate of this region in map tiles (e.g. 1000).
460 /// Coordinate is scaled as world coordinates divided by the legacy region size
461 /// and is thus is the number of legacy regions.
454 /// </summary> 462 /// </summary>
455 public uint RegionLocX 463 public uint RegionLocX
456 { 464 {
457 get { return m_regionLocX.Value; } 465 get { return WorldLocX / Constants.RegionSize; }
458 set { m_regionLocX = value; } 466 set { WorldLocX = value * Constants.RegionSize; }
459 } 467 }
460 468
461 /// <summary> 469 /// <summary>
462 /// The y co-ordinate of this region in map tiles (e.g. 1000). 470 /// The y co-ordinate of this region in map tiles (e.g. 1000).
471 /// Coordinate is scaled as world coordinates divided by the legacy region size
472 /// and is thus is the number of legacy regions.
463 /// </summary> 473 /// </summary>
464 public uint RegionLocY 474 public uint RegionLocY
465 { 475 {
466 get { return m_regionLocY.Value; } 476 get { return WorldLocY / Constants.RegionSize; }
467 set { m_regionLocY = value; } 477 set { WorldLocY = value * Constants.RegionSize; }
468 } 478 }
469 479
480 public void SetDefaultRegionSize()
481 {
482 WorldLocX = 0;
483 WorldLocY = 0;
484 WorldLocZ = 0;
485 RegionSizeX = Constants.RegionSize;
486 RegionSizeY = Constants.RegionSize;
487 RegionSizeZ = Constants.RegionHeight;
488 }
489
490 // A unique region handle is created from the region's world coordinates.
491 // This cannot be changed because some code expects to receive the region handle and then
492 // compute the region coordinates from it.
470 public ulong RegionHandle 493 public ulong RegionHandle
471 { 494 {
472 get { return Util.UIntsToLong((RegionLocX * (uint) Constants.RegionSize), (RegionLocY * (uint) Constants.RegionSize)); } 495 get { return Util.UIntsToLong(WorldLocX, WorldLocY); }
473 } 496 }
474 497
475 public void SetEndPoint(string ipaddr, int port) 498 public void SetEndPoint(string ipaddr, int port)
@@ -576,8 +599,25 @@ namespace OpenSim.Framework
576 599
577 string[] locationElements = location.Split(new char[] {','}); 600 string[] locationElements = location.Split(new char[] {','});
578 601
579 m_regionLocX = Convert.ToUInt32(locationElements[0]); 602 RegionLocX = Convert.ToUInt32(locationElements[0]);
580 m_regionLocY = Convert.ToUInt32(locationElements[1]); 603 RegionLocY = Convert.ToUInt32(locationElements[1]);
604
605 // Region size
606 // Default to legacy region size if not specified.
607 allKeys.Remove("SizeX");
608 string configSizeX = config.GetString("SizeX", Constants.RegionSize.ToString());
609 config.Set("SizeX", configSizeX);
610 RegionSizeX = Convert.ToUInt32(configSizeX);
611 allKeys.Remove("SizeY");
612 string configSizeY = config.GetString("SizeY", Constants.RegionSize.ToString());
613 config.Set("SizeY", configSizeX);
614 RegionSizeY = Convert.ToUInt32(configSizeY);
615 allKeys.Remove("SizeZ");
616 string configSizeZ = config.GetString("SizeZ", Constants.RegionHeight.ToString());
617 config.Set("SizeZ", configSizeX);
618 RegionSizeZ = Convert.ToUInt32(configSizeZ);
619
620 DoRegionSizeSanityChecks();
581 621
582 // InternalAddress 622 // InternalAddress
583 // 623 //
@@ -697,6 +737,57 @@ namespace OpenSim.Framework
697 } 737 }
698 } 738 }
699 739
740 // Make sure user specified region sizes are sane.
741 // Must be multiples of legacy region size (256).
742 private void DoRegionSizeSanityChecks()
743 {
744 if (RegionSizeX != Constants.RegionSize || RegionSizeY != Constants.RegionSize)
745 {
746 // Doing non-legacy region sizes.
747 // Enforce region size to be multiples of the legacy region size (256)
748 uint partial = RegionSizeX % Constants.RegionSize;
749 if (partial != 0)
750 {
751 RegionSizeX -= partial;
752 if (RegionSizeX == 0)
753 RegionSizeX = Constants.RegionSize;
754 m_log.ErrorFormat("{0} Region size must be multiple of {1}. Enforcing {2}.RegionSizeX={3} instead of specified {4}",
755 LogHeader, Constants.RegionSize, m_regionName, RegionSizeX, RegionSizeX + partial);
756 }
757 partial = RegionSizeY % Constants.RegionSize;
758 if (partial != 0)
759 {
760 RegionSizeY -= partial;
761 if (RegionSizeY == 0)
762 RegionSizeY = Constants.RegionSize;
763 m_log.ErrorFormat("{0} Region size must be multiple of {1}. Enforcing {2}.RegionSizeY={3} instead of specified {4}",
764 LogHeader, Constants.RegionSize, m_regionName, RegionSizeY, RegionSizeY + partial);
765 }
766
767 // Because of things in the viewer, regions MUST be square.
768 // Remove this check when viewers have been updated.
769 if (RegionSizeX != RegionSizeY)
770 {
771 uint minSize = Math.Min(RegionSizeX, RegionSizeY);
772 RegionSizeX = minSize;
773 RegionSizeY = minSize;
774 m_log.ErrorFormat("{0} Regions must be square until viewers are updated. Forcing region {1} size to <{2},{3}>",
775 LogHeader, m_regionName, RegionSizeX, RegionSizeY);
776 }
777
778 // There is a practical limit to region size.
779 if (RegionSizeX > Constants.MaximumRegionSize || RegionSizeY > Constants.MaximumRegionSize)
780 {
781 RegionSizeX = Util.Clamp<uint>(RegionSizeX, Constants.RegionSize, Constants.MaximumRegionSize);
782 RegionSizeY = Util.Clamp<uint>(RegionSizeY, Constants.RegionSize, Constants.MaximumRegionSize);
783 m_log.ErrorFormat("{0} Region dimensions must be less than {1}. Clamping {2}'s size to <{3},{4}>",
784 LogHeader, Constants.MaximumRegionSize, m_regionName, RegionSizeX, RegionSizeY);
785 }
786
787 m_log.InfoFormat("{0} Region {1} size set to <{2},{3}>", LogHeader, m_regionName, RegionSizeX, RegionSizeY);
788 }
789 }
790
700 private void WriteNiniConfig(IConfigSource source) 791 private void WriteNiniConfig(IConfigSource source)
701 { 792 {
702 IConfig config = source.Configs[RegionName]; 793 IConfig config = source.Configs[RegionName];
@@ -708,11 +799,17 @@ namespace OpenSim.Framework
708 799
709 config.Set("RegionUUID", RegionID.ToString()); 800 config.Set("RegionUUID", RegionID.ToString());
710 801
711 string location = String.Format("{0},{1}", m_regionLocX, m_regionLocY); 802 string location = String.Format("{0},{1}", RegionLocX, RegionLocY);
712 config.Set("Location", location); 803 config.Set("Location", location);
713 804
714 if (DataStore != String.Empty) 805 if (DataStore != String.Empty)
715 config.Set("Datastore", DataStore); 806 config.Set("Datastore", DataStore);
807 if (RegionSizeX != Constants.RegionSize || RegionSizeY != Constants.RegionSize)
808 {
809 config.Set("SizeX", RegionSizeX);
810 config.Set("SizeY", RegionSizeY);
811 config.Set("SizeZ", RegionSizeZ);
812 }
716 813
717 config.Set("InternalAddress", m_internalEndPoint.Address.ToString()); 814 config.Set("InternalAddress", m_internalEndPoint.Address.ToString());
718 config.Set("InternalPort", m_internalEndPoint.Port); 815 config.Set("InternalPort", m_internalEndPoint.Port);
@@ -796,10 +893,18 @@ namespace OpenSim.Framework
796 RegionID.ToString(), true); 893 RegionID.ToString(), true);
797 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, 894 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
798 "Region Name", RegionName, true); 895 "Region Name", RegionName, true);
896
799 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, 897 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
800 "Grid Location (X Axis)", m_regionLocX.ToString(), true); 898 "Grid Location (X Axis)", RegionLocX.ToString(), true);
801 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, 899 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
802 "Grid Location (Y Axis)", m_regionLocY.ToString(), true); 900 "Grid Location (Y Axis)", RegionLocY.ToString(), true);
901 configMember.addConfigurationOption("sim_size_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
902 "Size of region in X dimension", RegionSizeX.ToString(), true);
903 configMember.addConfigurationOption("sim_size_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
904 "Size of region in Y dimension", RegionSizeY.ToString(), true);
905 configMember.addConfigurationOption("sim_size_z", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
906 "Size of region in Z dimension", RegionSizeZ.ToString(), true);
907
803 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false); 908 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false);
804 configMember.addConfigurationOption("internal_ip_address", 909 configMember.addConfigurationOption("internal_ip_address",
805 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS, 910 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS,
@@ -862,10 +967,18 @@ namespace OpenSim.Framework
862 UUID.Random().ToString(), true); 967 UUID.Random().ToString(), true);
863 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, 968 configMember.addConfigurationOption("sim_name", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
864 "Region Name", "OpenSim Test", false); 969 "Region Name", "OpenSim Test", false);
970
865 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, 971 configMember.addConfigurationOption("sim_location_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
866 "Grid Location (X Axis)", "1000", false); 972 "Grid Location (X Axis)", "1000", false);
867 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32, 973 configMember.addConfigurationOption("sim_location_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
868 "Grid Location (Y Axis)", "1000", false); 974 "Grid Location (Y Axis)", "1000", false);
975 configMember.addConfigurationOption("sim_size_x", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
976 "Size of region in X dimension", Constants.RegionSize.ToString(), false);
977 configMember.addConfigurationOption("sim_size_y", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
978 "Size of region in Y dimension", Constants.RegionSize.ToString(), false);
979 configMember.addConfigurationOption("sim_size_z", ConfigurationOption.ConfigurationTypes.TYPE_UINT32,
980 "Size of region in Z dimension", Constants.RegionHeight.ToString(), false);
981
869 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false); 982 //m_configMember.addConfigurationOption("datastore", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Filename for local storage", "OpenSim.db", false);
870 configMember.addConfigurationOption("internal_ip_address", 983 configMember.addConfigurationOption("internal_ip_address",
871 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS, 984 ConfigurationOption.ConfigurationTypes.TYPE_IP_ADDRESS,
@@ -923,10 +1036,19 @@ namespace OpenSim.Framework
923 RegionName = (string) configuration_result; 1036 RegionName = (string) configuration_result;
924 break; 1037 break;
925 case "sim_location_x": 1038 case "sim_location_x":
926 m_regionLocX = (uint) configuration_result; 1039 RegionLocX = (uint) configuration_result;
927 break; 1040 break;
928 case "sim_location_y": 1041 case "sim_location_y":
929 m_regionLocY = (uint) configuration_result; 1042 RegionLocY = (uint) configuration_result;
1043 break;
1044 case "sim_size_x":
1045 RegionSizeX = (uint) configuration_result;
1046 break;
1047 case "sim_size_y":
1048 RegionSizeY = (uint) configuration_result;
1049 break;
1050 case "sim_size_z":
1051 RegionSizeZ = (uint) configuration_result;
930 break; 1052 break;
931 case "datastore": 1053 case "datastore":
932 DataStore = (string) configuration_result; 1054 DataStore = (string) configuration_result;
@@ -1010,8 +1132,13 @@ namespace OpenSim.Framework
1010 args["external_host_name"] = OSD.FromString(ExternalHostName); 1132 args["external_host_name"] = OSD.FromString(ExternalHostName);
1011 args["http_port"] = OSD.FromString(HttpPort.ToString()); 1133 args["http_port"] = OSD.FromString(HttpPort.ToString());
1012 args["server_uri"] = OSD.FromString(ServerURI); 1134 args["server_uri"] = OSD.FromString(ServerURI);
1135
1013 args["region_xloc"] = OSD.FromString(RegionLocX.ToString()); 1136 args["region_xloc"] = OSD.FromString(RegionLocX.ToString());
1014 args["region_yloc"] = OSD.FromString(RegionLocY.ToString()); 1137 args["region_yloc"] = OSD.FromString(RegionLocY.ToString());
1138 args["region_size_x"] = OSD.FromString(RegionSizeX.ToString());
1139 args["region_size_y"] = OSD.FromString(RegionSizeY.ToString());
1140 args["region_size_z"] = OSD.FromString(RegionSizeZ.ToString());
1141
1015 args["internal_ep_address"] = OSD.FromString(InternalEndPoint.Address.ToString()); 1142 args["internal_ep_address"] = OSD.FromString(InternalEndPoint.Address.ToString());
1016 args["internal_ep_port"] = OSD.FromString(InternalEndPoint.Port.ToString()); 1143 args["internal_ep_port"] = OSD.FromString(InternalEndPoint.Port.ToString());
1017 if ((RemotingAddress != null) && !RemotingAddress.Equals("")) 1144 if ((RemotingAddress != null) && !RemotingAddress.Equals(""))
@@ -1050,6 +1177,13 @@ namespace OpenSim.Framework
1050 UInt32.TryParse(args["region_yloc"].AsString(), out locy); 1177 UInt32.TryParse(args["region_yloc"].AsString(), out locy);
1051 RegionLocY = locy; 1178 RegionLocY = locy;
1052 } 1179 }
1180 if (args.ContainsKey("region_size_x"))
1181 RegionSizeX = (uint)args["region_size_x"].AsInteger();
1182 if (args.ContainsKey("region_size_y"))
1183 RegionSizeY = (uint)args["region_size_y"].AsInteger();
1184 if (args.ContainsKey("region_size_z"))
1185 RegionSizeZ = (uint)args["region_size_z"].AsInteger();
1186
1053 IPAddress ip_addr = null; 1187 IPAddress ip_addr = null;
1054 if (args["internal_ep_address"] != null) 1188 if (args["internal_ep_address"] != null)
1055 { 1189 {
diff --git a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
index d4806f1..563bcb9 100644
--- a/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/RegionLoader/Filesystem/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
index 1541a5b..ab36f10 100644
--- a/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/RegionLoader/Web/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/RegionSettings.cs b/OpenSim/Framework/RegionSettings.cs
index 47a2780..dec01ea 100644
--- a/OpenSim/Framework/RegionSettings.cs
+++ b/OpenSim/Framework/RegionSettings.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Framework
200 set { m_ObjectBonus = value; } 200 set { m_ObjectBonus = value; }
201 } 201 }
202 202
203 private int m_Maturity = 1; 203 private int m_Maturity = 0;
204 204
205 public int Maturity 205 public int Maturity
206 { 206 {
@@ -504,21 +504,14 @@ namespace OpenSim.Framework
504 set { m_TelehubEnabled = value; } 504 set { m_TelehubEnabled = value; }
505 } 505 }
506 506
507 // Connected Telehub object 507 /// <summary>
508 private UUID m_TelehubObject = UUID.Zero; 508 /// Connected Telehub object
509 public UUID TelehubObject 509 /// </summary>
510 { 510 public UUID TelehubObject { get; set; }
511 get
512 {
513 return m_TelehubObject;
514 }
515 set
516 {
517 m_TelehubObject = value;
518 }
519 }
520 511
521 // Our Connected Telehub's SpawnPoints 512 /// <summary>
513 /// Our connected Telehub's SpawnPoints
514 /// </summary>
522 public List<SpawnPoint> l_SpawnPoints = new List<SpawnPoint>(); 515 public List<SpawnPoint> l_SpawnPoints = new List<SpawnPoint>();
523 516
524 // Add a SpawnPoint 517 // Add a SpawnPoint
@@ -549,4 +542,4 @@ namespace OpenSim.Framework
549 l_SpawnPoints.Clear(); 542 l_SpawnPoints.Clear();
550 } 543 }
551 } 544 }
552} \ No newline at end of file 545}
diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs
index 537de7a..9249105 100644
--- a/OpenSim/Framework/SLUtil.cs
+++ b/OpenSim/Framework/SLUtil.cs
@@ -39,8 +39,32 @@ namespace OpenSim.Framework
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 /// <summary>
43 /// Asset types used only in OpenSim.
44 /// To avoid clashing with the code numbers used in Second Life, use only negative numbers here.
45 /// </summary>
46 public enum OpenSimAssetType : sbyte
47 {
48 Material = -2
49 }
50
51
42 #region SL / file extension / content-type conversions 52 #region SL / file extension / content-type conversions
43 53
54 /// <summary>
55 /// Returns the Enum entry corresponding to the given code, regardless of whether it belongs
56 /// to the AssetType or OpenSimAssetType enums.
57 /// </summary>
58 public static object AssetTypeFromCode(sbyte assetType)
59 {
60 if (Enum.IsDefined(typeof(OpenMetaverse.AssetType), assetType))
61 return (OpenMetaverse.AssetType)assetType;
62 else if (Enum.IsDefined(typeof(OpenSimAssetType), assetType))
63 return (OpenSimAssetType)assetType;
64 else
65 return OpenMetaverse.AssetType.Unknown;
66 }
67
44 private class TypeMapping 68 private class TypeMapping
45 { 69 {
46 private sbyte assetType; 70 private sbyte assetType;
@@ -56,12 +80,7 @@ namespace OpenSim.Framework
56 80
57 public object AssetType 81 public object AssetType
58 { 82 {
59 get { 83 get { return AssetTypeFromCode(assetType); }
60 if (Enum.IsDefined(typeof(OpenMetaverse.AssetType), assetType))
61 return (OpenMetaverse.AssetType)assetType;
62 else
63 return OpenMetaverse.AssetType.Unknown;
64 }
65 } 84 }
66 85
67 public InventoryType InventoryType 86 public InventoryType InventoryType
@@ -102,6 +121,11 @@ namespace OpenSim.Framework
102 : this((sbyte)assetType, inventoryType, contentType, null, extension) 121 : this((sbyte)assetType, inventoryType, contentType, null, extension)
103 { 122 {
104 } 123 }
124
125 public TypeMapping(OpenSimAssetType assetType, InventoryType inventoryType, string contentType, string extension)
126 : this((sbyte)assetType, inventoryType, contentType, null, extension)
127 {
128 }
105 } 129 }
106 130
107 /// <summary> 131 /// <summary>
@@ -142,7 +166,9 @@ namespace OpenSim.Framework
142 new TypeMapping(AssetType.CurrentOutfitFolder, InventoryType.Unknown, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"), 166 new TypeMapping(AssetType.CurrentOutfitFolder, InventoryType.Unknown, "application/vnd.ll.currentoutfitfolder", "currentoutfitfolder"),
143 new TypeMapping(AssetType.OutfitFolder, InventoryType.Unknown, "application/vnd.ll.outfitfolder", "outfitfolder"), 167 new TypeMapping(AssetType.OutfitFolder, InventoryType.Unknown, "application/vnd.ll.outfitfolder", "outfitfolder"),
144 new TypeMapping(AssetType.MyOutfitsFolder, InventoryType.Unknown, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"), 168 new TypeMapping(AssetType.MyOutfitsFolder, InventoryType.Unknown, "application/vnd.ll.myoutfitsfolder", "myoutfitsfolder"),
145 new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm") 169 new TypeMapping(AssetType.Mesh, InventoryType.Mesh, "application/vnd.ll.mesh", "llm"),
170
171 new TypeMapping(OpenSimAssetType.Material, InventoryType.Unknown, "application/llsd+xml", "material")
146 }; 172 };
147 173
148 private static Dictionary<sbyte, string> asset2Content; 174 private static Dictionary<sbyte, string> asset2Content;
@@ -247,12 +273,18 @@ namespace OpenSim.Framework
247 /// <returns></returns> 273 /// <returns></returns>
248 public static List<string> ParseNotecardToList(string rawInput) 274 public static List<string> ParseNotecardToList(string rawInput)
249 { 275 {
250 string[] input = rawInput.Replace("\r", "").Split('\n'); 276 string[] input;
251 int idx = 0; 277 int idx = 0;
252 int level = 0; 278 int level = 0;
253 List<string> output = new List<string>(); 279 List<string> output = new List<string>();
254 string[] words; 280 string[] words;
255 281
282 //The Linden format always ends with a } after the input data.
283 //Strip off trailing } so there is nothing after the input data.
284 int i = rawInput.LastIndexOf("}");
285 rawInput = rawInput.Remove(i, rawInput.Length-i);
286 input = rawInput.Replace("\r", "").Split('\n');
287
256 while (idx < input.Length) 288 while (idx < input.Length)
257 { 289 {
258 if (input[idx] == "{") 290 if (input[idx] == "{")
@@ -287,24 +319,18 @@ namespace OpenSim.Framework
287 break; 319 break;
288 if (words[0] == "Text") 320 if (words[0] == "Text")
289 { 321 {
290 int len = int.Parse(words[2]); 322 idx++; //Now points to first line of notecard text
291 idx++;
292 323
293 int count = -1; 324 //Number of lines in notecard.
325 int lines = input.Length - idx;
326 int line = 0;
294 327
295 while (count < len && idx < input.Length) 328 while (line < lines)
296 { 329 {
297 // int l = input[idx].Length; 330// m_log.DebugFormat("[PARSE NOTECARD]: Adding line {0}", input[idx]);
298 string ln = input[idx]; 331 output.Add(input[idx]);
299
300 int need = len-count-1;
301 if (ln.Length > need)
302 ln = ln.Substring(0, need);
303
304// m_log.DebugFormat("[PARSE NOTECARD]: Adding line {0}", ln);
305 output.Add(ln);
306 count += ln.Length + 1;
307 idx++; 332 idx++;
333 line++;
308 } 334 }
309 335
310 return output; 336 return output;
diff --git a/OpenSim/Framework/Serialization/ArchiveConstants.cs b/OpenSim/Framework/Serialization/ArchiveConstants.cs
index 0c12787..73ebfae 100644
--- a/OpenSim/Framework/Serialization/ArchiveConstants.cs
+++ b/OpenSim/Framework/Serialization/ArchiveConstants.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
32 33
33namespace OpenSim.Framework.Serialization 34namespace OpenSim.Framework.Serialization
34{ 35{
@@ -128,6 +129,7 @@ namespace OpenSim.Framework.Serialization
128 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Texture] = ASSET_EXTENSION_SEPARATOR + "texture.jp2"; 129 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.Texture] = ASSET_EXTENSION_SEPARATOR + "texture.jp2";
129 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TextureTGA] = ASSET_EXTENSION_SEPARATOR + "texture.tga"; 130 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TextureTGA] = ASSET_EXTENSION_SEPARATOR + "texture.tga";
130 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TrashFolder] = ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"; // Not sure if we'll ever see this 131 ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.TrashFolder] = ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"; // Not sure if we'll ever see this
132 ASSET_TYPE_TO_EXTENSION[(sbyte)OpenSimAssetType.Material] = ASSET_EXTENSION_SEPARATOR + "material.xml"; // Not sure if we'll ever see this
131 133
132 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "animation.bvh"] = (sbyte)AssetType.Animation; 134 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "animation.bvh"] = (sbyte)AssetType.Animation;
133 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bodypart.txt"] = (sbyte)AssetType.Bodypart; 135 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "bodypart.txt"] = (sbyte)AssetType.Bodypart;
@@ -152,6 +154,7 @@ namespace OpenSim.Framework.Serialization
152 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.jp2"] = (sbyte)AssetType.Texture; 154 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.jp2"] = (sbyte)AssetType.Texture;
153 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.tga"] = (sbyte)AssetType.TextureTGA; 155 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "texture.tga"] = (sbyte)AssetType.TextureTGA;
154 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder; 156 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "trashfolder.txt"] = (sbyte)AssetType.TrashFolder;
157 EXTENSION_TO_ASSET_TYPE[ASSET_EXTENSION_SEPARATOR + "material.xml"] = (sbyte)OpenSimAssetType.Material;
155 } 158 }
156 159
157 public static string CreateOarLandDataPath(LandData ld) 160 public static string CreateOarLandDataPath(LandData ld)
diff --git a/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs b/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs
index 88f9581..f2a6b8b 100644
--- a/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs
+++ b/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs
@@ -277,7 +277,7 @@ namespace OpenSim.Framework.Serialization.External
277 writer.WriteStartElement("GroupOwned"); 277 writer.WriteStartElement("GroupOwned");
278 writer.WriteString(inventoryItem.GroupOwned.ToString()); 278 writer.WriteString(inventoryItem.GroupOwned.ToString());
279 writer.WriteEndElement(); 279 writer.WriteEndElement();
280 if (options.ContainsKey("creators") && inventoryItem.CreatorData != null && inventoryItem.CreatorData != string.Empty) 280 if (options.ContainsKey("creators") && !string.IsNullOrEmpty(inventoryItem.CreatorData))
281 writer.WriteElementString("CreatorData", inventoryItem.CreatorData); 281 writer.WriteElementString("CreatorData", inventoryItem.CreatorData);
282 else if (options.ContainsKey("home")) 282 else if (options.ContainsKey("home"))
283 { 283 {
diff --git a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
index a8dff93..3f04148 100644
--- a/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Serialization/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 6c04c69..cbd34a2 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -86,26 +86,23 @@ namespace OpenSim.Framework.Servers
86 /// </summary> 86 /// </summary>
87 protected virtual void StartupSpecific() 87 protected virtual void StartupSpecific()
88 { 88 {
89 if (m_console == null) 89 StatsManager.SimExtraStats = new SimExtraStatsCollector();
90 return;
91
92 RegisterCommonCommands(); 90 RegisterCommonCommands();
93 91 RegisterCommonComponents(Config);
94 m_console.Commands.AddCommand("General", false, "quit", 92 }
95 "quit", 93
96 "Quit the application", HandleQuit); 94 protected override void ShutdownSpecific()
95 {
96 m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
97
98 RemovePIDFile();
97 99
98 m_console.Commands.AddCommand("General", false, "shutdown", 100 base.ShutdownSpecific();
99 "shutdown", 101
100 "Quit the application", HandleQuit); 102 Environment.Exit(0);
101 } 103 }
102 104
103 /// <summary> 105 /// <summary>
104 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
105 /// </summary>
106 public virtual void ShutdownSpecific() {}
107
108 /// <summary>
109 /// Provides a list of help topics that are available. Overriding classes should append their topics to the 106 /// Provides a list of help topics that are available. Overriding classes should append their topics to the
110 /// information returned when the base method is called. 107 /// information returned when the base method is called.
111 /// </summary> 108 /// </summary>
@@ -148,30 +145,13 @@ namespace OpenSim.Framework.Servers
148 145
149 TimeSpan timeTaken = DateTime.Now - m_startuptime; 146 TimeSpan timeTaken = DateTime.Now - m_startuptime;
150 147
151 m_log.InfoFormat( 148 MainConsole.Instance.OutputFormat(
152 "[STARTUP]: Non-script portion of startup took {0}m {1}s. PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED.", 149 "PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED. Non-script portion of startup took {0}m {1}s.",
153 timeTaken.Minutes, timeTaken.Seconds); 150 timeTaken.Minutes, timeTaken.Seconds);
154 } 151 }
155 152
156 /// <summary> 153 public string osSecret
157 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
158 /// </summary>
159 public virtual void Shutdown()
160 { 154 {
161 ShutdownSpecific();
162
163 m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
164 RemovePIDFile();
165
166 Environment.Exit(0);
167 }
168
169 private void HandleQuit(string module, string[] args)
170 {
171 Shutdown();
172 }
173
174 public string osSecret {
175 // Secret uuid for the simulator 155 // Secret uuid for the simulator
176 get { return m_osSecret; } 156 get { return m_osSecret; }
177 } 157 }
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 97035e3..7841f47 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -54,7 +54,6 @@ namespace OpenSim.Framework.Servers.HttpServer
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); 55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
56 56
57
58 /// <summary> 57 /// <summary>
59 /// This is a pending websocket request before it got an sucessful upgrade response. 58 /// This is a pending websocket request before it got an sucessful upgrade response.
60 /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to 59 /// The consumer must call handler.HandshakeAndUpgrade() to signal to the handler to
@@ -81,6 +80,11 @@ namespace OpenSim.Framework.Servers.HttpServer
81 /// </remarks> 80 /// </remarks>
82 public int RequestNumber { get; private set; } 81 public int RequestNumber { get; private set; }
83 82
83 /// <summary>
84 /// Statistic for holding number of requests processed.
85 /// </summary>
86 private Stat m_requestsProcessedStat;
87
84 private volatile int NotSocketErrors = 0; 88 private volatile int NotSocketErrors = 0;
85 public volatile bool HTTPDRunning = false; 89 public volatile bool HTTPDRunning = false;
86 90
@@ -383,6 +387,8 @@ namespace OpenSim.Framework.Servers.HttpServer
383 387
384 if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs)) 388 if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out psEvArgs))
385 { 389 {
390 psEvArgs.RequestsReceived++;
391
386 PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request); 392 PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request);
387 393
388 if (psEvArgs.Request != null) 394 if (psEvArgs.Request != null)
@@ -437,9 +443,8 @@ namespace OpenSim.Framework.Servers.HttpServer
437 } 443 }
438 } 444 }
439 445
440 public void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request) 446 private void OnHandleRequestIOThread(IHttpClientContext context, IHttpRequest request)
441 { 447 {
442
443 OSHttpRequest req = new OSHttpRequest(context, request); 448 OSHttpRequest req = new OSHttpRequest(context, request);
444 WebSocketRequestDelegate dWebSocketRequestDelegate = null; 449 WebSocketRequestDelegate dWebSocketRequestDelegate = null;
445 lock (m_WebSocketHandlers) 450 lock (m_WebSocketHandlers)
@@ -454,9 +459,8 @@ namespace OpenSim.Framework.Servers.HttpServer
454 } 459 }
455 460
456 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context); 461 OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request),context);
457 462 resp.ReuseContext = true;
458 HandleRequest(req, resp); 463 HandleRequest(req, resp);
459
460 464
461 // !!!HACK ALERT!!! 465 // !!!HACK ALERT!!!
462 // There seems to be a bug in the underlying http code that makes subsequent requests 466 // There seems to be a bug in the underlying http code that makes subsequent requests
@@ -687,7 +691,7 @@ namespace OpenSim.Framework.Servers.HttpServer
687 691
688 if (buffer != null) 692 if (buffer != null)
689 { 693 {
690 if (!response.SendChunked) 694 if (!response.SendChunked && response.ContentLength64 <= 0)
691 response.ContentLength64 = buffer.LongLength; 695 response.ContentLength64 = buffer.LongLength;
692 696
693 response.OutputStream.Write(buffer, 0, buffer.Length); 697 response.OutputStream.Write(buffer, 0, buffer.Length);
@@ -782,7 +786,7 @@ namespace OpenSim.Framework.Servers.HttpServer
782 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}", 786 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
783 RequestNumber, 787 RequestNumber,
784 Port, 788 Port,
785 (request.ContentType == null || request.ContentType == "") ? "not set" : request.ContentType, 789 string.IsNullOrEmpty(request.ContentType) ? "not set" : request.ContentType,
786 request.HttpMethod, 790 request.HttpMethod,
787 request.Url.PathAndQuery, 791 request.Url.PathAndQuery,
788 request.RemoteIPEndPoint); 792 request.RemoteIPEndPoint);
@@ -1053,7 +1057,21 @@ namespace OpenSim.Framework.Servers.HttpServer
1053 } 1057 }
1054 1058
1055 response.ContentType = "text/xml"; 1059 response.ContentType = "text/xml";
1056 responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse); 1060 using (MemoryStream outs = new MemoryStream())
1061 {
1062 using (XmlTextWriter writer = new XmlTextWriter(outs, Encoding.UTF8))
1063 {
1064 writer.Formatting = Formatting.None;
1065 XmlRpcResponseSerializer.Singleton.Serialize(writer, xmlRpcResponse);
1066 writer.Flush();
1067 outs.Flush();
1068 outs.Position = 0;
1069 using (StreamReader sr = new StreamReader(outs))
1070 {
1071 responseString = sr.ReadToEnd();
1072 }
1073 }
1074 }
1057 } 1075 }
1058 else 1076 else
1059 { 1077 {
@@ -1850,8 +1868,8 @@ namespace OpenSim.Framework.Servers.HttpServer
1850 m_httpListener2.Start(64); 1868 m_httpListener2.Start(64);
1851 1869
1852 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events 1870 // Long Poll Service Manager with 3 worker threads a 25 second timeout for no events
1853// m_PollServiceManager = new PollServiceRequestManager(this, 3, 25000);
1854 m_PollServiceManager = new PollServiceRequestManager(this, 4, 25000); 1871 m_PollServiceManager = new PollServiceRequestManager(this, 4, 25000);
1872 m_PollServiceManager.Start();
1855 HTTPDRunning = true; 1873 HTTPDRunning = true;
1856 1874
1857 //HttpListenerContext context; 1875 //HttpListenerContext context;
@@ -1870,6 +1888,21 @@ namespace OpenSim.Framework.Servers.HttpServer
1870 // useful without inbound HTTP. 1888 // useful without inbound HTTP.
1871 throw e; 1889 throw e;
1872 } 1890 }
1891
1892 m_requestsProcessedStat
1893 = new Stat(
1894 "HTTPRequestsServed",
1895 "Number of inbound HTTP requests processed",
1896 "",
1897 "requests",
1898 "httpserver",
1899 Port.ToString(),
1900 StatType.Pull,
1901 MeasuresOfInterest.AverageChangeOverTime,
1902 stat => stat.Value = RequestNumber,
1903 StatVerbosity.Debug);
1904
1905 StatsManager.RegisterStat(m_requestsProcessedStat);
1873 } 1906 }
1874 1907
1875 public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err) 1908 public void httpServerDisconnectMonitor(IHttpClientContext source, SocketError err)
@@ -1902,9 +1935,12 @@ namespace OpenSim.Framework.Servers.HttpServer
1902 public void Stop() 1935 public void Stop()
1903 { 1936 {
1904 HTTPDRunning = false; 1937 HTTPDRunning = false;
1938
1939 StatsManager.DeregisterStat(m_requestsProcessedStat);
1940
1905 try 1941 try
1906 { 1942 {
1907// m_PollServiceManager.Stop(); 1943 m_PollServiceManager.Stop();
1908 1944
1909 m_httpListener2.ExceptionThrown -= httpServerException; 1945 m_httpListener2.ExceptionThrown -= httpServerException;
1910 //m_httpListener2.DisconnectHandler = null; 1946 //m_httpListener2.DisconnectHandler = null;
@@ -1931,6 +1967,7 @@ namespace OpenSim.Framework.Servers.HttpServer
1931 1967
1932 public void RemoveHTTPHandler(string httpMethod, string path) 1968 public void RemoveHTTPHandler(string httpMethod, string path)
1933 { 1969 {
1970 if (path == null) return; // Caps module isn't loaded, tries to remove handler where path = null
1934 lock (m_HTTPHandlers) 1971 lock (m_HTTPHandlers)
1935 { 1972 {
1936 if (httpMethod != null && httpMethod.Length == 0) 1973 if (httpMethod != null && httpMethod.Length == 0)
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseOutputStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseOutputStreamHandler.cs
new file mode 100644
index 0000000..72b3065
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/BaseOutputStreamHandler.cs
@@ -0,0 +1,60 @@
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.IO;
29
30namespace OpenSim.Framework.Servers.HttpServer
31{
32 /// <summary>
33 /// Base handler for writing to an output stream
34 /// </summary>
35 /// <remarks>
36 /// Inheriting classes should override ProcessRequest() rather than Handle()
37 /// </remarks>
38 public abstract class BaseOutputStreamHandler : BaseRequestHandler, IRequestHandler
39 {
40 protected BaseOutputStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
41
42 protected BaseOutputStreamHandler(string httpMethod, string path, string name, string description)
43 : base(httpMethod, path, name, description) {}
44
45 public virtual void Handle(
46 string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
47 {
48 RequestsReceived++;
49
50 ProcessRequest(path, request, response, httpRequest, httpResponse);
51
52 RequestsHandled++;
53 }
54
55 protected virtual void ProcessRequest(
56 string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
57 {
58 }
59 }
60} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
index ae7aaf2..bbac699 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs
@@ -31,6 +31,10 @@ namespace OpenSim.Framework.Servers.HttpServer
31{ 31{
32 public abstract class BaseRequestHandler 32 public abstract class BaseRequestHandler
33 { 33 {
34 public int RequestsReceived { get; protected set; }
35
36 public int RequestsHandled { get; protected set; }
37
34 public virtual string ContentType 38 public virtual string ContentType
35 { 39 {
36 get { return "application/xml"; } 40 get { return "application/xml"; }
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
index 6342983..252cc2a 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandler.cs
@@ -29,14 +29,35 @@ using System.IO;
29 29
30namespace OpenSim.Framework.Servers.HttpServer 30namespace OpenSim.Framework.Servers.HttpServer
31{ 31{
32 /// <summary>
33 /// Base streamed request handler.
34 /// </summary>
35 /// <remarks>
36 /// Inheriting classes should override ProcessRequest() rather than Handle()
37 /// </remarks>
32 public abstract class BaseStreamHandler : BaseRequestHandler, IStreamedRequestHandler 38 public abstract class BaseStreamHandler : BaseRequestHandler, IStreamedRequestHandler
33 { 39 {
34 public abstract byte[] Handle(string path, Stream request,
35 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse);
36
37 protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {} 40 protected BaseStreamHandler(string httpMethod, string path) : this(httpMethod, path, null, null) {}
38 41
39 protected BaseStreamHandler(string httpMethod, string path, string name, string description) 42 protected BaseStreamHandler(string httpMethod, string path, string name, string description)
40 : base(httpMethod, path, name, description) {} 43 : base(httpMethod, path, name, description) {}
44
45 public virtual byte[] Handle(
46 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
47 {
48 RequestsReceived++;
49
50 byte[] result = ProcessRequest(path, request, httpRequest, httpResponse);
51
52 RequestsHandled++;
53
54 return result;
55 }
56
57 protected virtual byte[] ProcessRequest(
58 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 {
60 return null;
61 }
41 } 62 }
42} \ No newline at end of file 63} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs
new file mode 100644
index 0000000..1b88545
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/BaseStreamHandlerBasicDOSProtector.cs
@@ -0,0 +1,107 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using OpenSim.Framework;
28using System.IO;
29
30namespace OpenSim.Framework.Servers.HttpServer
31{
32 /// <summary>
33 /// BaseStreamHandlerBasicDOSProtector Base streamed request handler.
34 /// </summary>
35 /// <remarks>
36 /// Inheriting classes should override ProcessRequest() rather than Handle()
37 /// </remarks>
38 public abstract class BaseStreamHandlerBasicDOSProtector : BaseRequestHandler, IStreamedRequestHandler
39 {
40
41 private readonly BasicDosProtectorOptions _options;
42 private readonly BasicDOSProtector _dosProtector;
43
44 protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, BasicDosProtectorOptions options) : this(httpMethod, path, null, null, options) {}
45
46 protected BaseStreamHandlerBasicDOSProtector(string httpMethod, string path, string name, string description, BasicDosProtectorOptions options)
47 : base(httpMethod, path, name, description)
48 {
49 _options = options;
50 _dosProtector = new BasicDOSProtector(_options);
51 }
52
53 public virtual byte[] Handle(
54 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
55 {
56 byte[] result;
57 RequestsReceived++;
58 string clientstring = GetClientString(httpRequest);
59 string endpoint = GetRemoteAddr(httpRequest);
60 if (_dosProtector.Process(clientstring, endpoint))
61 result = ProcessRequest(path, request, httpRequest, httpResponse);
62 else
63 result = ThrottledRequest(path, request, httpRequest, httpResponse);
64 if (_options.MaxConcurrentSessions > 0)
65 _dosProtector.ProcessEnd(clientstring, endpoint);
66
67 RequestsHandled++;
68
69 return result;
70 }
71
72 protected virtual byte[] ProcessRequest(
73 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
74 {
75 return null;
76 }
77
78 protected virtual byte[] ThrottledRequest(
79 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
80 {
81 return new byte[0];
82 }
83
84
85 private string GetRemoteAddr(IOSHttpRequest httpRequest)
86 {
87 string remoteaddr = string.Empty;
88 if (httpRequest.Headers["remote_addr"] != null)
89 remoteaddr = httpRequest.Headers["remote_addr"];
90
91 return remoteaddr;
92 }
93
94 private string GetClientString(IOSHttpRequest httpRequest)
95 {
96 string clientstring = string.Empty;
97
98 if (_options.AllowXForwardedFor && httpRequest.Headers["x-forwarded-for"] != null)
99 clientstring = httpRequest.Headers["x-forwarded-for"];
100 else
101 clientstring = GetRemoteAddr(httpRequest);
102
103 return clientstring;
104
105 }
106 }
107}
diff --git a/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
index b94bfb4..1b03f54 100644
--- a/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BinaryStreamHandler.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Framework.Servers.HttpServer
45 m_method = binaryMethod; 45 m_method = binaryMethod;
46 } 46 }
47 47
48 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 48 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
49 { 49 {
50 byte[] data = ReadFully(request); 50 byte[] data = ReadFully(request);
51 string param = GetParam(path); 51 string param = GetParam(path);
diff --git a/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs
new file mode 100644
index 0000000..cd4b8ff
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/GenericHTTPBasicDOSProtector.cs
@@ -0,0 +1,119 @@
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.Collections;
29
30namespace OpenSim.Framework.Servers.HttpServer
31{
32 public class GenericHTTPDOSProtector
33 {
34 private readonly GenericHTTPMethod _normalMethod;
35 private readonly GenericHTTPMethod _throttledMethod;
36
37 private readonly BasicDosProtectorOptions _options;
38 private readonly BasicDOSProtector _dosProtector;
39
40 public GenericHTTPDOSProtector(GenericHTTPMethod normalMethod, GenericHTTPMethod throttledMethod, BasicDosProtectorOptions options)
41 {
42 _normalMethod = normalMethod;
43 _throttledMethod = throttledMethod;
44
45 _options = options;
46 _dosProtector = new BasicDOSProtector(_options);
47 }
48 public Hashtable Process(Hashtable request)
49 {
50 Hashtable process = null;
51 string clientstring= GetClientString(request);
52 string endpoint = GetRemoteAddr(request);
53 if (_dosProtector.Process(clientstring, endpoint))
54 process = _normalMethod(request);
55 else
56 process = _throttledMethod(request);
57
58 if (_options.MaxConcurrentSessions>0)
59 _dosProtector.ProcessEnd(clientstring, endpoint);
60
61 return process;
62 }
63
64 private string GetRemoteAddr(Hashtable request)
65 {
66 string remoteaddr = "";
67 if (!request.ContainsKey("headers"))
68 return remoteaddr;
69 Hashtable requestinfo = (Hashtable)request["headers"];
70 if (!requestinfo.ContainsKey("remote_addr"))
71 return remoteaddr;
72 object remote_addrobj = requestinfo["remote_addr"];
73 if (remote_addrobj != null)
74 {
75 if (!string.IsNullOrEmpty(remote_addrobj.ToString()))
76 {
77 remoteaddr = remote_addrobj.ToString();
78 }
79
80 }
81 return remoteaddr;
82 }
83
84 private string GetClientString(Hashtable request)
85 {
86 string clientstring = "";
87 if (!request.ContainsKey("headers"))
88 return clientstring;
89
90 Hashtable requestinfo = (Hashtable)request["headers"];
91 if (_options.AllowXForwardedFor && requestinfo.ContainsKey("x-forwarded-for"))
92 {
93 object str = requestinfo["x-forwarded-for"];
94 if (str != null)
95 {
96 if (!string.IsNullOrEmpty(str.ToString()))
97 {
98 return str.ToString();
99 }
100 }
101 }
102 if (!requestinfo.ContainsKey("remote_addr"))
103 return clientstring;
104
105 object remote_addrobj = requestinfo["remote_addr"];
106 if (remote_addrobj != null)
107 {
108 if (!string.IsNullOrEmpty(remote_addrobj.ToString()))
109 {
110 clientstring = remote_addrobj.ToString();
111 }
112 }
113
114 return clientstring;
115
116 }
117
118 }
119}
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
index cb5cce5..b8541cb 100644
--- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IStreamHandler.cs
@@ -32,7 +32,6 @@ namespace OpenSim.Framework.Servers.HttpServer
32{ 32{
33 public interface IRequestHandler 33 public interface IRequestHandler
34 { 34 {
35
36 /// <summary> 35 /// <summary>
37 /// Name for this handler. 36 /// Name for this handler.
38 /// </summary> 37 /// </summary>
@@ -59,6 +58,19 @@ namespace OpenSim.Framework.Servers.HttpServer
59 58
60 // Return path 59 // Return path
61 string Path { get; } 60 string Path { get; }
61
62 /// <summary>
63 /// Number of requests received by this handler
64 /// </summary>
65 int RequestsReceived { get; }
66
67 /// <summary>
68 /// Number of requests handled.
69 /// </summary>
70 /// <remarks>
71 /// Should be equal to RequestsReceived unless requested are being handled slowly or there is deadlock.
72 /// </remarks>
73 int RequestsHandled { get; }
62 } 74 }
63 75
64 public interface IStreamedRequestHandler : IRequestHandler 76 public interface IStreamedRequestHandler : IRequestHandler
@@ -69,7 +81,6 @@ namespace OpenSim.Framework.Servers.HttpServer
69 81
70 public interface IStreamHandler : IRequestHandler 82 public interface IStreamHandler : IRequestHandler
71 { 83 {
72 // Handle request stream, return byte array
73 void Handle(string path, Stream request, Stream response, IOSHttpRequest httpReqbuest, IOSHttpResponse httpResponse); 84 void Handle(string path, Stream request, Stream response, IOSHttpRequest httpReqbuest, IOSHttpResponse httpResponse);
74 } 85 }
75 86
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
index c19ac32..3fd3bf7 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs
@@ -50,25 +50,39 @@ namespace OpenSim.Framework.Servers.HttpServer
50 50
51 public enum EventType : int 51 public enum EventType : int
52 { 52 {
53 Normal = 0, 53 LongPoll = 0,
54 LslHttp = 1, 54 LslHttp = 1,
55 Inventory = 2, 55 Inventory = 2,
56 Texture = 3, 56 Texture = 3,
57 Mesh = 4 57 Mesh = 4
58 } 58 }
59 59
60 public string Url { get; set; }
61
62 /// <summary>
63 /// Number of requests received for this poll service.
64 /// </summary>
65 public int RequestsReceived { get; set; }
66
67 /// <summary>
68 /// Number of requests handled by this poll service.
69 /// </summary>
70 public int RequestsHandled { get; set; }
71
60 public PollServiceEventArgs( 72 public PollServiceEventArgs(
61 RequestMethod pRequest, 73 RequestMethod pRequest,
74 string pUrl,
62 HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents, 75 HasEventsMethod pHasEvents, GetEventsMethod pGetEvents, NoEventsMethod pNoEvents,
63 UUID pId, int pTimeOutms) 76 UUID pId, int pTimeOutms)
64 { 77 {
65 Request = pRequest; 78 Request = pRequest;
79 Url = pUrl;
66 HasEvents = pHasEvents; 80 HasEvents = pHasEvents;
67 GetEvents = pGetEvents; 81 GetEvents = pGetEvents;
68 NoEvents = pNoEvents; 82 NoEvents = pNoEvents;
69 Id = pId; 83 Id = pId;
70 TimeOutms = pTimeOutms; 84 TimeOutms = pTimeOutms;
71 Type = EventType.Normal; 85 Type = EventType.LongPoll;
72 } 86 }
73 } 87 }
74} 88}
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
index 723530a..6aa9479 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs
@@ -26,13 +26,19 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
30using System.Reflection;
31using System.Text;
29using HttpServer; 32using HttpServer;
33using log4net;
30using OpenMetaverse; 34using OpenMetaverse;
31 35
32namespace OpenSim.Framework.Servers.HttpServer 36namespace OpenSim.Framework.Servers.HttpServer
33{ 37{
34 public class PollServiceHttpRequest 38 public class PollServiceHttpRequest
35 { 39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
36 public readonly PollServiceEventArgs PollServiceArgs; 42 public readonly PollServiceEventArgs PollServiceArgs;
37 public readonly IHttpClientContext HttpContext; 43 public readonly IHttpClientContext HttpContext;
38 public readonly IHttpRequest Request; 44 public readonly IHttpRequest Request;
@@ -48,5 +54,44 @@ namespace OpenSim.Framework.Servers.HttpServer
48 RequestTime = System.Environment.TickCount; 54 RequestTime = System.Environment.TickCount;
49 RequestID = UUID.Random(); 55 RequestID = UUID.Random();
50 } 56 }
57
58 internal void DoHTTPGruntWork(BaseHttpServer server, Hashtable responsedata)
59 {
60 OSHttpResponse response
61 = new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext);
62
63 byte[] buffer = server.DoHTTPGruntWork(responsedata, response);
64
65 response.SendChunked = false;
66 response.ContentLength64 = buffer.Length;
67 response.ContentEncoding = Encoding.UTF8;
68
69 try
70 {
71 response.OutputStream.Write(buffer, 0, buffer.Length);
72 }
73 catch (Exception ex)
74 {
75 m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
76 }
77 finally
78 {
79 //response.OutputStream.Close();
80 try
81 {
82 response.OutputStream.Flush();
83 response.Send();
84
85 //if (!response.KeepAlive && response.ReuseContext)
86 // response.FreeContext();
87 }
88 catch (Exception e)
89 {
90 m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
91 }
92
93 PollServiceArgs.RequestsHandled++;
94 }
95 }
51 } 96 }
52} \ No newline at end of file 97} \ No newline at end of file
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
index 5406f00..44f7045 100644
--- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
+++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs
@@ -64,14 +64,17 @@ namespace OpenSim.Framework.Servers.HttpServer
64 m_server = pSrv; 64 m_server = pSrv;
65 m_WorkerThreadCount = pWorkerThreadCount; 65 m_WorkerThreadCount = pWorkerThreadCount;
66 m_workerThreads = new Thread[m_WorkerThreadCount]; 66 m_workerThreads = new Thread[m_WorkerThreadCount];
67 }
67 68
69 public void Start()
70 {
68 //startup worker threads 71 //startup worker threads
69 for (uint i = 0; i < m_WorkerThreadCount; i++) 72 for (uint i = 0; i < m_WorkerThreadCount; i++)
70 { 73 {
71 m_workerThreads[i] 74 m_workerThreads[i]
72 = Watchdog.StartThread( 75 = Watchdog.StartThread(
73 PoolWorkerJob, 76 PoolWorkerJob,
74 String.Format("PollServiceWorkerThread{0}", i), 77 string.Format("PollServiceWorkerThread{0}:{1}", i, m_server.Port),
75 ThreadPriority.Normal, 78 ThreadPriority.Normal,
76 false, 79 false,
77 false, 80 false,
@@ -81,7 +84,7 @@ namespace OpenSim.Framework.Servers.HttpServer
81 84
82 m_retrysThread = Watchdog.StartThread( 85 m_retrysThread = Watchdog.StartThread(
83 this.CheckRetries, 86 this.CheckRetries,
84 "PollServiceWatcherThread", 87 string.Format("PollServiceWatcherThread:{0}", m_server.Port),
85 ThreadPriority.Normal, 88 ThreadPriority.Normal,
86 false, 89 false,
87 true, 90 true,
@@ -89,7 +92,6 @@ namespace OpenSim.Framework.Servers.HttpServer
89 1000 * 60 * 10); 92 1000 * 60 * 10);
90 } 93 }
91 94
92
93 private void ReQueueEvent(PollServiceHttpRequest req) 95 private void ReQueueEvent(PollServiceHttpRequest req)
94 { 96 {
95 if (m_running) 97 if (m_running)
@@ -103,7 +105,7 @@ namespace OpenSim.Framework.Servers.HttpServer
103 { 105 {
104 if (m_running) 106 if (m_running)
105 { 107 {
106 if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.Normal) 108 if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.LongPoll)
107 { 109 {
108 m_requests.Enqueue(req); 110 m_requests.Enqueue(req);
109 } 111 }
@@ -140,13 +142,13 @@ namespace OpenSim.Framework.Servers.HttpServer
140 } 142 }
141 } 143 }
142 144
143 ~PollServiceRequestManager() 145 public void Stop()
144 { 146 {
145 m_running = false; 147 m_running = false;
146 Thread.Sleep(1000); // let the world move 148 Thread.Sleep(1000); // let the world move
147 149
148 foreach (Thread t in m_workerThreads) 150 foreach (Thread t in m_workerThreads)
149 Watchdog.AbortThread(t.ManagedThreadId); 151 Watchdog.AbortThread(t.ManagedThreadId);
150 152
151 try 153 try
152 { 154 {
@@ -205,7 +207,7 @@ namespace OpenSim.Framework.Servers.HttpServer
205 if (responsedata == null) 207 if (responsedata == null)
206 continue; 208 continue;
207 209
208 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.Normal) // This is the event queue 210 if (req.PollServiceArgs.Type == PollServiceEventArgs.EventType.LongPoll) // This is the event queue
209 { 211 {
210 try 212 try
211 { 213 {
diff --git a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
index 8e592c1..f409667 100644
--- a/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
index 07082a8..bd55657 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestDeserialiseHandler.cs
@@ -33,7 +33,7 @@ namespace OpenSim.Framework.Servers.HttpServer
33{ 33{
34 public delegate TResponse RestDeserialiseMethod<TRequest, TResponse>(TRequest request); 34 public delegate TResponse RestDeserialiseMethod<TRequest, TResponse>(TRequest request);
35 35
36 public class RestDeserialiseHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler 36 public class RestDeserialiseHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
37 where TRequest : new() 37 where TRequest : new()
38 { 38 {
39 private RestDeserialiseMethod<TRequest, TResponse> m_method; 39 private RestDeserialiseMethod<TRequest, TResponse> m_method;
@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Servers.HttpServer
48 m_method = method; 48 m_method = method;
49 } 49 }
50 50
51 public void Handle(string path, Stream request, Stream responseStream, 51 protected override void ProcessRequest(string path, Stream request, Stream responseStream,
52 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 52 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
53 { 53 {
54 TRequest deserial; 54 TRequest deserial;
diff --git a/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs b/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
index edcd134..83c9848 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestSessionService.cs
@@ -183,7 +183,7 @@ namespace OpenSim.Framework.Servers.HttpServer
183 183
184 public delegate bool CheckIdentityMethod(string sid, string aid); 184 public delegate bool CheckIdentityMethod(string sid, string aid);
185 185
186 public class RestDeserialiseSecureHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler 186 public class RestDeserialiseSecureHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
187 where TRequest : new() 187 where TRequest : new()
188 { 188 {
189 private static readonly ILog m_log 189 private static readonly ILog m_log
@@ -201,7 +201,7 @@ namespace OpenSim.Framework.Servers.HttpServer
201 m_method = method; 201 m_method = method;
202 } 202 }
203 203
204 public void Handle(string path, Stream request, Stream responseStream, 204 protected override void ProcessRequest(string path, Stream request, Stream responseStream,
205 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 205 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
206 { 206 {
207 RestSessionObject<TRequest> deserial = default(RestSessionObject<TRequest>); 207 RestSessionObject<TRequest> deserial = default(RestSessionObject<TRequest>);
@@ -237,7 +237,7 @@ namespace OpenSim.Framework.Servers.HttpServer
237 237
238 public delegate bool CheckTrustedSourceMethod(IPEndPoint peer); 238 public delegate bool CheckTrustedSourceMethod(IPEndPoint peer);
239 239
240 public class RestDeserialiseTrustedHandler<TRequest, TResponse> : BaseRequestHandler, IStreamHandler 240 public class RestDeserialiseTrustedHandler<TRequest, TResponse> : BaseOutputStreamHandler, IStreamHandler
241 where TRequest : new() 241 where TRequest : new()
242 { 242 {
243 private static readonly ILog m_log 243 private static readonly ILog m_log
@@ -260,7 +260,7 @@ namespace OpenSim.Framework.Servers.HttpServer
260 m_method = method; 260 m_method = method;
261 } 261 }
262 262
263 public void Handle(string path, Stream request, Stream responseStream, 263 protected override void ProcessRequest(string path, Stream request, Stream responseStream,
264 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 264 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
265 { 265 {
266 TRequest deserial = default(TRequest); 266 TRequest deserial = default(TRequest);
@@ -292,6 +292,5 @@ namespace OpenSim.Framework.Servers.HttpServer
292 serializer.Serialize(xmlWriter, response); 292 serializer.Serialize(xmlWriter, response);
293 } 293 }
294 } 294 }
295 } 295 }
296 296} \ No newline at end of file
297}
diff --git a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
index 1f17fee..0305dee 100644
--- a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Framework.Servers.HttpServer
48 m_restMethod = restMethod; 48 m_restMethod = restMethod;
49 } 49 }
50 50
51 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 51 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
52 { 52 {
53 Encoding encoding = Encoding.UTF8; 53 Encoding encoding = Encoding.UTF8;
54 StreamReader streamReader = new StreamReader(request, encoding); 54 StreamReader streamReader = new StreamReader(request, encoding);
diff --git a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
index ee96b47..c2925e3 100644
--- a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
@@ -28,8 +28,10 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Net;
31using System.Security.Cryptography; 32using System.Security.Cryptography;
32using System.Text; 33using System.Text;
34using System.Threading;
33using HttpServer; 35using HttpServer;
34 36
35namespace OpenSim.Framework.Servers.HttpServer 37namespace OpenSim.Framework.Servers.HttpServer
@@ -75,7 +77,7 @@ namespace OpenSim.Framework.Servers.HttpServer
75 /// <summary> 77 /// <summary>
76 /// This is a regular HTTP Request... This may be removed in the future. 78 /// This is a regular HTTP Request... This may be removed in the future.
77 /// </summary> 79 /// </summary>
78 public event RegularHttpRequestDelegate OnRegularHttpRequest; 80// public event RegularHttpRequestDelegate OnRegularHttpRequest;
79 81
80 /// <summary> 82 /// <summary>
81 /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired 83 /// When the upgrade from a HTTP request to a Websocket is completed, this will be fired
@@ -98,6 +100,8 @@ namespace OpenSim.Framework.Servers.HttpServer
98 /// </summary> 100 /// </summary>
99 public ValidateHandshake HandshakeValidateMethodOverride = null; 101 public ValidateHandshake HandshakeValidateMethodOverride = null;
100 102
103 private ManualResetEvent _receiveDone = new ManualResetEvent(false);
104
101 private OSHttpRequest _request; 105 private OSHttpRequest _request;
102 private HTTPNetworkContext _networkContext; 106 private HTTPNetworkContext _networkContext;
103 private IHttpClientContext _clientContext; 107 private IHttpClientContext _clientContext;
@@ -109,6 +113,8 @@ namespace OpenSim.Framework.Servers.HttpServer
109 private bool _closing; 113 private bool _closing;
110 private bool _upgraded; 114 private bool _upgraded;
111 private int _maxPayloadBytes = 41943040; 115 private int _maxPayloadBytes = 41943040;
116 private int _initialMsgTimeout = 0;
117 private int _defaultReadTimeout = 10000;
112 118
113 private const string HandshakeAcceptText = 119 private const string HandshakeAcceptText =
114 "HTTP/1.1 101 Switching Protocols\r\n" + 120 "HTTP/1.1 101 Switching Protocols\r\n" +
@@ -131,6 +137,7 @@ namespace OpenSim.Framework.Servers.HttpServer
131 { 137 {
132 _request = preq; 138 _request = preq;
133 _networkContext = pContext.GiveMeTheNetworkStreamIKnowWhatImDoing(); 139 _networkContext = pContext.GiveMeTheNetworkStreamIKnowWhatImDoing();
140 _networkContext.Stream.ReadTimeout = _defaultReadTimeout;
134 _clientContext = pContext; 141 _clientContext = pContext;
135 _bufferLength = bufferlen; 142 _bufferLength = bufferlen;
136 _buffer = new byte[_bufferLength]; 143 _buffer = new byte[_bufferLength];
@@ -206,6 +213,16 @@ namespace OpenSim.Framework.Servers.HttpServer
206 } 213 }
207 214
208 /// <summary> 215 /// <summary>
216 /// Set this to the maximum amount of milliseconds to wait for the first complete message to be sent or received on the websocket after upgrading
217 /// Default, it waits forever. Use this when your Websocket consuming code opens a connection and waits for a message from the other side to avoid a Denial of Service vector.
218 /// </summary>
219 public int InitialMsgTimeout
220 {
221 get { return _initialMsgTimeout; }
222 set { _initialMsgTimeout = value; }
223 }
224
225 /// <summary>
209 /// This triggers the websocket start the upgrade process 226 /// This triggers the websocket start the upgrade process
210 /// </summary> 227 /// </summary>
211 public void HandshakeAndUpgrade() 228 public void HandshakeAndUpgrade()
@@ -245,6 +262,7 @@ namespace OpenSim.Framework.Servers.HttpServer
245 string rawaccept = string.Format(HandshakeAcceptText, acceptKey); 262 string rawaccept = string.Format(HandshakeAcceptText, acceptKey);
246 SendUpgradeSuccess(rawaccept); 263 SendUpgradeSuccess(rawaccept);
247 264
265
248 } 266 }
249 else 267 else
250 { 268 {
@@ -258,6 +276,10 @@ namespace OpenSim.Framework.Servers.HttpServer
258 SendUpgradeSuccess(rawaccept); 276 SendUpgradeSuccess(rawaccept);
259 } 277 }
260 } 278 }
279 public IPEndPoint GetRemoteIPEndpoint()
280 {
281 return _request.RemoteIPEndPoint;
282 }
261 283
262 /// <summary> 284 /// <summary>
263 /// Generates a handshake response key string based on the client's 285 /// Generates a handshake response key string based on the client's
@@ -290,9 +312,16 @@ namespace OpenSim.Framework.Servers.HttpServer
290 WebSocketState socketState = new WebSocketState() { ReceivedBytes = new List<byte>(), Header = WebsocketFrameHeader.HeaderDefault(), FrameComplete = true}; 312 WebSocketState socketState = new WebSocketState() { ReceivedBytes = new List<byte>(), Header = WebsocketFrameHeader.HeaderDefault(), FrameComplete = true};
291 313
292 byte[] bhandshakeResponse = Encoding.UTF8.GetBytes(pHandshakeResponse); 314 byte[] bhandshakeResponse = Encoding.UTF8.GetBytes(pHandshakeResponse);
315
316
317
318
293 try 319 try
294 { 320 {
295 321 if (_initialMsgTimeout > 0)
322 {
323 _receiveDone.Reset();
324 }
296 // Begin reading the TCP stream before writing the Upgrade success message to the other side of the stream. 325 // Begin reading the TCP stream before writing the Upgrade success message to the other side of the stream.
297 _networkContext.Stream.BeginRead(_buffer, 0, _bufferLength, OnReceive, socketState); 326 _networkContext.Stream.BeginRead(_buffer, 0, _bufferLength, OnReceive, socketState);
298 327
@@ -303,16 +332,20 @@ namespace OpenSim.Framework.Servers.HttpServer
303 UpgradeCompletedDelegate d = OnUpgradeCompleted; 332 UpgradeCompletedDelegate d = OnUpgradeCompleted;
304 if (d != null) 333 if (d != null)
305 d(this, new UpgradeCompletedEventArgs()); 334 d(this, new UpgradeCompletedEventArgs());
335 if (_initialMsgTimeout > 0)
336 {
337 if (!_receiveDone.WaitOne(TimeSpan.FromMilliseconds(_initialMsgTimeout)))
338 Close(string.Empty);
339 }
306 } 340 }
307 catch (IOException fail) 341 catch (IOException)
308 { 342 {
309 Close(string.Empty); 343 Close(string.Empty);
310 } 344 }
311 catch (ObjectDisposedException fail) 345 catch (ObjectDisposedException)
312 { 346 {
313 Close(string.Empty); 347 Close(string.Empty);
314 } 348 }
315
316 } 349 }
317 350
318 /// <summary> 351 /// <summary>
@@ -414,8 +447,6 @@ namespace OpenSim.Framework.Servers.HttpServer
414 _socketState.Header = pheader; 447 _socketState.Header = pheader;
415 } 448 }
416 449
417
418
419 if (_socketState.FrameComplete) 450 if (_socketState.FrameComplete)
420 { 451 {
421 ProcessFrame(_socketState); 452 ProcessFrame(_socketState);
@@ -424,7 +455,6 @@ namespace OpenSim.Framework.Servers.HttpServer
424 _socketState.ExpectedBytes = 0; 455 _socketState.ExpectedBytes = 0;
425 456
426 } 457 }
427
428 } 458 }
429 } 459 }
430 else 460 else
@@ -457,8 +487,7 @@ namespace OpenSim.Framework.Servers.HttpServer
457 _socketState.ReceivedBytes.Clear(); 487 _socketState.ReceivedBytes.Clear();
458 _socketState.ExpectedBytes = 0; 488 _socketState.ExpectedBytes = 0;
459 // do some processing 489 // do some processing
460 } 490 }
461
462 } 491 }
463 } 492 }
464 if (offset > 0) 493 if (offset > 0)
@@ -477,13 +506,12 @@ namespace OpenSim.Framework.Servers.HttpServer
477 { 506 {
478 // We can't read the stream anymore... 507 // We can't read the stream anymore...
479 } 508 }
480
481 } 509 }
482 catch (IOException fail) 510 catch (IOException)
483 { 511 {
484 Close(string.Empty); 512 Close(string.Empty);
485 } 513 }
486 catch (ObjectDisposedException fail) 514 catch (ObjectDisposedException)
487 { 515 {
488 Close(string.Empty); 516 Close(string.Empty);
489 } 517 }
@@ -495,6 +523,11 @@ namespace OpenSim.Framework.Servers.HttpServer
495 /// <param name="message">the string message that is to be sent</param> 523 /// <param name="message">the string message that is to be sent</param>
496 public void SendMessage(string message) 524 public void SendMessage(string message)
497 { 525 {
526 if (_initialMsgTimeout > 0)
527 {
528 _receiveDone.Set();
529 _initialMsgTimeout = 0;
530 }
498 byte[] messagedata = Encoding.UTF8.GetBytes(message); 531 byte[] messagedata = Encoding.UTF8.GetBytes(message);
499 WebSocketFrame textMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata }; 532 WebSocketFrame textMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = messagedata };
500 textMessageFrame.Header.Opcode = WebSocketReader.OpCode.Text; 533 textMessageFrame.Header.Opcode = WebSocketReader.OpCode.Text;
@@ -505,6 +538,11 @@ namespace OpenSim.Framework.Servers.HttpServer
505 538
506 public void SendData(byte[] data) 539 public void SendData(byte[] data)
507 { 540 {
541 if (_initialMsgTimeout > 0)
542 {
543 _receiveDone.Set();
544 _initialMsgTimeout = 0;
545 }
508 WebSocketFrame dataMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = data}; 546 WebSocketFrame dataMessageFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = data};
509 dataMessageFrame.Header.IsEnd = true; 547 dataMessageFrame.Header.IsEnd = true;
510 dataMessageFrame.Header.Opcode = WebSocketReader.OpCode.Binary; 548 dataMessageFrame.Header.Opcode = WebSocketReader.OpCode.Binary;
@@ -537,6 +575,11 @@ namespace OpenSim.Framework.Servers.HttpServer
537 /// </summary> 575 /// </summary>
538 public void SendPingCheck() 576 public void SendPingCheck()
539 { 577 {
578 if (_initialMsgTimeout > 0)
579 {
580 _receiveDone.Set();
581 _initialMsgTimeout = 0;
582 }
540 WebSocketFrame pingFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = new byte[0] }; 583 WebSocketFrame pingFrame = new WebSocketFrame() { Header = WebsocketFrameHeader.HeaderDefault(), WebSocketPayload = new byte[0] };
541 pingFrame.Header.Opcode = WebSocketReader.OpCode.Ping; 584 pingFrame.Header.Opcode = WebSocketReader.OpCode.Ping;
542 pingFrame.Header.IsEnd = true; 585 pingFrame.Header.IsEnd = true;
@@ -550,6 +593,11 @@ namespace OpenSim.Framework.Servers.HttpServer
550 /// <param name="message"></param> 593 /// <param name="message"></param>
551 public void Close(string message) 594 public void Close(string message)
552 { 595 {
596 if (_initialMsgTimeout > 0)
597 {
598 _receiveDone.Set();
599 _initialMsgTimeout = 0;
600 }
553 if (_networkContext == null) 601 if (_networkContext == null)
554 return; 602 return;
555 if (_networkContext.Stream != null) 603 if (_networkContext.Stream != null)
@@ -589,7 +637,11 @@ namespace OpenSim.Framework.Servers.HttpServer
589 WebSocketReader.Mask(psocketState.Header.Mask, unmask); 637 WebSocketReader.Mask(psocketState.Header.Mask, unmask);
590 psocketState.ReceivedBytes = new List<byte>(unmask); 638 psocketState.ReceivedBytes = new List<byte>(unmask);
591 } 639 }
592 640 if (psocketState.Header.Opcode != WebSocketReader.OpCode.Continue && _initialMsgTimeout > 0)
641 {
642 _receiveDone.Set();
643 _initialMsgTimeout = 0;
644 }
593 switch (psocketState.Header.Opcode) 645 switch (psocketState.Header.Opcode)
594 { 646 {
595 case WebSocketReader.OpCode.Ping: 647 case WebSocketReader.OpCode.Ping:
@@ -702,6 +754,11 @@ namespace OpenSim.Framework.Servers.HttpServer
702 } 754 }
703 public void Dispose() 755 public void Dispose()
704 { 756 {
757 if (_initialMsgTimeout > 0)
758 {
759 _receiveDone.Set();
760 _initialMsgTimeout = 0;
761 }
705 if (_networkContext != null && _networkContext.Stream != null) 762 if (_networkContext != null && _networkContext.Stream != null)
706 { 763 {
707 if (_networkContext.Stream.CanWrite) 764 if (_networkContext.Stream.CanWrite)
diff --git a/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs b/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs
new file mode 100644
index 0000000..f212208
--- /dev/null
+++ b/OpenSim/Framework/Servers/HttpServer/XmlRpcBasicDOSProtector.cs
@@ -0,0 +1,91 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Net;
29using Nwc.XmlRpc;
30using OpenSim.Framework;
31
32
33namespace OpenSim.Framework.Servers.HttpServer
34{
35 public class XmlRpcBasicDOSProtector
36 {
37 private readonly XmlRpcMethod _normalMethod;
38 private readonly XmlRpcMethod _throttledMethod;
39
40 private readonly BasicDosProtectorOptions _options;
41 private readonly BasicDOSProtector _dosProtector;
42
43 public XmlRpcBasicDOSProtector(XmlRpcMethod normalMethod, XmlRpcMethod throttledMethod,BasicDosProtectorOptions options)
44 {
45 _normalMethod = normalMethod;
46 _throttledMethod = throttledMethod;
47
48 _options = options;
49 _dosProtector = new BasicDOSProtector(_options);
50
51 }
52 public XmlRpcResponse Process(XmlRpcRequest request, IPEndPoint client)
53 {
54
55 XmlRpcResponse resp = null;
56 string clientstring = GetClientString(request, client);
57 string endpoint = GetEndPoint(request, client);
58 if (_dosProtector.Process(clientstring, endpoint))
59 resp = _normalMethod(request, client);
60 else
61 resp = _throttledMethod(request, client);
62 if (_options.MaxConcurrentSessions > 0)
63 _dosProtector.ProcessEnd(clientstring, endpoint);
64 return resp;
65 }
66
67 private string GetClientString(XmlRpcRequest request, IPEndPoint client)
68 {
69 string clientstring;
70 if (_options.AllowXForwardedFor && request.Params.Count > 3)
71 {
72 object headerstr = request.Params[3];
73 if (headerstr != null && !string.IsNullOrEmpty(headerstr.ToString()))
74 clientstring = request.Params[3].ToString();
75 else
76 clientstring = client.Address.ToString();
77 }
78 else
79 clientstring = client.Address.ToString();
80 return clientstring;
81 }
82
83 private string GetEndPoint(XmlRpcRequest request, IPEndPoint client)
84 {
85 return client.Address.ToString();
86 }
87
88 }
89
90
91}
diff --git a/OpenSim/Framework/Servers/MainServer.cs b/OpenSim/Framework/Servers/MainServer.cs
index cfd34bb..57931d4 100644
--- a/OpenSim/Framework/Servers/MainServer.cs
+++ b/OpenSim/Framework/Servers/MainServer.cs
@@ -121,12 +121,14 @@ namespace OpenSim.Framework.Servers
121 + " level >= 2 then long 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" 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" 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" 124 + " level >= 5 then a sample from the beginning of the data is logged.\n"
125 + " level >= 6 then the entire incoming data is logged.\n" 125 + " level >= 6 then the entire data is logged.\n"
126 + " no level is specified then the current level is returned.\n\n" 126 + " no level is specified then the current level is returned.\n\n"
127 + "If out or all and\n" 127 + "If out or all and\n"
128 + " level >= 3 then short notices about all outgoing requests going through WebUtil are logged.\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", 129 + " level >= 4 then the time taken to fulfill the request is logged.\n"
130 + " level >= 5 then a sample from the beginning of the data is logged.\n"
131 + " level >= 6 then the entire data is logged.\n",
130 HandleDebugHttpCommand); 132 HandleDebugHttpCommand);
131 } 133 }
132 134
@@ -283,7 +285,12 @@ namespace OpenSim.Framework.Servers
283 public static bool RemoveHttpServer(uint port) 285 public static bool RemoveHttpServer(uint port)
284 { 286 {
285 lock (m_Servers) 287 lock (m_Servers)
288 {
289 if (instance != null && instance.Port == port)
290 instance = null;
291
286 return m_Servers.Remove(port); 292 return m_Servers.Remove(port);
293 }
287 } 294 }
288 295
289 /// <summary> 296 /// <summary>
diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs
index 1ff8aca..7108314 100644
--- a/OpenSim/Framework/Servers/ServerBase.cs
+++ b/OpenSim/Framework/Servers/ServerBase.cs
@@ -62,6 +62,8 @@ namespace OpenSim.Framework.Servers
62 62
63 protected string m_pidFile = String.Empty; 63 protected string m_pidFile = String.Empty;
64 64
65 protected ServerStatsCollector m_serverStatsCollector;
66
65 /// <summary> 67 /// <summary>
66 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc. 68 /// Server version information. Usually VersionInfo + information about git commit, operating system, etc.
67 /// </summary> 69 /// </summary>
@@ -76,6 +78,11 @@ namespace OpenSim.Framework.Servers
76 78
77 protected void CreatePIDFile(string path) 79 protected void CreatePIDFile(string path)
78 { 80 {
81 if (File.Exists(path))
82 m_log.ErrorFormat(
83 "[SERVER BASE]: Previous pid file {0} still exists on startup. Possibly previously unclean shutdown.",
84 path);
85
79 try 86 try
80 { 87 {
81 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString(); 88 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
@@ -239,7 +246,7 @@ namespace OpenSim.Framework.Servers
239 "Show thread status", HandleShow); 246 "Show thread status", HandleShow);
240 247
241 m_console.Commands.AddCommand( 248 m_console.Commands.AddCommand(
242 "General", false, "threads abort", 249 "Debug", false, "threads abort",
243 "threads abort <thread-id>", 250 "threads abort <thread-id>",
244 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort); 251 "Abort a managed thread. Use \"show threads\" to find possible threads.", HandleThreadsAbort);
245 252
@@ -249,11 +256,180 @@ namespace OpenSim.Framework.Servers
249 "Show thread status. Synonym for \"show threads\"", 256 "Show thread status. Synonym for \"show threads\"",
250 (string module, string[] args) => Notice(GetThreadsReport())); 257 (string module, string[] args) => Notice(GetThreadsReport()));
251 258
259 m_console.Commands.AddCommand (
260 "Debug", false, "debug comms set",
261 "debug comms set serialosdreq true|false",
262 "Set comms parameters. For debug purposes.",
263 HandleDebugCommsSet);
264
265 m_console.Commands.AddCommand (
266 "Debug", false, "debug comms status",
267 "debug comms status",
268 "Show current debug comms parameters.",
269 HandleDebugCommsStatus);
270
271 m_console.Commands.AddCommand (
272 "Debug", false, "debug threadpool set",
273 "debug threadpool set worker|iocp min|max <n>",
274 "Set threadpool parameters. For debug purposes.",
275 HandleDebugThreadpoolSet);
276
277 m_console.Commands.AddCommand (
278 "Debug", false, "debug threadpool status",
279 "debug threadpool status",
280 "Show current debug threadpool parameters.",
281 HandleDebugThreadpoolStatus);
282
252 m_console.Commands.AddCommand( 283 m_console.Commands.AddCommand(
253 "General", false, "force gc", 284 "Debug", false, "force gc",
254 "force gc", 285 "force gc",
255 "Manually invoke runtime garbage collection. For debugging purposes", 286 "Manually invoke runtime garbage collection. For debugging purposes",
256 HandleForceGc); 287 HandleForceGc);
288
289 m_console.Commands.AddCommand(
290 "General", false, "quit",
291 "quit",
292 "Quit the application", (mod, args) => Shutdown());
293
294 m_console.Commands.AddCommand(
295 "General", false, "shutdown",
296 "shutdown",
297 "Quit the application", (mod, args) => Shutdown());
298
299 ChecksManager.RegisterConsoleCommands(m_console);
300 StatsManager.RegisterConsoleCommands(m_console);
301 }
302
303 public void RegisterCommonComponents(IConfigSource configSource)
304 {
305 IConfig networkConfig = configSource.Configs["Network"];
306
307 if (networkConfig != null)
308 {
309 WebUtil.SerializeOSDRequestsPerEndpoint = networkConfig.GetBoolean("SerializeOSDRequests", false);
310 }
311
312 m_serverStatsCollector = new ServerStatsCollector();
313 m_serverStatsCollector.Initialise(configSource);
314 m_serverStatsCollector.Start();
315 }
316
317 private void HandleDebugCommsStatus(string module, string[] args)
318 {
319 Notice("serialosdreq is {0}", WebUtil.SerializeOSDRequestsPerEndpoint);
320 }
321
322 private void HandleDebugCommsSet(string module, string[] args)
323 {
324 if (args.Length != 5)
325 {
326 Notice("Usage: debug comms set serialosdreq true|false");
327 return;
328 }
329
330 if (args[3] != "serialosdreq")
331 {
332 Notice("Usage: debug comms set serialosdreq true|false");
333 return;
334 }
335
336 bool setSerializeOsdRequests;
337
338 if (!ConsoleUtil.TryParseConsoleBool(m_console, args[4], out setSerializeOsdRequests))
339 return;
340
341 WebUtil.SerializeOSDRequestsPerEndpoint = setSerializeOsdRequests;
342
343 Notice("serialosdreq is now {0}", setSerializeOsdRequests);
344 }
345
346 private void HandleDebugThreadpoolStatus(string module, string[] args)
347 {
348 int workerThreads, iocpThreads;
349
350 ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
351 Notice("Min worker threads: {0}", workerThreads);
352 Notice("Min IOCP threads: {0}", iocpThreads);
353
354 ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
355 Notice("Max worker threads: {0}", workerThreads);
356 Notice("Max IOCP threads: {0}", iocpThreads);
357
358 ThreadPool.GetAvailableThreads(out workerThreads, out iocpThreads);
359 Notice("Available worker threads: {0}", workerThreads);
360 Notice("Available IOCP threads: {0}", iocpThreads);
361 }
362
363 private void HandleDebugThreadpoolSet(string module, string[] args)
364 {
365 if (args.Length != 6)
366 {
367 Notice("Usage: debug threadpool set worker|iocp min|max <n>");
368 return;
369 }
370
371 int newThreads;
372
373 if (!ConsoleUtil.TryParseConsoleInt(m_console, args[5], out newThreads))
374 return;
375
376 string poolType = args[3];
377 string bound = args[4];
378
379 bool fail = false;
380 int workerThreads, iocpThreads;
381
382 if (poolType == "worker")
383 {
384 if (bound == "min")
385 {
386 ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
387
388 if (!ThreadPool.SetMinThreads(newThreads, iocpThreads))
389 fail = true;
390 }
391 else
392 {
393 ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
394
395 if (!ThreadPool.SetMaxThreads(newThreads, iocpThreads))
396 fail = true;
397 }
398 }
399 else
400 {
401 if (bound == "min")
402 {
403 ThreadPool.GetMinThreads(out workerThreads, out iocpThreads);
404
405 if (!ThreadPool.SetMinThreads(workerThreads, newThreads))
406 fail = true;
407 }
408 else
409 {
410 ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
411
412 if (!ThreadPool.SetMaxThreads(workerThreads, newThreads))
413 fail = true;
414 }
415 }
416
417 if (fail)
418 {
419 Notice("ERROR: Could not set {0} {1} threads to {2}", poolType, bound, newThreads);
420 }
421 else
422 {
423 int minWorkerThreads, maxWorkerThreads, minIocpThreads, maxIocpThreads;
424
425 ThreadPool.GetMinThreads(out minWorkerThreads, out minIocpThreads);
426 ThreadPool.GetMaxThreads(out maxWorkerThreads, out maxIocpThreads);
427
428 Notice("Min worker threads now {0}", minWorkerThreads);
429 Notice("Min IOCP threads now {0}", minIocpThreads);
430 Notice("Max worker threads now {0}", maxWorkerThreads);
431 Notice("Max IOCP threads now {0}", maxIocpThreads);
432 }
257 } 433 }
258 434
259 private void HandleForceGc(string module, string[] args) 435 private void HandleForceGc(string module, string[] args)
@@ -641,7 +817,68 @@ namespace OpenSim.Framework.Servers
641 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); 817 sb.AppendFormat("Total threads active: {0}\n\n", totalThreads);
642 818
643 sb.Append("Main threadpool (excluding script engine pools)\n"); 819 sb.Append("Main threadpool (excluding script engine pools)\n");
644 sb.Append(Util.GetThreadPoolReport()); 820 sb.Append(GetThreadPoolReport());
821
822 return sb.ToString();
823 }
824
825 /// <summary>
826 /// Get a thread pool report.
827 /// </summary>
828 /// <returns></returns>
829 public static string GetThreadPoolReport()
830 {
831 string threadPoolUsed = null;
832 int maxThreads = 0;
833 int minThreads = 0;
834 int allocatedThreads = 0;
835 int inUseThreads = 0;
836 int waitingCallbacks = 0;
837 int completionPortThreads = 0;
838
839 StringBuilder sb = new StringBuilder();
840 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
841 {
842 STPInfo stpi = Util.GetSmartThreadPoolInfo();
843
844 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
845 if (stpi != null)
846 {
847 threadPoolUsed = "SmartThreadPool";
848 maxThreads = stpi.MaxThreads;
849 minThreads = stpi.MinThreads;
850 inUseThreads = stpi.InUseThreads;
851 allocatedThreads = stpi.ActiveThreads;
852 waitingCallbacks = stpi.WaitingCallbacks;
853 }
854 }
855 else if (
856 Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem
857 || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
858 {
859 threadPoolUsed = "BuiltInThreadPool";
860 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
861 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
862 int availableThreads;
863 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
864 inUseThreads = maxThreads - availableThreads;
865 allocatedThreads = -1;
866 waitingCallbacks = -1;
867 }
868
869 if (threadPoolUsed != null)
870 {
871 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
872 sb.AppendFormat("Max threads : {0}\n", maxThreads);
873 sb.AppendFormat("Min threads : {0}\n", minThreads);
874 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
875 sb.AppendFormat("In use threads : {0}\n", inUseThreads);
876 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
877 }
878 else
879 {
880 sb.AppendFormat("Thread pool not used\n");
881 }
645 882
646 return sb.ToString(); 883 return sb.ToString();
647 } 884 }
@@ -693,5 +930,16 @@ namespace OpenSim.Framework.Servers
693 if (m_console != null) 930 if (m_console != null)
694 m_console.OutputFormat(format, components); 931 m_console.OutputFormat(format, components);
695 } 932 }
933
934 public virtual void Shutdown()
935 {
936 m_serverStatsCollector.Close();
937 ShutdownSpecific();
938 }
939
940 /// <summary>
941 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
942 /// </summary>
943 protected virtual void ShutdownSpecific() {}
696 } 944 }
697} 945}
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
index 737c14d..33b1366 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.6CM"; 32 private const string VERSION_NUMBER = "0.8.0CM";
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/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs
index 574ee56..2ec4bd1 100644
--- a/OpenSim/Framework/TaskInventoryItem.cs
+++ b/OpenSim/Framework/TaskInventoryItem.cs
@@ -124,7 +124,7 @@ namespace OpenSim.Framework
124 { 124 {
125 get 125 get
126 { 126 {
127 if (_creatorData != null && _creatorData != string.Empty) 127 if (!string.IsNullOrEmpty(_creatorData))
128 return _creatorID.ToString() + ';' + _creatorData; 128 return _creatorID.ToString() + ';' + _creatorData;
129 else 129 else
130 return _creatorID.ToString(); 130 return _creatorID.ToString();
diff --git a/OpenSim/Framework/Tests/LocationTest.cs b/OpenSim/Framework/Tests/LocationTest.cs
index a56ecb4..3d5d1d2 100644
--- a/OpenSim/Framework/Tests/LocationTest.cs
+++ b/OpenSim/Framework/Tests/LocationTest.cs
@@ -51,21 +51,28 @@ namespace OpenSim.Framework.Tests
51 [Test] 51 [Test]
52 public void locationXYRegionHandle() 52 public void locationXYRegionHandle()
53 { 53 {
54 Location TestLocation1 = new Location(256000,256000); 54 Location TestLocation1 = new Location(255000,256000);
55 Location TestLocation2 = new Location(1099511628032000); 55 Location TestLocation2 = new Location(1095216660736000);
56 Assert.That(TestLocation1 == TestLocation2); 56 Assert.That(TestLocation1 == TestLocation2);
57 57
58 Assert.That(TestLocation2.X == 256000 && TestLocation2.Y == 256000, "Test xy location doesn't match regionhandle provided"); 58 Assert.That(TestLocation1.X == 255000 && TestLocation1.Y == 256000, "Test xy location doesn't match position in the constructor");
59 Assert.That(TestLocation2.X == 255000 && TestLocation2.Y == 256000, "Test xy location doesn't match regionhandle provided");
59 60
60 Assert.That(TestLocation2.RegionHandle == 1099511628032000, 61 Assert.That(TestLocation2.RegionHandle == 1095216660736000,
61 "Location RegionHandle Property didn't match regionhandle provided in constructor"); 62 "Location RegionHandle Property didn't match regionhandle provided in constructor");
62 63
64 ulong RegionHandle = TestLocation1.RegionHandle;
65 Assert.That(RegionHandle.Equals(1095216660736000), "Equals(regionhandle) failed to match the position in the constructor");
63 66
64 TestLocation1 = new Location(256001, 256001); 67 TestLocation2 = new Location(RegionHandle);
65 TestLocation2 = new Location(1099511628032000); 68 Assert.That(TestLocation2.Equals(255000, 256000), "Decoded regionhandle failed to match the original position in the constructor");
69
70
71 TestLocation1 = new Location(255001, 256001);
72 TestLocation2 = new Location(1095216660736000);
66 Assert.That(TestLocation1 != TestLocation2); 73 Assert.That(TestLocation1 != TestLocation2);
67 74
68 Assert.That(TestLocation1.Equals(256001, 256001), "Equals(x,y) failed to match the position in the constructor"); 75 Assert.That(TestLocation1.Equals(255001, 256001), "Equals(x,y) failed to match the position in the constructor");
69 76
70 Assert.That(TestLocation2.GetHashCode() == (TestLocation2.X.GetHashCode() ^ TestLocation2.Y.GetHashCode()), "GetHashCode failed to produce the expected hashcode"); 77 Assert.That(TestLocation2.GetHashCode() == (TestLocation2.X.GetHashCode() ^ TestLocation2.Y.GetHashCode()), "GetHashCode failed to produce the expected hashcode");
71 78
diff --git a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
index 0fbdaf3..08f2af5 100644
--- a/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
+++ b/OpenSim/Framework/Tests/MundaneFrameworkTests.cs
@@ -100,7 +100,7 @@ namespace OpenSim.Framework.Tests
100 cadu.AVHeight = Size1.Z; 100 cadu.AVHeight = Size1.Z;
101 101
102 AgentPosition position2 = new AgentPosition(); 102 AgentPosition position2 = new AgentPosition();
103 position2.CopyFrom(cadu); 103 position2.CopyFrom(cadu, position1.SessionID);
104 104
105 Assert.IsTrue( 105 Assert.IsTrue(
106 position2.AgentID == position1.AgentID 106 position2.AgentID == position1.AgentID
diff --git a/OpenSim/Framework/Tests/UtilTest.cs b/OpenSim/Framework/Tests/UtilTest.cs
index 11ca068..3b7f252 100644
--- a/OpenSim/Framework/Tests/UtilTest.cs
+++ b/OpenSim/Framework/Tests/UtilTest.cs
@@ -282,5 +282,87 @@ namespace OpenSim.Framework.Tests
282 String.Format("Incorrect InventoryType mapped from Content-Type {0}", invcontenttypes[i])); 282 String.Format("Incorrect InventoryType mapped from Content-Type {0}", invcontenttypes[i]));
283 } 283 }
284 } 284 }
285
286 [Test]
287 public void FakeParcelIDTests()
288 {
289 byte[] hexBytes8 = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 };
290 byte[] hexBytes16 = {
291 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
292 0x77, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f };
293 UInt64 var64Bit = (UInt64)0xfedcba9876543210;
294
295 //Region handle is for location 255000,256000.
296 ulong regionHandle1 = 1095216660736000;
297 uint x1 = 100;
298 uint y1 = 200;
299 uint z1 = 22;
300 ulong regionHandle2;
301 uint x2, y2, z2;
302 UUID fakeParcelID1, fakeParcelID2, uuid;
303
304 ulong bigInt64 = Util.BytesToUInt64Big(hexBytes8);
305 Assert.AreEqual(var64Bit, bigInt64,
306 "BytesToUint64Bit conversion of 8 bytes to UInt64 failed.");
307
308 //Test building and decoding using some typical input values
309 fakeParcelID1 = Util.BuildFakeParcelID(regionHandle1, x1, y1);
310 Util.ParseFakeParcelID(fakeParcelID1, out regionHandle2, out x2, out y2);
311 Assert.AreEqual(regionHandle1, regionHandle2,
312 "region handle decoded from FakeParcelID wth X/Y failed.");
313 Assert.AreEqual(x1, x2,
314 "X coordinate decoded from FakeParcelID wth X/Y failed.");
315 Assert.AreEqual(y1, y2,
316 "Y coordinate decoded from FakeParcelID wth X/Y failed.");
317
318 fakeParcelID1 = Util.BuildFakeParcelID(regionHandle1, x1, y1, z1);
319 Util.ParseFakeParcelID(fakeParcelID1, out regionHandle2, out x2, out y2, out z2);
320 Assert.AreEqual(regionHandle1, regionHandle2,
321 "region handle decoded from FakeParcelID with X/Y/Z failed.");
322 Assert.AreEqual(x1, x2,
323 "X coordinate decoded from FakeParcelID with X/Y/Z failed.");
324 Assert.AreEqual(y1, y2,
325 "Y coordinate decoded from FakeParcelID with X/Y/Z failed.");
326 Assert.AreEqual(z1, z2,
327 "Z coordinate decoded from FakeParcelID with X/Y/Z failed.");
328
329 //Do some more extreme tests to check the encoding and decoding
330 x1 = 0x55aa;
331 y1 = 0x9966;
332 z1 = 0x5a96;
333
334 fakeParcelID1 = Util.BuildFakeParcelID(var64Bit, x1, y1);
335 Util.ParseFakeParcelID(fakeParcelID1, out regionHandle2, out x2, out y2);
336 Assert.AreEqual(var64Bit, regionHandle2,
337 "region handle decoded from FakeParcelID with X/Y/Z failed.");
338 Assert.AreEqual(x1, x2,
339 "X coordinate decoded from FakeParcelID with X/Y/Z failed.");
340 Assert.AreEqual(y1, y2,
341 "Y coordinate decoded from FakeParcelID with X/Y/Z failed.");
342
343 fakeParcelID1 = Util.BuildFakeParcelID(var64Bit, x1, y1, z1);
344 Util.ParseFakeParcelID(fakeParcelID1, out regionHandle2, out x2, out y2, out z2);
345 Assert.AreEqual(var64Bit, regionHandle2,
346 "region handle decoded from FakeParcelID with X/Y/Z failed.");
347 Assert.AreEqual(x1, x2,
348 "X coordinate decoded from FakeParcelID with X/Y/Z failed.");
349 Assert.AreEqual(y1, y2,
350 "Y coordinate decoded from FakeParcelID with X/Y/Z failed.");
351 Assert.AreEqual(z1, z2,
352 "Z coordinate decoded from FakeParcelID with X/Y/Z failed.");
353
354
355 x1 = 64;
356 y1 = 192;
357 fakeParcelID1 = Util.BuildFakeParcelID(regionHandle1, x1, y1);
358 Util.FakeParcelIDToGlobalPosition(fakeParcelID1, out x2, out y2);
359 Assert.AreEqual(255000+x1, x2,
360 "Global X coordinate decoded from regionHandle failed.");
361 Assert.AreEqual(256000+y1, y2,
362 "Global Y coordinate decoded from regionHandle failed.");
363
364 uuid = new UUID("00dd0700-00d1-0700-3800-000032000000");
365 Util.FakeParcelIDToGlobalPosition(uuid, out x2, out y2);
366 }
285 } 367 }
286} 368}
diff --git a/OpenSim/Framework/UserProfiles.cs b/OpenSim/Framework/UserProfiles.cs
new file mode 100644
index 0000000..6133591
--- /dev/null
+++ b/OpenSim/Framework/UserProfiles.cs
@@ -0,0 +1,117 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenMetaverse;
30
31namespace OpenSim.Framework
32{
33 public class UserClassifiedAdd
34 {
35 public UUID ClassifiedId = UUID.Zero;
36 public UUID CreatorId = UUID.Zero;
37 public int CreationDate = 0;
38 public int ExpirationDate = 0;
39 public int Category = 0;
40 public string Name = string.Empty;
41 public string Description = string.Empty;
42 public UUID ParcelId = UUID.Zero;
43 public int ParentEstate = 0;
44 public UUID SnapshotId = UUID.Zero;
45 public string SimName = string.Empty;
46 public string GlobalPos = "<0,0,0>";
47 public string ParcelName = string.Empty;
48 public byte Flags = 0;
49 public int Price = 0;
50 }
51
52 public class UserProfileProperties
53 {
54 public UUID UserId = UUID.Zero;
55 public UUID PartnerId = UUID.Zero;
56 public bool PublishProfile = false;
57 public bool PublishMature = false;
58 public string WebUrl = string.Empty;
59 public int WantToMask = 0;
60 public string WantToText = string.Empty;
61 public int SkillsMask = 0;
62 public string SkillsText = string.Empty;
63 public string Language = string.Empty;
64 public UUID ImageId = UUID.Zero;
65 public string AboutText = string.Empty;
66 public UUID FirstLifeImageId = UUID.Zero;
67 public string FirstLifeText = string.Empty;
68 }
69
70 public class UserProfilePick
71 {
72 public UUID PickId = UUID.Zero;
73 public UUID CreatorId = UUID.Zero;
74 public bool TopPick = false;
75 public string Name = string.Empty;
76 public string OriginalName = string.Empty;
77 public string Desc = string.Empty;
78 public UUID ParcelId = UUID.Zero;
79 public UUID SnapshotId = UUID.Zero;
80 public string User = string.Empty;
81 public string SimName = string.Empty;
82 public string GlobalPos = "<0,0,0>";
83 public int SortOrder = 0;
84 public bool Enabled = false;
85 }
86
87 public class UserProfileNotes
88 {
89 public UUID UserId;
90 public UUID TargetId;
91 public string Notes;
92 }
93
94 public class UserAccountProperties
95 {
96 public string EmailAddress = string.Empty;
97 public string Firstname = string.Empty;
98 public string LastName = string.Empty;
99 public string Password = string.Empty;
100 public string UserId = string.Empty;
101 }
102
103 public class UserAccountAuth
104 {
105 public string UserId = UUID.Zero.ToString();
106 public string Password = string.Empty;
107 }
108
109 public class UserAppData
110 {
111 public string TagId = string.Empty;
112 public string DataKey = string.Empty;
113 public string UserId = UUID.Zero.ToString();
114 public string DataVal = string.Empty;
115 }
116}
117
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 557f38e..1775fef 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -89,9 +89,30 @@ namespace OpenSim.Framework
89 } 89 }
90 90
91 /// <summary> 91 /// <summary>
92 /// Class for delivering SmartThreadPool statistical information
93 /// </summary>
94 /// <remarks>
95 /// We do it this way so that we do not directly expose STP.
96 /// </remarks>
97 public class STPInfo
98 {
99 public string Name { get; set; }
100 public STPStartInfo STPStartInfo { get; set; }
101 public WIGStartInfo WIGStartInfo { get; set; }
102 public bool IsIdle { get; set; }
103 public bool IsShuttingDown { get; set; }
104 public int MaxThreads { get; set; }
105 public int MinThreads { get; set; }
106 public int InUseThreads { get; set; }
107 public int ActiveThreads { get; set; }
108 public int WaitingCallbacks { get; set; }
109 public int MaxConcurrentWorkItems { get; set; }
110 }
111
112 /// <summary>
92 /// Miscellaneous utility functions 113 /// Miscellaneous utility functions
93 /// </summary> 114 /// </summary>
94 public class Util 115 public static class Util
95 { 116 {
96 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 117 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
97 118
@@ -109,7 +130,7 @@ namespace OpenSim.Framework
109 private static SmartThreadPool m_ThreadPool; 130 private static SmartThreadPool m_ThreadPool;
110 131
111 // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC. 132 // Unix-epoch starts at January 1st 1970, 00:00:00 UTC. And all our times in the server are (or at least should be) in UTC.
112 private static readonly DateTime unixEpoch = 133 public static readonly DateTime UnixEpoch =
113 DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime(); 134 DateTime.ParseExact("1970-01-01 00:00:00 +0", "yyyy-MM-dd hh:mm:ss z", DateTimeFormatInfo.InvariantInfo).ToUniversalTime();
114 135
115 private static readonly string rawUUIDPattern 136 private static readonly string rawUUIDPattern
@@ -120,6 +141,11 @@ namespace OpenSim.Framework
120 public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool; 141 public static FireAndForgetMethod DefaultFireAndForgetMethod = FireAndForgetMethod.SmartThreadPool;
121 public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod; 142 public static FireAndForgetMethod FireAndForgetMethod = DefaultFireAndForgetMethod;
122 143
144 public static bool IsPlatformMono
145 {
146 get { return Type.GetType("Mono.Runtime") != null; }
147 }
148
123 /// <summary> 149 /// <summary>
124 /// Gets the name of the directory where the current running executable 150 /// Gets the name of the directory where the current running executable
125 /// is located 151 /// is located
@@ -307,6 +333,49 @@ namespace OpenSim.Framework
307 return Utils.UIntsToLong(X, Y); 333 return Utils.UIntsToLong(X, Y);
308 } 334 }
309 335
336 // Regions are identified with a 'handle' made up of its region coordinates packed into a ulong.
337 // Several places rely on the ability to extract a region's location from its handle.
338 // Note the location is in 'world coordinates' (see below).
339 // Region handles are based on the lowest coordinate of the region so trim the passed x,y to be the regions 0,0.
340 public static ulong RegionWorldLocToHandle(uint X, uint Y)
341 {
342 return Utils.UIntsToLong(X, Y);
343 }
344
345 public static ulong RegionLocToHandle(uint X, uint Y)
346 {
347 return Utils.UIntsToLong(Util.RegionToWorldLoc(X), Util.RegionToWorldLoc(Y));
348 }
349
350 public static void RegionHandleToWorldLoc(ulong handle, out uint X, out uint Y)
351 {
352 X = (uint)(handle >> 32);
353 Y = (uint)(handle & (ulong)uint.MaxValue);
354 }
355
356 public static void RegionHandleToRegionLoc(ulong handle, out uint X, out uint Y)
357 {
358 uint worldX, worldY;
359 RegionHandleToWorldLoc(handle, out worldX, out worldY);
360 X = WorldToRegionLoc(worldX);
361 Y = WorldToRegionLoc(worldY);
362 }
363
364 // A region location can be 'world coordinates' (meters from zero) or 'region coordinates'
365 // (number of regions from zero). This measurement of regions relies on the legacy 256 region size.
366 // These routines exist to make what is being converted explicit so the next person knows what was meant.
367 // Convert a region's 'world coordinate' to its 'region coordinate'.
368 public static uint WorldToRegionLoc(uint worldCoord)
369 {
370 return worldCoord / Constants.RegionSize;
371 }
372
373 // Convert a region's 'region coordinate' to its 'world coordinate'.
374 public static uint RegionToWorldLoc(uint regionCoord)
375 {
376 return regionCoord * Constants.RegionSize;
377 }
378
310 public static T Clamp<T>(T x, T min, T max) 379 public static T Clamp<T>(T x, T min, T max)
311 where T : IComparable<T> 380 where T : IComparable<T>
312 { 381 {
@@ -495,20 +564,18 @@ namespace OpenSim.Framework
495 564
496 public static int ToUnixTime(DateTime stamp) 565 public static int ToUnixTime(DateTime stamp)
497 { 566 {
498 TimeSpan t = stamp.ToUniversalTime() - unixEpoch; 567 TimeSpan t = stamp.ToUniversalTime() - UnixEpoch;
499 return (int) t.TotalSeconds; 568 return (int)t.TotalSeconds;
500 } 569 }
501 570
502 public static DateTime ToDateTime(ulong seconds) 571 public static DateTime ToDateTime(ulong seconds)
503 { 572 {
504 DateTime epoch = unixEpoch; 573 return UnixEpoch.AddSeconds(seconds);
505 return epoch.AddSeconds(seconds);
506 } 574 }
507 575
508 public static DateTime ToDateTime(int seconds) 576 public static DateTime ToDateTime(int seconds)
509 { 577 {
510 DateTime epoch = unixEpoch; 578 return UnixEpoch.AddSeconds(seconds);
511 return epoch.AddSeconds(seconds);
512 } 579 }
513 580
514 /// <summary> 581 /// <summary>
@@ -976,7 +1043,7 @@ namespace OpenSim.Framework
976 else if (typeof(T) == typeof(Int32)) 1043 else if (typeof(T) == typeof(Int32))
977 val = cnf.GetInt(varname, (int)val); 1044 val = cnf.GetInt(varname, (int)val);
978 else if (typeof(T) == typeof(float)) 1045 else if (typeof(T) == typeof(float))
979 val = cnf.GetFloat(varname, (int)val); 1046 val = cnf.GetFloat(varname, (float)val);
980 else 1047 else
981 m_log.ErrorFormat("[UTIL]: Unhandled type {0}", typeof(T)); 1048 m_log.ErrorFormat("[UTIL]: Unhandled type {0}", typeof(T));
982 } 1049 }
@@ -1233,7 +1300,7 @@ namespace OpenSim.Framework
1233 byte[] bytes = 1300 byte[] bytes =
1234 { 1301 {
1235 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), 1302 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
1236 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), 1303 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
1237 (byte)x, (byte)(x >> 8), 0, 0, 1304 (byte)x, (byte)(x >> 8), 0, 0,
1238 (byte)y, (byte)(y >> 8), 0, 0 }; 1305 (byte)y, (byte)(y >> 8), 0, 0 };
1239 return new UUID(bytes, 0); 1306 return new UUID(bytes, 0);
@@ -1244,7 +1311,7 @@ namespace OpenSim.Framework
1244 byte[] bytes = 1311 byte[] bytes =
1245 { 1312 {
1246 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24), 1313 (byte)regionHandle, (byte)(regionHandle >> 8), (byte)(regionHandle >> 16), (byte)(regionHandle >> 24),
1247 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle << 56), 1314 (byte)(regionHandle >> 32), (byte)(regionHandle >> 40), (byte)(regionHandle >> 48), (byte)(regionHandle >> 56),
1248 (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8), 1315 (byte)x, (byte)(x >> 8), (byte)z, (byte)(z >> 8),
1249 (byte)y, (byte)(y >> 8), 0, 0 }; 1316 (byte)y, (byte)(y >> 8), 0, 0 };
1250 return new UUID(bytes, 0); 1317 return new UUID(bytes, 0);
@@ -1317,7 +1384,7 @@ namespace OpenSim.Framework
1317 ru = "OSX/Mono"; 1384 ru = "OSX/Mono";
1318 else 1385 else
1319 { 1386 {
1320 if (Type.GetType("Mono.Runtime") != null) 1387 if (IsPlatformMono)
1321 ru = "Win/Mono"; 1388 ru = "Win/Mono";
1322 else 1389 else
1323 ru = "Win/.NET"; 1390 ru = "Win/.NET";
@@ -1765,10 +1832,12 @@ namespace OpenSim.Framework
1765 FireAndForget(callback, null); 1832 FireAndForget(callback, null);
1766 } 1833 }
1767 1834
1768 public static void InitThreadPool(int maxThreads) 1835 public static void InitThreadPool(int minThreads, int maxThreads)
1769 { 1836 {
1770 if (maxThreads < 2) 1837 if (maxThreads < 2)
1771 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2"); 1838 throw new ArgumentOutOfRangeException("maxThreads", "maxThreads must be greater than 2");
1839 if (minThreads > maxThreads || minThreads < 2)
1840 throw new ArgumentOutOfRangeException("minThreads", "minThreads must be greater than 2 and less than or equal to maxThreads");
1772 if (m_ThreadPool != null) 1841 if (m_ThreadPool != null)
1773 throw new InvalidOperationException("SmartThreadPool is already initialized"); 1842 throw new InvalidOperationException("SmartThreadPool is already initialized");
1774 1843
@@ -1776,7 +1845,7 @@ namespace OpenSim.Framework
1776 startInfo.ThreadPoolName = "Util"; 1845 startInfo.ThreadPoolName = "Util";
1777 startInfo.IdleTimeout = 2000; 1846 startInfo.IdleTimeout = 2000;
1778 startInfo.MaxWorkerThreads = maxThreads; 1847 startInfo.MaxWorkerThreads = maxThreads;
1779 startInfo.MinWorkerThreads = 2; 1848 startInfo.MinWorkerThreads = minThreads;
1780 1849
1781 m_ThreadPool = new SmartThreadPool(startInfo); 1850 m_ThreadPool = new SmartThreadPool(startInfo);
1782 } 1851 }
@@ -1851,8 +1920,8 @@ namespace OpenSim.Framework
1851 break; 1920 break;
1852 case FireAndForgetMethod.SmartThreadPool: 1921 case FireAndForgetMethod.SmartThreadPool:
1853 if (m_ThreadPool == null) 1922 if (m_ThreadPool == null)
1854 InitThreadPool(15); 1923 InitThreadPool(2, 15);
1855 m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj }); 1924 m_ThreadPool.QueueWorkItem((cb, o) => cb(o), realCallback, obj);
1856 break; 1925 break;
1857 case FireAndForgetMethod.Thread: 1926 case FireAndForgetMethod.Thread:
1858 Thread thread = new Thread(delegate(object o) { realCallback(o); }); 1927 Thread thread = new Thread(delegate(object o) { realCallback(o); });
@@ -1864,72 +1933,29 @@ namespace OpenSim.Framework
1864 } 1933 }
1865 1934
1866 /// <summary> 1935 /// <summary>
1867 /// Get a thread pool report. 1936 /// Get information about the current state of the smart thread pool.
1868 /// </summary> 1937 /// </summary>
1869 /// <returns></returns> 1938 /// <returns>
1870 public static string GetThreadPoolReport() 1939 /// null if this isn't the pool being used for non-scriptengine threads.
1940 /// </returns>
1941 public static STPInfo GetSmartThreadPoolInfo()
1871 { 1942 {
1872 string threadPoolUsed = null; 1943 if (m_ThreadPool == null)
1873 int maxThreads = 0; 1944 return null;
1874 int minThreads = 0;
1875 int allocatedThreads = 0;
1876 int inUseThreads = 0;
1877 int waitingCallbacks = 0;
1878 int completionPortThreads = 0;
1879
1880 StringBuilder sb = new StringBuilder();
1881 if (FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
1882 {
1883 // ROBUST currently leaves this the FireAndForgetMethod but never actually initializes the threadpool.
1884 if (m_ThreadPool != null)
1885 {
1886 threadPoolUsed = "SmartThreadPool";
1887 maxThreads = m_ThreadPool.MaxThreads;
1888 minThreads = m_ThreadPool.MinThreads;
1889 inUseThreads = m_ThreadPool.InUseThreads;
1890 allocatedThreads = m_ThreadPool.ActiveThreads;
1891 waitingCallbacks = m_ThreadPool.WaitingCallbacks;
1892 }
1893 }
1894 else if (
1895 FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem
1896 || FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem)
1897 {
1898 threadPoolUsed = "BuiltInThreadPool";
1899 ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads);
1900 ThreadPool.GetMinThreads(out minThreads, out completionPortThreads);
1901 int availableThreads;
1902 ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads);
1903 inUseThreads = maxThreads - availableThreads;
1904 allocatedThreads = -1;
1905 waitingCallbacks = -1;
1906 }
1907
1908 if (threadPoolUsed != null)
1909 {
1910 sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed);
1911 sb.AppendFormat("Max threads : {0}\n", maxThreads);
1912 sb.AppendFormat("Min threads : {0}\n", minThreads);
1913 sb.AppendFormat("Allocated threads : {0}\n", allocatedThreads < 0 ? "not applicable" : allocatedThreads.ToString());
1914 sb.AppendFormat("In use threads : {0}\n", inUseThreads);
1915 sb.AppendFormat("Work items waiting : {0}\n", waitingCallbacks < 0 ? "not available" : waitingCallbacks.ToString());
1916 }
1917 else
1918 {
1919 sb.AppendFormat("Thread pool not used\n");
1920 }
1921
1922 return sb.ToString();
1923 }
1924 1945
1925 private static object SmartThreadPoolCallback(object o) 1946 STPInfo stpi = new STPInfo();
1926 { 1947 stpi.Name = m_ThreadPool.Name;
1927 object[] array = (object[])o; 1948 stpi.STPStartInfo = m_ThreadPool.STPStartInfo;
1928 WaitCallback callback = (WaitCallback)array[0]; 1949 stpi.IsIdle = m_ThreadPool.IsIdle;
1929 object obj = array[1]; 1950 stpi.IsShuttingDown = m_ThreadPool.IsShuttingdown;
1951 stpi.MaxThreads = m_ThreadPool.MaxThreads;
1952 stpi.MinThreads = m_ThreadPool.MinThreads;
1953 stpi.InUseThreads = m_ThreadPool.InUseThreads;
1954 stpi.ActiveThreads = m_ThreadPool.ActiveThreads;
1955 stpi.WaitingCallbacks = m_ThreadPool.WaitingCallbacks;
1956 stpi.MaxConcurrentWorkItems = m_ThreadPool.Concurrency;
1930 1957
1931 callback(obj); 1958 return stpi;
1932 return null;
1933 } 1959 }
1934 1960
1935 #endregion FireAndForget Threading Pattern 1961 #endregion FireAndForget Threading Pattern
@@ -2058,8 +2084,10 @@ namespace OpenSim.Framework
2058 #region Xml Serialization Utilities 2084 #region Xml Serialization Utilities
2059 public static bool ReadBoolean(XmlTextReader reader) 2085 public static bool ReadBoolean(XmlTextReader reader)
2060 { 2086 {
2087 // AuroraSim uses "int" for some fields that are boolean in OpenSim, e.g. "PassCollisions". Don't fail because of this.
2061 reader.ReadStartElement(); 2088 reader.ReadStartElement();
2062 bool result = Boolean.Parse(reader.ReadContentAsString().ToLower()); 2089 string val = reader.ReadContentAsString().ToLower();
2090 bool result = val.Equals("true") || val.Equals("1");
2063 reader.ReadEndElement(); 2091 reader.ReadEndElement();
2064 2092
2065 return result; 2093 return result;
@@ -2148,7 +2176,7 @@ namespace OpenSim.Framework
2148 /// <param name="secret">the secret part</param> 2176 /// <param name="secret">the secret part</param>
2149 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret) 2177 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret)
2150 { 2178 {
2151 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty; 2179 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "UserUPUUI"; secret = string.Empty;
2152 2180
2153 string[] parts = value.Split(';'); 2181 string[] parts = value.Split(';');
2154 if (parts.Length >= 1) 2182 if (parts.Length >= 1)
@@ -2282,7 +2310,7 @@ namespace OpenSim.Framework
2282 { 2310 {
2283 lock (m_syncRoot) 2311 lock (m_syncRoot)
2284 { 2312 {
2285 m_lowQueue.Enqueue(data); 2313 q.Enqueue(data);
2286 m_s.WaitOne(0); 2314 m_s.WaitOne(0);
2287 m_s.Release(); 2315 m_s.Release();
2288 } 2316 }
@@ -2322,7 +2350,7 @@ namespace OpenSim.Framework
2322 { 2350 {
2323 if (m_highQueue.Count > 0) 2351 if (m_highQueue.Count > 0)
2324 res = m_highQueue.Dequeue(); 2352 res = m_highQueue.Dequeue();
2325 else 2353 else if (m_lowQueue.Count > 0)
2326 res = m_lowQueue.Dequeue(); 2354 res = m_lowQueue.Dequeue();
2327 2355
2328 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0) 2356 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index bf57fd4..33ef8e0 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -67,6 +67,11 @@ namespace OpenSim.Framework
67 public static int RequestNumber { get; internal set; } 67 public static int RequestNumber { get; internal set; }
68 68
69 /// <summary> 69 /// <summary>
70 /// Control where OSD requests should be serialized per endpoint.
71 /// </summary>
72 public static bool SerializeOSDRequestsPerEndpoint { get; set; }
73
74 /// <summary>
70 /// this is the header field used to communicate the local request id 75 /// this is the header field used to communicate the local request id
71 /// used for performance and debugging 76 /// used for performance and debugging
72 /// </summary> 77 /// </summary>
@@ -145,10 +150,50 @@ namespace OpenSim.Framework
145 150
146 public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed) 151 public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed)
147 { 152 {
148 lock (EndPointLock(url)) 153 if (SerializeOSDRequestsPerEndpoint)
154 {
155 lock (EndPointLock(url))
156 {
157 return ServiceOSDRequestWorker(url, data, method, timeout, compressed);
158 }
159 }
160 else
161 {
162 return ServiceOSDRequestWorker(url, data, method, timeout, compressed);
163 }
164 }
165
166 public static void LogOutgoingDetail(Stream outputStream)
167 {
168 using (StreamReader reader = new StreamReader(Util.Copy(outputStream), Encoding.UTF8))
169 {
170 string output;
171
172 if (DebugLevel == 5)
173 {
174 const int sampleLength = 80;
175 char[] sampleChars = new char[sampleLength];
176 reader.Read(sampleChars, 0, sampleLength);
177 output = new string(sampleChars);
178 }
179 else
180 {
181 output = reader.ReadToEnd();
182 }
183
184 LogOutgoingDetail(output);
185 }
186 }
187
188 public static void LogOutgoingDetail(string output)
189 {
190 if (DebugLevel == 5)
149 { 191 {
150 return ServiceOSDRequestWorker(url,data,method,timeout,compressed); 192 output = output.Substring(0, 80);
193 output = output + "...";
151 } 194 }
195
196 m_log.DebugFormat("[WEB UTIL]: {0}", output.Replace("\n", @"\n"));
152 } 197 }
153 198
154 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed) 199 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed)
@@ -178,7 +223,11 @@ namespace OpenSim.Framework
178 // If there is some input, write it into the request 223 // If there is some input, write it into the request
179 if (data != null) 224 if (data != null)
180 { 225 {
181 strBuffer = OSDParser.SerializeJsonString(data); 226 strBuffer = OSDParser.SerializeJsonString(data);
227
228 if (DebugLevel >= 5)
229 LogOutgoingDetail(strBuffer);
230
182 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer); 231 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer);
183 232
184 if (compressed) 233 if (compressed)
@@ -358,6 +407,10 @@ namespace OpenSim.Framework
358 if (data != null) 407 if (data != null)
359 { 408 {
360 queryString = BuildQueryString(data); 409 queryString = BuildQueryString(data);
410
411 if (DebugLevel >= 5)
412 LogOutgoingDetail(queryString);
413
361 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString); 414 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString);
362 415
363 request.ContentLength = buffer.Length; 416 request.ContentLength = buffer.Length;
@@ -668,7 +721,7 @@ namespace OpenSim.Framework
668 /// <returns></returns> 721 /// <returns></returns>
669 public static string[] GetPreferredImageTypes(string accept) 722 public static string[] GetPreferredImageTypes(string accept)
670 { 723 {
671 if (accept == null || accept == string.Empty) 724 if (string.IsNullOrEmpty(accept))
672 return new string[0]; 725 return new string[0];
673 726
674 string[] types = accept.Split(new char[] { ',' }); 727 string[] types = accept.Split(new char[] { ',' });
@@ -769,6 +822,9 @@ namespace OpenSim.Framework
769 int length = (int)buffer.Length; 822 int length = (int)buffer.Length;
770 request.ContentLength = length; 823 request.ContentLength = length;
771 824
825 if (WebUtil.DebugLevel >= 5)
826 WebUtil.LogOutgoingDetail(buffer);
827
772 request.BeginGetRequestStream(delegate(IAsyncResult res) 828 request.BeginGetRequestStream(delegate(IAsyncResult res)
773 { 829 {
774 Stream requestStream = request.EndGetRequestStream(res); 830 Stream requestStream = request.EndGetRequestStream(res);
@@ -928,11 +984,12 @@ namespace OpenSim.Framework
928 /// <param name="verb"></param> 984 /// <param name="verb"></param>
929 /// <param name="requestUrl"></param> 985 /// <param name="requestUrl"></param>
930 /// <param name="obj"> </param> 986 /// <param name="obj"> </param>
987 /// <param name="timeoutsecs"> </param>
931 /// <returns></returns> 988 /// <returns></returns>
932 /// 989 ///
933 /// <exception cref="System.Net.WebException">Thrown if we encounter a network issue while posting 990 /// <exception cref="System.Net.WebException">Thrown if we encounter a network issue while posting
934 /// the request. You'll want to make sure you deal with this as they're not uncommon</exception> 991 /// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
935 public static string MakeRequest(string verb, string requestUrl, string obj) 992 public static string MakeRequest(string verb, string requestUrl, string obj, int timeoutsecs)
936 { 993 {
937 int reqnum = WebUtil.RequestNumber++; 994 int reqnum = WebUtil.RequestNumber++;
938 995
@@ -946,6 +1003,8 @@ namespace OpenSim.Framework
946 1003
947 WebRequest request = WebRequest.Create(requestUrl); 1004 WebRequest request = WebRequest.Create(requestUrl);
948 request.Method = verb; 1005 request.Method = verb;
1006 if (timeoutsecs > 0)
1007 request.Timeout = timeoutsecs * 1000;
949 string respstring = String.Empty; 1008 string respstring = String.Empty;
950 1009
951 int tickset = Util.EnvironmentTickCountSubtract(tickstart); 1010 int tickset = Util.EnvironmentTickCountSubtract(tickstart);
@@ -966,6 +1025,9 @@ namespace OpenSim.Framework
966 length = (int)obj.Length; 1025 length = (int)obj.Length;
967 request.ContentLength = length; 1026 request.ContentLength = length;
968 1027
1028 if (WebUtil.DebugLevel >= 5)
1029 WebUtil.LogOutgoingDetail(buffer);
1030
969 Stream requestStream = null; 1031 Stream requestStream = null;
970 try 1032 try
971 { 1033 {
@@ -1039,6 +1101,11 @@ namespace OpenSim.Framework
1039 1101
1040 return respstring; 1102 return respstring;
1041 } 1103 }
1104
1105 public static string MakeRequest(string verb, string requestUrl, string obj)
1106 {
1107 return MakeRequest(verb, requestUrl, obj, -1);
1108 }
1042 } 1109 }
1043 1110
1044 public class SynchronousRestObjectRequester 1111 public class SynchronousRestObjectRequester
@@ -1111,6 +1178,9 @@ namespace OpenSim.Framework
1111 int length = (int)buffer.Length; 1178 int length = (int)buffer.Length;
1112 request.ContentLength = length; 1179 request.ContentLength = length;
1113 1180
1181 if (WebUtil.DebugLevel >= 5)
1182 WebUtil.LogOutgoingDetail(buffer);
1183
1114 Stream requestStream = null; 1184 Stream requestStream = null;
1115 try 1185 try
1116 { 1186 {
@@ -1213,4 +1283,4 @@ namespace OpenSim.Framework
1213 return deserial; 1283 return deserial;
1214 } 1284 }
1215 } 1285 }
1216} 1286} \ No newline at end of file
diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs
index c3e7ec2..3a4e5df 100644
--- a/OpenSim/Region/Application/Application.cs
+++ b/OpenSim/Region/Application/Application.cs
@@ -103,48 +103,63 @@ namespace OpenSim
103 "[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset"); 103 "[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset");
104 104
105 // Verify the Threadpool allocates or uses enough worker and IO completion threads 105 // Verify the Threadpool allocates or uses enough worker and IO completion threads
106 // .NET 2.0 workerthreads default to 50 * numcores 106 // .NET 2.0, workerthreads default to 50 * numcores
107 // .NET 3.0 workerthreads defaults to 250 * numcores 107 // .NET 3.0, workerthreads defaults to 250 * numcores
108 // .NET 4.0 workerthreads are dynamic based on bitness and OS resources 108 // .NET 4.0, workerthreads are dynamic based on bitness and OS resources
109 // Max IO Completion threads are 1000 on all 3 CLRs. 109 // Max IO Completion threads are 1000 on all 3 CLRs
110 //
111 // Mono 2.10.9 to at least Mono 3.1, workerthreads default to 100 * numcores, iocp threads to 4 * numcores
110 int workerThreadsMin = 500; 112 int workerThreadsMin = 500;
111 int workerThreadsMax = 1000; // may need further adjustment to match other CLR 113 int workerThreadsMax = 1000; // may need further adjustment to match other CLR
112 int iocpThreadsMin = 1000; 114 int iocpThreadsMin = 1000;
113 int iocpThreadsMax = 2000; // may need further adjustment to match other CLR 115 int iocpThreadsMax = 2000; // may need further adjustment to match other CLR
116
117 {
118 int currentMinWorkerThreads, currentMinIocpThreads;
119 System.Threading.ThreadPool.GetMinThreads(out currentMinWorkerThreads, out currentMinIocpThreads);
120 m_log.InfoFormat(
121 "[OPENSIM MAIN]: Runtime gave us {0} min worker threads and {1} min IOCP threads",
122 currentMinWorkerThreads, currentMinIocpThreads);
123 }
124
114 int workerThreads, iocpThreads; 125 int workerThreads, iocpThreads;
115 System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads); 126 System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
116 m_log.InfoFormat("[OPENSIM MAIN]: Runtime gave us {0} worker threads and {1} IOCP threads", workerThreads, iocpThreads); 127 m_log.InfoFormat("[OPENSIM MAIN]: Runtime gave us {0} max worker threads and {1} max IOCP threads", workerThreads, iocpThreads);
128
117 if (workerThreads < workerThreadsMin) 129 if (workerThreads < workerThreadsMin)
118 { 130 {
119 workerThreads = workerThreadsMin; 131 workerThreads = workerThreadsMin;
120 m_log.InfoFormat("[OPENSIM MAIN]: Bumping up to worker threads to {0}",workerThreads); 132 m_log.InfoFormat("[OPENSIM MAIN]: Bumping up to max worker threads to {0}",workerThreads);
121 } 133 }
122 if (workerThreads > workerThreadsMax) 134 if (workerThreads > workerThreadsMax)
123 { 135 {
124 workerThreads = workerThreadsMax; 136 workerThreads = workerThreadsMax;
125 m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads); 137 m_log.InfoFormat("[OPENSIM MAIN]: Limiting max worker threads to {0}",workerThreads);
126 } 138 }
139
127 // Increase the number of IOCP threads available. 140 // Increase the number of IOCP threads available.
128 // Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17) 141 // Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17)
129 if (iocpThreads < iocpThreadsMin) 142 if (iocpThreads < iocpThreadsMin)
130 { 143 {
131 iocpThreads = iocpThreadsMin; 144 iocpThreads = iocpThreadsMin;
132 m_log.InfoFormat("[OPENSIM MAIN]: Bumping up IO completion threads to {0}",iocpThreads); 145 m_log.InfoFormat("[OPENSIM MAIN]: Bumping up max IOCP threads to {0}",iocpThreads);
133 } 146 }
134 // Make sure we don't overallocate IOCP threads and thrash system resources 147 // Make sure we don't overallocate IOCP threads and thrash system resources
135 if ( iocpThreads > iocpThreadsMax ) 148 if ( iocpThreads > iocpThreadsMax )
136 { 149 {
137 iocpThreads = iocpThreadsMax; 150 iocpThreads = iocpThreadsMax;
138 m_log.InfoFormat("[OPENSIM MAIN]: Limiting IO completion threads to {0}",iocpThreads); 151 m_log.InfoFormat("[OPENSIM MAIN]: Limiting max IOCP completion threads to {0}",iocpThreads);
139 } 152 }
140 // set the resulting worker and IO completion thread counts back to ThreadPool 153 // set the resulting worker and IO completion thread counts back to ThreadPool
141 if ( System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads) ) 154 if ( System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads) )
142 { 155 {
143 m_log.InfoFormat("[OPENSIM MAIN]: Threadpool set to {0} worker threads and {1} IO completion threads", workerThreads, iocpThreads); 156 m_log.InfoFormat(
157 "[OPENSIM MAIN]: Threadpool set to {0} max worker threads and {1} max IOCP threads",
158 workerThreads, iocpThreads);
144 } 159 }
145 else 160 else
146 { 161 {
147 m_log.Info("[OPENSIM MAIN]: Threadpool reconfiguration failed, runtime defaults still in effect."); 162 m_log.Warn("[OPENSIM MAIN]: Threadpool reconfiguration failed, runtime defaults still in effect.");
148 } 163 }
149 164
150 // Check if the system is compatible with OpenSimulator. 165 // Check if the system is compatible with OpenSimulator.
@@ -152,17 +167,16 @@ namespace OpenSim
152 string supported = String.Empty; 167 string supported = String.Empty;
153 if (Util.IsEnvironmentSupported(ref supported)) 168 if (Util.IsEnvironmentSupported(ref supported))
154 { 169 {
155 m_log.Info("Environment is compatible.\n"); 170 m_log.Info("[OPENSIM MAIN]: Environment is supported by OpenSimulator.");
156 } 171 }
157 else 172 else
158 { 173 {
159 m_log.Warn("Environment is unsupported (" + supported + ")\n"); 174 m_log.Warn("[OPENSIM MAIN]: Environment is not supported by OpenSimulator (" + supported + ")\n");
160 } 175 }
161 176
162 // Configure nIni aliases and localles 177 // Configure nIni aliases and localles
163 Culture.SetCurrentCulture(); 178 Culture.SetCurrentCulture();
164 179
165
166 // Validate that the user has the most basic configuration done 180 // Validate that the user has the most basic configuration done
167 // If not, offer to do the most basic configuration for them warning them along the way of the importance of 181 // If not, offer to do the most basic configuration for them warning them along the way of the importance of
168 // reading these files. 182 // reading these files.
diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs
index fc3999f..52e520c 100644
--- a/OpenSim/Region/Application/ConfigurationLoader.cs
+++ b/OpenSim/Region/Application/ConfigurationLoader.cs
@@ -124,7 +124,7 @@ namespace OpenSim
124 else 124 else
125 { 125 {
126 Application.iniFilePath = Path.GetFullPath( 126 Application.iniFilePath = Path.GetFullPath(
127 Path.Combine(Util.configDir(), iniFileName)); 127 Path.Combine(Util.configDir(), iniFileName));
128 128
129 if (!File.Exists(Application.iniFilePath)) 129 if (!File.Exists(Application.iniFilePath))
130 { 130 {
@@ -139,12 +139,29 @@ namespace OpenSim
139 } 139 }
140 } 140 }
141 141
142 m_config = new OpenSimConfigSource();
143 m_config.Source = new IniConfigSource();
144 m_config.Source.Merge(DefaultConfig());
145
146 m_log.Info("[CONFIG]: Reading configuration settings");
147
148 for (int i = 0 ; i < sources.Count ; i++)
149 {
150 if (ReadConfig(m_config, sources[i]))
151 {
152 iniFileExists = true;
153 AddIncludes(m_config, sources);
154 }
155 }
156
157 // Override distro settings with contents of inidirectory
142 string iniDirName = startupConfig.GetString("inidirectory", "config"); 158 string iniDirName = startupConfig.GetString("inidirectory", "config");
143 string iniDirPath = Path.Combine(Util.configDir(), iniDirName); 159 string iniDirPath = Path.Combine(Util.configDir(), iniDirName);
144 160
145 if (Directory.Exists(iniDirPath)) 161 if (Directory.Exists(iniDirPath))
146 { 162 {
147 m_log.InfoFormat("Searching folder {0} for config ini files", iniDirPath); 163 m_log.InfoFormat("[CONFIG]: Searching folder {0} for config ini files", iniDirPath);
164 List<string> overrideSources = new List<string>();
148 165
149 string[] fileEntries = Directory.GetFiles(iniDirName); 166 string[] fileEntries = Directory.GetFiles(iniDirName);
150 foreach (string filePath in fileEntries) 167 foreach (string filePath in fileEntries)
@@ -152,33 +169,38 @@ namespace OpenSim
152 if (Path.GetExtension(filePath).ToLower() == ".ini") 169 if (Path.GetExtension(filePath).ToLower() == ".ini")
153 { 170 {
154 if (!sources.Contains(Path.GetFullPath(filePath))) 171 if (!sources.Contains(Path.GetFullPath(filePath)))
172 {
173 overrideSources.Add(Path.GetFullPath(filePath));
174 // put it in sources too, to avoid circularity
155 sources.Add(Path.GetFullPath(filePath)); 175 sources.Add(Path.GetFullPath(filePath));
176 }
156 } 177 }
157 } 178 }
158 }
159 179
160 m_config = new OpenSimConfigSource();
161 m_config.Source = new IniConfigSource();
162 m_config.Source.Merge(DefaultConfig());
163 180
164 m_log.Info("[CONFIG]: Reading configuration settings"); 181 if (overrideSources.Count > 0)
182 {
183 OpenSimConfigSource overrideConfig = new OpenSimConfigSource();
184 overrideConfig.Source = new IniConfigSource();
185
186 for (int i = 0 ; i < overrideSources.Count ; i++)
187 {
188 if (ReadConfig(overrideConfig, overrideSources[i]))
189 {
190 iniFileExists = true;
191 AddIncludes(overrideConfig, overrideSources);
192 }
193 }
194 m_config.Source.Merge(overrideConfig.Source);
195 }
196 }
165 197
166 if (sources.Count == 0) 198 if (sources.Count == 0)
167 { 199 {
168 m_log.FatalFormat("[CONFIG]: Could not load any configuration"); 200 m_log.FatalFormat("[CONFIG]: Could not load any configuration");
169 Environment.Exit(1); 201 Environment.Exit(1);
170 } 202 }
171 203 else if (!iniFileExists)
172 for (int i = 0 ; i < sources.Count ; i++)
173 {
174 if (ReadConfig(sources[i]))
175 {
176 iniFileExists = true;
177 AddIncludes(sources);
178 }
179 }
180
181 if (!iniFileExists)
182 { 204 {
183 m_log.FatalFormat("[CONFIG]: Could not load any configuration"); 205 m_log.FatalFormat("[CONFIG]: Could not load any configuration");
184 m_log.FatalFormat("[CONFIG]: Configuration exists, but there was an error loading it!"); 206 m_log.FatalFormat("[CONFIG]: Configuration exists, but there was an error loading it!");
@@ -201,9 +223,9 @@ namespace OpenSim
201 223
202 envConfigSource.LoadEnv(); 224 envConfigSource.LoadEnv();
203 m_config.Source.Merge(envConfigSource); 225 m_config.Source.Merge(envConfigSource);
204 m_config.Source.ExpandKeyValues();
205 } 226 }
206 227
228 m_config.Source.ExpandKeyValues();
207 229
208 ReadConfigSettings(); 230 ReadConfigSettings();
209 231
@@ -214,10 +236,10 @@ namespace OpenSim
214 /// Adds the included files as ini configuration files 236 /// Adds the included files as ini configuration files
215 /// </summary> 237 /// </summary>
216 /// <param name="sources">List of URL strings or filename strings</param> 238 /// <param name="sources">List of URL strings or filename strings</param>
217 private void AddIncludes(List<string> sources) 239 private void AddIncludes(OpenSimConfigSource configSource, List<string> sources)
218 { 240 {
219 //loop over config sources 241 //loop over config sources
220 foreach (IConfig config in m_config.Source.Configs) 242 foreach (IConfig config in configSource.Source.Configs)
221 { 243 {
222 // Look for Include-* in the key name 244 // Look for Include-* in the key name
223 string[] keys = config.GetKeys(); 245 string[] keys = config.GetKeys();
@@ -284,7 +306,7 @@ namespace OpenSim
284 /// </summary> 306 /// </summary>
285 /// <param name="iniPath">Full path to the ini</param> 307 /// <param name="iniPath">Full path to the ini</param>
286 /// <returns></returns> 308 /// <returns></returns>
287 private bool ReadConfig(string iniPath) 309 private bool ReadConfig(OpenSimConfigSource configSource, string iniPath)
288 { 310 {
289 bool success = false; 311 bool success = false;
290 312
@@ -292,7 +314,7 @@ namespace OpenSim
292 { 314 {
293 m_log.InfoFormat("[CONFIG]: Reading configuration file {0}", Path.GetFullPath(iniPath)); 315 m_log.InfoFormat("[CONFIG]: Reading configuration file {0}", Path.GetFullPath(iniPath));
294 316
295 m_config.Source.Merge(new IniConfigSource(iniPath)); 317 configSource.Source.Merge(new IniConfigSource(iniPath));
296 success = true; 318 success = true;
297 } 319 }
298 else 320 else
@@ -305,7 +327,7 @@ namespace OpenSim
305 { 327 {
306 XmlReader r = XmlReader.Create(iniPath); 328 XmlReader r = XmlReader.Create(iniPath);
307 XmlConfigSource cs = new XmlConfigSource(r); 329 XmlConfigSource cs = new XmlConfigSource(r);
308 m_config.Source.Merge(cs); 330 configSource.Source.Merge(cs);
309 331
310 success = true; 332 success = true;
311 } 333 }
@@ -337,10 +359,7 @@ namespace OpenSim
337 config.Set("physics", "OpenDynamicsEngine"); 359 config.Set("physics", "OpenDynamicsEngine");
338 config.Set("meshing", "Meshmerizer"); 360 config.Set("meshing", "Meshmerizer");
339 config.Set("physical_prim", true); 361 config.Set("physical_prim", true);
340 config.Set("see_into_this_sim_from_neighbor", true);
341 config.Set("serverside_object_permissions", true); 362 config.Set("serverside_object_permissions", true);
342 config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
343 config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
344 config.Set("storage_prim_inventories", true); 363 config.Set("storage_prim_inventories", true);
345 config.Set("startup_console_commands_file", String.Empty); 364 config.Set("startup_console_commands_file", String.Empty);
346 config.Set("shutdown_console_commands_file", String.Empty); 365 config.Set("shutdown_console_commands_file", String.Empty);
@@ -372,7 +391,6 @@ namespace OpenSim
372 { 391 {
373 m_configSettings.PhysicsEngine = startupConfig.GetString("physics"); 392 m_configSettings.PhysicsEngine = startupConfig.GetString("physics");
374 m_configSettings.MeshEngineName = startupConfig.GetString("meshing"); 393 m_configSettings.MeshEngineName = startupConfig.GetString("meshing");
375 m_configSettings.StorageDll = startupConfig.GetString("storage_plugin");
376 394
377 m_configSettings.ClientstackDll 395 m_configSettings.ClientstackDll
378 = startupConfig.GetString("clientstack_plugin", "OpenSim.Region.ClientStack.LindenUDP.dll"); 396 = startupConfig.GetString("clientstack_plugin", "OpenSim.Region.ClientStack.LindenUDP.dll");
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index a7e7d03..85049c9 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -86,6 +86,7 @@ namespace OpenSim
86 IConfig startupConfig = Config.Configs["Startup"]; 86 IConfig startupConfig = Config.Configs["Startup"];
87 IConfig networkConfig = Config.Configs["Network"]; 87 IConfig networkConfig = Config.Configs["Network"];
88 88
89 int stpMinThreads = 2;
89 int stpMaxThreads = 15; 90 int stpMaxThreads = 15;
90 91
91 if (startupConfig != null) 92 if (startupConfig != null)
@@ -112,12 +113,13 @@ namespace OpenSim
112 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod)) 113 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod))
113 Util.FireAndForgetMethod = asyncCallMethod; 114 Util.FireAndForgetMethod = asyncCallMethod;
114 115
116 stpMinThreads = startupConfig.GetInt("MinPoolThreads", 15);
115 stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 15); 117 stpMaxThreads = startupConfig.GetInt("MaxPoolThreads", 15);
116 m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) "); 118 m_consolePrompt = startupConfig.GetString("ConsolePrompt", @"Region (\R) ");
117 } 119 }
118 120
119 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) 121 if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool)
120 Util.InitThreadPool(stpMaxThreads); 122 Util.InitThreadPool(stpMinThreads, stpMaxThreads);
121 123
122 m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod); 124 m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod);
123 } 125 }
@@ -170,6 +172,13 @@ namespace OpenSim
170 if (userStatsURI != String.Empty) 172 if (userStatsURI != String.Empty)
171 MainServer.Instance.AddStreamHandler(new OpenSim.UXSimStatusHandler(this)); 173 MainServer.Instance.AddStreamHandler(new OpenSim.UXSimStatusHandler(this));
172 174
175 if (managedStatsURI != String.Empty)
176 {
177 string urlBase = String.Format("/{0}/", managedStatsURI);
178 MainServer.Instance.AddHTTPHandler(urlBase, StatsManager.HandleStatsRequest);
179 m_log.InfoFormat("[OPENSIM] Enabling remote managed stats fetch. URL = {0}", urlBase);
180 }
181
173 if (m_console is RemoteConsole) 182 if (m_console is RemoteConsole)
174 { 183 {
175 if (m_consolePort == 0) 184 if (m_consolePort == 0)
@@ -226,41 +235,35 @@ namespace OpenSim
226 "Force the update of all objects on clients", 235 "Force the update of all objects on clients",
227 HandleForceUpdate); 236 HandleForceUpdate);
228 237
229 m_console.Commands.AddCommand("Debug", false, "debug packet",
230 "debug packet <level> [<avatar-first-name> <avatar-last-name>]",
231 "Turn on packet debugging",
232 "If level > 255 then all incoming and outgoing packets are logged.\n"
233 + "If level <= 255 then incoming AgentUpdate and outgoing SimStats and SimulatorViewerTimeMessage packets are not logged.\n"
234 + "If level <= 200 then incoming RequestImage and outgoing ImagePacket, ImageData, LayerData and CoarseLocationUpdate packets are not logged.\n"
235 + "If level <= 100 then incoming ViewerEffect and AgentAnimation and outgoing ViewerEffect and AvatarAnimation packets are not logged.\n"
236 + "If level <= 50 then outgoing ImprovedTerseObjectUpdate packets are not logged.\n"
237 + "If level <= 0 then no packets are logged.\n"
238 + "If an avatar name is given then only packets from that avatar are logged",
239 Debug);
240
241 m_console.Commands.AddCommand("General", false, "change region", 238 m_console.Commands.AddCommand("General", false, "change region",
242 "change region <region name>", 239 "change region <region name>",
243 "Change current console region", ChangeSelectedRegion); 240 "Change current console region",
241 ChangeSelectedRegion);
244 242
245 m_console.Commands.AddCommand("Archiving", false, "save xml", 243 m_console.Commands.AddCommand("Archiving", false, "save xml",
246 "save xml", 244 "save xml",
247 "Save a region's data in XML format", SaveXml); 245 "Save a region's data in XML format",
246 SaveXml);
248 247
249 m_console.Commands.AddCommand("Archiving", false, "save xml2", 248 m_console.Commands.AddCommand("Archiving", false, "save xml2",
250 "save xml2", 249 "save xml2",
251 "Save a region's data in XML2 format", SaveXml2); 250 "Save a region's data in XML2 format",
251 SaveXml2);
252 252
253 m_console.Commands.AddCommand("Archiving", false, "load xml", 253 m_console.Commands.AddCommand("Archiving", false, "load xml",
254 "load xml [-newIDs [<x> <y> <z>]]", 254 "load xml [-newIDs [<x> <y> <z>]]",
255 "Load a region's data from XML format", LoadXml); 255 "Load a region's data from XML format",
256 LoadXml);
256 257
257 m_console.Commands.AddCommand("Archiving", false, "load xml2", 258 m_console.Commands.AddCommand("Archiving", false, "load xml2",
258 "load xml2", 259 "load xml2",
259 "Load a region's data from XML2 format", LoadXml2); 260 "Load a region's data from XML2 format",
261 LoadXml2);
260 262
261 m_console.Commands.AddCommand("Archiving", false, "save prims xml2", 263 m_console.Commands.AddCommand("Archiving", false, "save prims xml2",
262 "save prims xml2 [<prim name> <file name>]", 264 "save prims xml2 [<prim name> <file name>]",
263 "Save named prim to XML2", SavePrimsXml2); 265 "Save named prim to XML2",
266 SavePrimsXml2);
264 267
265 m_console.Commands.AddCommand("Archiving", false, "load oar", 268 m_console.Commands.AddCommand("Archiving", false, "load oar",
266 "load oar [--merge] [--skip-assets] [<OAR path>]", 269 "load oar [--merge] [--skip-assets] [<OAR path>]",
@@ -290,7 +293,23 @@ namespace OpenSim
290 293
291 m_console.Commands.AddCommand("Objects", false, "edit scale", 294 m_console.Commands.AddCommand("Objects", false, "edit scale",
292 "edit scale <name> <x> <y> <z>", 295 "edit scale <name> <x> <y> <z>",
293 "Change the scale of a named prim", HandleEditScale); 296 "Change the scale of a named prim",
297 HandleEditScale);
298
299 m_console.Commands.AddCommand("Objects", false, "rotate scene",
300 "rotate scene <degrees> [centerX, centerY]",
301 "Rotates all scene objects around centerX, centerY (defailt 128, 128) (please back up your region before using)",
302 HandleRotateScene);
303
304 m_console.Commands.AddCommand("Objects", false, "scale scene",
305 "scale scene <factor>",
306 "Scales the scene objects (please back up your region before using)",
307 HandleScaleScene);
308
309 m_console.Commands.AddCommand("Objects", false, "translate scene",
310 "translate scene xOffset yOffset zOffset",
311 "translates the scene objects (please back up your region before using)",
312 HandleTranslateScene);
294 313
295 m_console.Commands.AddCommand("Users", false, "kick user", 314 m_console.Commands.AddCommand("Users", false, "kick user",
296 "kick user <first> <last> [--force] [message]", 315 "kick user <first> <last> [--force] [message]",
@@ -308,31 +327,38 @@ namespace OpenSim
308 327
309 m_console.Commands.AddCommand("Comms", false, "show connections", 328 m_console.Commands.AddCommand("Comms", false, "show connections",
310 "show connections", 329 "show connections",
311 "Show connection data", HandleShow); 330 "Show connection data",
331 HandleShow);
312 332
313 m_console.Commands.AddCommand("Comms", false, "show circuits", 333 m_console.Commands.AddCommand("Comms", false, "show circuits",
314 "show circuits", 334 "show circuits",
315 "Show agent circuit data", HandleShow); 335 "Show agent circuit data",
336 HandleShow);
316 337
317 m_console.Commands.AddCommand("Comms", false, "show pending-objects", 338 m_console.Commands.AddCommand("Comms", false, "show pending-objects",
318 "show pending-objects", 339 "show pending-objects",
319 "Show # of objects on the pending queues of all scene viewers", HandleShow); 340 "Show # of objects on the pending queues of all scene viewers",
341 HandleShow);
320 342
321 m_console.Commands.AddCommand("General", false, "show modules", 343 m_console.Commands.AddCommand("General", false, "show modules",
322 "show modules", 344 "show modules",
323 "Show module data", HandleShow); 345 "Show module data",
346 HandleShow);
324 347
325 m_console.Commands.AddCommand("Regions", false, "show regions", 348 m_console.Commands.AddCommand("Regions", false, "show regions",
326 "show regions", 349 "show regions",
327 "Show region data", HandleShow); 350 "Show region data",
351 HandleShow);
328 352
329 m_console.Commands.AddCommand("Regions", false, "show ratings", 353 m_console.Commands.AddCommand("Regions", false, "show ratings",
330 "show ratings", 354 "show ratings",
331 "Show rating data", HandleShow); 355 "Show rating data",
356 HandleShow);
332 357
333 m_console.Commands.AddCommand("Objects", false, "backup", 358 m_console.Commands.AddCommand("Objects", false, "backup",
334 "backup", 359 "backup",
335 "Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.", RunCommand); 360 "Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.",
361 RunCommand);
336 362
337 m_console.Commands.AddCommand("Regions", false, "create region", 363 m_console.Commands.AddCommand("Regions", false, "create region",
338 "create region [\"region name\"] <region_file.ini>", 364 "create region [\"region name\"] <region_file.ini>",
@@ -345,34 +371,26 @@ namespace OpenSim
345 371
346 m_console.Commands.AddCommand("Regions", false, "restart", 372 m_console.Commands.AddCommand("Regions", false, "restart",
347 "restart", 373 "restart",
348 "Restart all sims in this instance", RunCommand); 374 "Restart all sims in this instance",
375 RunCommand);
349 376
350 m_console.Commands.AddCommand("General", false, "command-script", 377 m_console.Commands.AddCommand("General", false, "command-script",
351 "command-script <script>", 378 "command-script <script>",
352 "Run a command script from file", RunCommand); 379 "Run a command script from file",
380 RunCommand);
353 381
354 m_console.Commands.AddCommand("Regions", false, "remove-region", 382 m_console.Commands.AddCommand("Regions", false, "remove-region",
355 "remove-region <name>", 383 "remove-region <name>",
356 "Remove a region from this simulator", RunCommand); 384 "Remove a region from this simulator",
385 RunCommand);
357 386
358 m_console.Commands.AddCommand("Regions", false, "delete-region", 387 m_console.Commands.AddCommand("Regions", false, "delete-region",
359 "delete-region <name>", 388 "delete-region <name>",
360 "Delete a region from disk", RunCommand); 389 "Delete a region from disk",
361 390 RunCommand);
362 m_console.Commands.AddCommand("General", false, "modules list",
363 "modules list",
364 "List modules", HandleModules);
365
366 m_console.Commands.AddCommand("General", false, "modules load",
367 "modules load <name>",
368 "Load a module", HandleModules);
369
370 m_console.Commands.AddCommand("General", false, "modules unload",
371 "modules unload <name>",
372 "Unload a module", HandleModules);
373 } 391 }
374 392
375 public override void ShutdownSpecific() 393 protected override void ShutdownSpecific()
376 { 394 {
377 if (m_shutdownCommandsFile != String.Empty) 395 if (m_shutdownCommandsFile != String.Empty)
378 { 396 {
@@ -435,8 +453,8 @@ namespace OpenSim
435 { 453 {
436 RegionInfo regionInfo = presence.Scene.RegionInfo; 454 RegionInfo regionInfo = presence.Scene.RegionInfo;
437 455
438 if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) && 456 if (presence.Firstname.ToLower().Equals(mainParams[2].ToLower()) &&
439 presence.Lastname.ToLower().Contains(mainParams[3].ToLower())) 457 presence.Lastname.ToLower().Equals(mainParams[3].ToLower()))
440 { 458 {
441 MainConsole.Instance.Output( 459 MainConsole.Instance.Output(
442 String.Format( 460 String.Format(
@@ -449,7 +467,8 @@ namespace OpenSim
449 else 467 else
450 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); 468 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
451 469
452 presence.Scene.IncomingCloseAgent(presence.UUID, force); 470 presence.Scene.CloseAgent(presence.UUID, force);
471 break;
453 } 472 }
454 } 473 }
455 474
@@ -501,6 +520,121 @@ namespace OpenSim
501 } 520 }
502 } 521 }
503 522
523 private void HandleRotateScene(string module, string[] args)
524 {
525 string usage = "Usage: rotate scene <angle in degrees> [centerX centerY] (centerX and centerY are optional and default to Constants.RegionSize / 2";
526
527 float centerX = Constants.RegionSize * 0.5f;
528 float centerY = Constants.RegionSize * 0.5f;
529
530 if (args.Length < 3 || args.Length == 4)
531 {
532 MainConsole.Instance.Output(usage);
533 return;
534 }
535
536 float angle = (float)(Convert.ToSingle(args[2]) / 180.0 * Math.PI);
537 OpenMetaverse.Quaternion rot = OpenMetaverse.Quaternion.CreateFromAxisAngle(0, 0, 1, angle);
538
539 if (args.Length > 4)
540 {
541 centerX = Convert.ToSingle(args[3]);
542 centerY = Convert.ToSingle(args[4]);
543 }
544
545 Vector3 center = new Vector3(centerX, centerY, 0.0f);
546
547 SceneManager.ForEachSelectedScene(delegate(Scene scene)
548 {
549 scene.ForEachSOG(delegate(SceneObjectGroup sog)
550 {
551 if (sog.AttachmentPoint == 0)
552 {
553 sog.RootPart.UpdateRotation(rot * sog.GroupRotation);
554 Vector3 offset = sog.AbsolutePosition - center;
555 offset *= rot;
556 sog.UpdateGroupPosition(center + offset);
557 }
558 });
559 });
560 }
561
562 private void HandleScaleScene(string module, string[] args)
563 {
564 string usage = "Usage: scale scene <factor>";
565
566 if (args.Length < 3)
567 {
568 MainConsole.Instance.Output(usage);
569 return;
570 }
571
572 float factor = (float)(Convert.ToSingle(args[2]));
573
574 float minZ = float.MaxValue;
575
576 SceneManager.ForEachSelectedScene(delegate(Scene scene)
577 {
578 scene.ForEachSOG(delegate(SceneObjectGroup sog)
579 {
580 if (sog.AttachmentPoint == 0)
581 {
582 if (sog.RootPart.AbsolutePosition.Z < minZ)
583 minZ = sog.RootPart.AbsolutePosition.Z;
584 }
585 });
586 });
587
588 SceneManager.ForEachSelectedScene(delegate(Scene scene)
589 {
590 scene.ForEachSOG(delegate(SceneObjectGroup sog)
591 {
592 if (sog.AttachmentPoint == 0)
593 {
594 Vector3 tmpRootPos = sog.RootPart.AbsolutePosition;
595 tmpRootPos.Z -= minZ;
596 tmpRootPos *= factor;
597 tmpRootPos.Z += minZ;
598
599 foreach (SceneObjectPart sop in sog.Parts)
600 {
601 if (sop.ParentID != 0)
602 sop.OffsetPosition *= factor;
603 sop.Scale *= factor;
604 }
605
606 sog.UpdateGroupPosition(tmpRootPos);
607 }
608 });
609 });
610 }
611
612 private void HandleTranslateScene(string module, string[] args)
613 {
614 string usage = "Usage: translate scene <xOffset, yOffset, zOffset>";
615
616 if (args.Length < 5)
617 {
618 MainConsole.Instance.Output(usage);
619 return;
620 }
621
622 float xOFfset = (float)Convert.ToSingle(args[2]);
623 float yOffset = (float)Convert.ToSingle(args[3]);
624 float zOffset = (float)Convert.ToSingle(args[4]);
625
626 Vector3 offset = new Vector3(xOFfset, yOffset, zOffset);
627
628 SceneManager.ForEachSelectedScene(delegate(Scene scene)
629 {
630 scene.ForEachSOG(delegate(SceneObjectGroup sog)
631 {
632 if (sog.AttachmentPoint == 0)
633 sog.UpdateGroupPosition(sog.AbsolutePosition + offset);
634 });
635 });
636 }
637
504 /// <summary> 638 /// <summary>
505 /// Creates a new region based on the parameters specified. This will ask the user questions on the console 639 /// Creates a new region based on the parameters specified. This will ask the user questions on the console
506 /// </summary> 640 /// </summary>
@@ -566,34 +700,6 @@ namespace OpenSim
566 } 700 }
567 701
568 /// <summary> 702 /// <summary>
569 /// Load, Unload, and list Region modules in use
570 /// </summary>
571 /// <param name="module"></param>
572 /// <param name="cmd"></param>
573 private void HandleModules(string module, string[] cmd)
574 {
575 List<string> args = new List<string>(cmd);
576 args.RemoveAt(0);
577 string[] cmdparams = args.ToArray();
578
579 if (cmdparams.Length > 0)
580 {
581 switch (cmdparams[0].ToLower())
582 {
583 case "list":
584 //TODO: Convert to new region modules
585 break;
586 case "unload":
587 //TODO: Convert to new region modules
588 break;
589 case "load":
590 //TODO: Convert to new region modules
591 break;
592 }
593 }
594 }
595
596 /// <summary>
597 /// Runs commands issued by the server console from the operator 703 /// Runs commands issued by the server console from the operator
598 /// </summary> 704 /// </summary>
599 /// <param name="command">The first argument of the parameter (the command)</param> 705 /// <param name="command">The first argument of the parameter (the command)</param>
@@ -701,45 +807,6 @@ namespace OpenSim
701 RefreshPrompt(); 807 RefreshPrompt();
702 } 808 }
703 809
704 /// <summary>
705 /// Turn on some debugging values for OpenSim.
706 /// </summary>
707 /// <param name="args"></param>
708 protected void Debug(string module, string[] args)
709 {
710 if (args.Length == 1)
711 return;
712
713 switch (args[1])
714 {
715 case "packet":
716 string name = null;
717 if (args.Length == 5)
718 name = string.Format("{0} {1}", args[3], args[4]);
719
720 if (args.Length > 2)
721 {
722 int newDebug;
723 if (int.TryParse(args[2], out newDebug))
724 {
725 SceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name);
726 // We provide user information elsewhere if any clients had their debug level set.
727// MainConsole.Instance.OutputFormat("Debug packet level set to {0}", newDebug);
728 }
729 else
730 {
731 MainConsole.Instance.Output("Usage: debug packet 0..255");
732 }
733 }
734
735 break;
736
737 default:
738 MainConsole.Instance.Output("Unknown debug command");
739 break;
740 }
741 }
742
743 // see BaseOpenSimServer 810 // see BaseOpenSimServer
744 /// <summary> 811 /// <summary>
745 /// Many commands list objects for debugging. Some of the types are listed here 812 /// Many commands list objects for debugging. Some of the types are listed here
@@ -829,7 +896,7 @@ namespace OpenSim
829 foreach (IRegionModuleBase module in sharedModules.OrderBy(m => m.Name)) 896 foreach (IRegionModuleBase module in sharedModules.OrderBy(m => m.Name))
830 MainConsole.Instance.OutputFormat("New Region Module (Shared): {0}", module.Name); 897 MainConsole.Instance.OutputFormat("New Region Module (Shared): {0}", module.Name);
831 898
832 foreach (IRegionModuleBase module in sharedModules.OrderBy(m => m.Name)) 899 foreach (IRegionModuleBase module in nonSharedModules.OrderBy(m => m.Name))
833 MainConsole.Instance.OutputFormat("New Region Module (Non-Shared): {0}", module.Name); 900 MainConsole.Instance.OutputFormat("New Region Module (Non-Shared): {0}", module.Name);
834 } 901 }
835 ); 902 );
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 88bd869..f663c77 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -75,6 +75,7 @@ namespace OpenSim
75 protected int proxyOffset = 0; 75 protected int proxyOffset = 0;
76 76
77 public string userStatsURI = String.Empty; 77 public string userStatsURI = String.Empty;
78 public string managedStatsURI = String.Empty;
78 79
79 protected bool m_autoCreateClientStack = true; 80 protected bool m_autoCreateClientStack = true;
80 81
@@ -199,6 +200,8 @@ namespace OpenSim
199 new string[] { "Startup", "Permissions" }, "DefaultPermissionsModule"); 200 new string[] { "Startup", "Permissions" }, "DefaultPermissionsModule");
200 201
201 m_permsModules = new List<string>(permissionModules.Split(',')); 202 m_permsModules = new List<string>(permissionModules.Split(','));
203
204 managedStatsURI = startupConfig.GetString("ManagedStatsRemoteFetchURI", String.Empty);
202 } 205 }
203 206
204 // Load the simulation data service 207 // Load the simulation data service
@@ -248,10 +251,7 @@ namespace OpenSim
248 } 251 }
249 252
250 if (m_console != null) 253 if (m_console != null)
251 {
252 StatsManager.RegisterConsoleCommands(m_console);
253 AddPluginCommands(m_console); 254 AddPluginCommands(m_console);
254 }
255 } 255 }
256 256
257 protected virtual void AddPluginCommands(ICommandConsole console) 257 protected virtual void AddPluginCommands(ICommandConsole console)
@@ -496,9 +496,6 @@ namespace OpenSim
496 scene.SnmpService.LinkUp(scene); 496 scene.SnmpService.LinkUp(scene);
497 } 497 }
498 498
499 scene.Start();
500 scene.StartScripts();
501
502 return clientServers; 499 return clientServers;
503 } 500 }
504 501
@@ -813,7 +810,7 @@ namespace OpenSim
813 810
814 if (foundClientServer) 811 if (foundClientServer)
815 { 812 {
816 m_clientServers[clientServerElement].NetworkStop(); 813 m_clientServers[clientServerElement].Stop();
817 m_clientServers.RemoveAt(clientServerElement); 814 m_clientServers.RemoveAt(clientServerElement);
818 } 815 }
819 } 816 }
@@ -827,6 +824,7 @@ namespace OpenSim
827 ShutdownClientServer(whichRegion); 824 ShutdownClientServer(whichRegion);
828 IScene scene; 825 IScene scene;
829 CreateRegion(whichRegion, true, out scene); 826 CreateRegion(whichRegion, true, out scene);
827 scene.Start();
830 } 828 }
831 829
832 # region Setup methods 830 # region Setup methods
@@ -840,73 +838,49 @@ namespace OpenSim
840 /// <summary> 838 /// <summary>
841 /// Handler to supply the current status of this sim 839 /// Handler to supply the current status of this sim
842 /// </summary> 840 /// </summary>
841 /// <remarks>
843 /// Currently this is always OK if the simulator is still listening for connections on its HTTP service 842 /// Currently this is always OK if the simulator is still listening for connections on its HTTP service
844 public class SimStatusHandler : IStreamedRequestHandler 843 /// </remarks>
844 public class SimStatusHandler : BaseStreamHandler
845 { 845 {
846 public byte[] Handle(string path, Stream request, 846 public SimStatusHandler() : base("GET", "/simstatus", "SimStatus", "Simulator Status") {}
847
848 protected override byte[] ProcessRequest(string path, Stream request,
847 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 849 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
848 { 850 {
849 return Util.UTF8.GetBytes("OK"); 851 return Util.UTF8.GetBytes("OK");
850 } 852 }
851 853
852 public string Name { get { return "SimStatus"; } } 854 public override string ContentType
853 public string Description { get { return "Simulator Status"; } }
854
855 public string ContentType
856 { 855 {
857 get { return "text/plain"; } 856 get { return "text/plain"; }
858 } 857 }
859
860 public string HttpMethod
861 {
862 get { return "GET"; }
863 }
864
865 public string Path
866 {
867 get { return "/simstatus"; }
868 }
869 } 858 }
870 859
871 /// <summary> 860 /// <summary>
872 /// Handler to supply the current extended status of this sim 861 /// Handler to supply the current extended status of this sim
873 /// Sends the statistical data in a json serialization 862 /// Sends the statistical data in a json serialization
874 /// </summary> 863 /// </summary>
875 public class XSimStatusHandler : IStreamedRequestHandler 864 public class XSimStatusHandler : BaseStreamHandler
876 { 865 {
877 OpenSimBase m_opensim; 866 OpenSimBase m_opensim;
878 string osXStatsURI = String.Empty;
879
880 public string Name { get { return "XSimStatus"; } }
881 public string Description { get { return "Simulator XStatus"; } }
882 867
883 public XSimStatusHandler(OpenSimBase sim) 868 public XSimStatusHandler(OpenSimBase sim)
869 : base("GET", "/" + Util.SHA1Hash(sim.osSecret), "XSimStatus", "Simulator XStatus")
884 { 870 {
885 m_opensim = sim; 871 m_opensim = sim;
886 osXStatsURI = Util.SHA1Hash(sim.osSecret);
887 } 872 }
888 873
889 public byte[] Handle(string path, Stream request, 874 protected override byte[] ProcessRequest(string path, Stream request,
890 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 875 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
891 { 876 {
892 return Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest)); 877 return Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest));
893 } 878 }
894 879
895 public string ContentType 880 public override string ContentType
896 { 881 {
897 get { return "text/plain"; } 882 get { return "text/plain"; }
898 } 883 }
899
900 public string HttpMethod
901 {
902 get { return "GET"; }
903 }
904
905 public string Path
906 {
907 // This is for the OpenSimulator instance and is the osSecret hashed
908 get { return "/" + osXStatsURI; }
909 }
910 } 884 }
911 885
912 /// <summary> 886 /// <summary>
@@ -915,42 +889,26 @@ namespace OpenSim
915 /// If the request contains a key, "callback" the response will be wrappend in the 889 /// If the request contains a key, "callback" the response will be wrappend in the
916 /// associated value for jsonp used with ajax/javascript 890 /// associated value for jsonp used with ajax/javascript
917 /// </summary> 891 /// </summary>
918 public class UXSimStatusHandler : IStreamedRequestHandler 892 protected class UXSimStatusHandler : BaseStreamHandler
919 { 893 {
920 OpenSimBase m_opensim; 894 OpenSimBase m_opensim;
921 string osUXStatsURI = String.Empty;
922
923 public string Name { get { return "UXSimStatus"; } }
924 public string Description { get { return "Simulator UXStatus"; } }
925 895
926 public UXSimStatusHandler(OpenSimBase sim) 896 public UXSimStatusHandler(OpenSimBase sim)
897 : base("GET", "/" + sim.userStatsURI, "UXSimStatus", "Simulator UXStatus")
927 { 898 {
928 m_opensim = sim; 899 m_opensim = sim;
929 osUXStatsURI = sim.userStatsURI;
930
931 } 900 }
932 901
933 public byte[] Handle(string path, Stream request, 902 protected override byte[] ProcessRequest(string path, Stream request,
934 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 903 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
935 { 904 {
936 return Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest)); 905 return Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest));
937 } 906 }
938 907
939 public string ContentType 908 public override string ContentType
940 { 909 {
941 get { return "text/plain"; } 910 get { return "text/plain"; }
942 } 911 }
943
944 public string HttpMethod
945 {
946 get { return "GET"; }
947 }
948
949 public string Path
950 {
951 // This is for the OpenSimulator instance and is the user provided URI
952 get { return "/" + osUXStatsURI; }
953 }
954 } 912 }
955 913
956 #endregion 914 #endregion
@@ -958,7 +916,7 @@ namespace OpenSim
958 /// <summary> 916 /// <summary>
959 /// Performs any last-minute sanity checking and shuts down the region server 917 /// Performs any last-minute sanity checking and shuts down the region server
960 /// </summary> 918 /// </summary>
961 public override void ShutdownSpecific() 919 protected override void ShutdownSpecific()
962 { 920 {
963 if (proxyUrl.Length > 0) 921 if (proxyUrl.Length > 0)
964 { 922 {
@@ -978,6 +936,8 @@ namespace OpenSim
978 { 936 {
979 m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e); 937 m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e);
980 } 938 }
939
940 base.ShutdownSpecific();
981 } 941 }
982 942
983 /// <summary> 943 /// <summary>
@@ -1025,7 +985,7 @@ namespace OpenSim
1025 regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, true); 985 regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, true);
1026 986
1027 string newName; 987 string newName;
1028 if (estateName != null && estateName != "") 988 if (!string.IsNullOrEmpty(estateName))
1029 newName = estateName; 989 newName = estateName;
1030 else 990 else
1031 newName = MainConsole.Instance.CmdPrompt("New estate name", regInfo.EstateSettings.EstateName); 991 newName = MainConsole.Instance.CmdPrompt("New estate name", regInfo.EstateSettings.EstateName);
diff --git a/OpenSim/Region/ClientStack/IClientNetworkServer.cs b/OpenSim/Region/ClientStack/IClientNetworkServer.cs
index 54a441b..bb7e6d0 100644
--- a/OpenSim/Region/ClientStack/IClientNetworkServer.cs
+++ b/OpenSim/Region/ClientStack/IClientNetworkServer.cs
@@ -38,11 +38,22 @@ namespace OpenSim.Region.ClientStack
38 IPAddress _listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, 38 IPAddress _listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource,
39 AgentCircuitManager authenticateClass); 39 AgentCircuitManager authenticateClass);
40 40
41 void NetworkStop();
42 bool HandlesRegion(Location x); 41 bool HandlesRegion(Location x);
43 void AddScene(IScene x);
44 42
43 /// <summary>
44 /// Add the given scene to be handled by this IClientNetworkServer.
45 /// </summary>
46 /// <param name='scene'></param>
47 void AddScene(IScene scene);
48
49 /// <summary>
50 /// Start sending and receiving data.
51 /// </summary>
45 void Start(); 52 void Start();
53
54 /// <summary>
55 /// Stop sending and receiving data.
56 /// </summary>
46 void Stop(); 57 void Stop();
47 } 58 }
48} 59}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs
new file mode 100644
index 0000000..bbadc55
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs
@@ -0,0 +1,136 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Specialized;
31using System.Drawing;
32using System.Drawing.Imaging;
33using System.Reflection;
34using System.IO;
35using System.Web;
36using log4net;
37using Nini.Config;
38using Mono.Addins;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41using OpenSim.Framework;
42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Servers.HttpServer;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes;
46using OpenSim.Services.Interfaces;
47using Caps = OpenSim.Framework.Capabilities.Caps;
48using OpenSim.Capabilities.Handlers;
49
50namespace OpenSim.Region.ClientStack.Linden
51{
52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AvatarPickerSearchModule")]
53 public class AvatarPickerSearchModule : INonSharedRegionModule
54 {
55// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 private Scene m_scene;
58 private IPeople m_People;
59 private bool m_Enabled = false;
60
61 private string m_URL;
62
63 #region ISharedRegionModule Members
64
65 public void Initialise(IConfigSource source)
66 {
67 IConfig config = source.Configs["ClientStack.LindenCaps"];
68 if (config == null)
69 return;
70
71 m_URL = config.GetString("Cap_AvatarPickerSearch", string.Empty);
72 // Cap doesn't exist
73 if (m_URL != string.Empty)
74 m_Enabled = true;
75 }
76
77 public void AddRegion(Scene s)
78 {
79 if (!m_Enabled)
80 return;
81
82 m_scene = s;
83 }
84
85 public void RemoveRegion(Scene s)
86 {
87 if (!m_Enabled)
88 return;
89
90 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
91 m_scene = null;
92 }
93
94 public void RegionLoaded(Scene s)
95 {
96 if (!m_Enabled)
97 return;
98
99 m_People = m_scene.RequestModuleInterface<IPeople>();
100 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
101 }
102
103 public void PostInitialise()
104 {
105 }
106
107 public void Close() { }
108
109 public string Name { get { return "AvatarPickerSearchModule"; } }
110
111 public Type ReplaceableInterface
112 {
113 get { return null; }
114 }
115
116 #endregion
117
118 public void RegisterCaps(UUID agentID, Caps caps)
119 {
120 UUID capID = UUID.Random();
121
122 if (m_URL == "localhost")
123 {
124// m_log.DebugFormat("[AVATAR PICKER SEARCH]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
125 caps.RegisterHandler(
126 "AvatarPickerSearch",
127 new AvatarPickerSearchHandler("/CAPS/" + capID + "/", m_People, "AvatarPickerSearch", "Search for avatars by name"));
128 }
129 else
130 {
131 // m_log.DebugFormat("[AVATAR PICKER SEARCH]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName);
132 caps.RegisterHandler("AvatarPickerSearch", m_URL);
133 }
134 }
135 }
136} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 8241e07..613bc24 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -282,13 +282,19 @@ namespace OpenSim.Region.ClientStack.Linden
282 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); 282 m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req);
283 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); 283 m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req);
284 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); 284 m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req);
285 IRequestHandler getObjectPhysicsDataHandler = new RestStreamHandler("POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData); 285
286 IRequestHandler getObjectPhysicsDataHandler
287 = new RestStreamHandler(
288 "POST", capsBase + m_getObjectPhysicsDataPath, GetObjectPhysicsData, "GetObjectPhysicsData", null);
286 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler); 289 m_HostCapsObj.RegisterHandler("GetObjectPhysicsData", getObjectPhysicsDataHandler);
287 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost); 290 IRequestHandler getObjectCostHandler = new RestStreamHandler("POST", capsBase + m_getObjectCostPath, GetObjectCost);
288 m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler); 291 m_HostCapsObj.RegisterHandler("GetObjectCost", getObjectCostHandler);
289 IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected); 292 IRequestHandler ResourceCostSelectedHandler = new RestStreamHandler("POST", capsBase + m_ResourceCostSelectedPath, ResourceCostSelected);
290 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler); 293 m_HostCapsObj.RegisterHandler("ResourceCostSelected", ResourceCostSelectedHandler);
291 IRequestHandler UpdateAgentInformationHandler = new RestStreamHandler("POST", capsBase + m_UpdateAgentInformationPath, UpdateAgentInformation); 294
295 IRequestHandler UpdateAgentInformationHandler
296 = new RestStreamHandler(
297 "POST", capsBase + m_UpdateAgentInformationPath, UpdateAgentInformation, "UpdateAgentInformation", null);
292 m_HostCapsObj.RegisterHandler("UpdateAgentInformation", UpdateAgentInformationHandler); 298 m_HostCapsObj.RegisterHandler("UpdateAgentInformation", UpdateAgentInformationHandler);
293 299
294 m_HostCapsObj.RegisterHandler( 300 m_HostCapsObj.RegisterHandler(
@@ -361,18 +367,7 @@ namespace OpenSim.Region.ClientStack.Linden
361 foreach (OSD c in capsRequested) 367 foreach (OSD c in capsRequested)
362 validCaps.Add(c.AsString()); 368 validCaps.Add(c.AsString());
363 369
364 Hashtable caps = m_HostCapsObj.CapsHandlers.GetCapsDetails(true, validCaps); 370 string result = LLSDHelpers.SerialiseLLSDReply(m_HostCapsObj.GetCapsDetails(true, validCaps));
365
366 // Add the external too
367 foreach (KeyValuePair<string, string> kvp in m_HostCapsObj.ExternalCapsHandlers)
368 {
369 if (!validCaps.Contains(kvp.Key))
370 continue;
371
372 caps[kvp.Key] = kvp.Value;
373 }
374
375 string result = LLSDHelpers.SerialiseLLSDReply(caps);
376 371
377 //m_log.DebugFormat("[CAPS] CapsRequest {0}", result); 372 //m_log.DebugFormat("[CAPS] CapsRequest {0}", result);
378 373
@@ -748,6 +743,10 @@ namespace OpenSim.Region.ClientStack.Linden
748 inType = (sbyte)InventoryType.Sound; 743 inType = (sbyte)InventoryType.Sound;
749 assType = (sbyte)AssetType.Sound; 744 assType = (sbyte)AssetType.Sound;
750 } 745 }
746 else if (inventoryType == "snapshot")
747 {
748 inType = (sbyte)InventoryType.Snapshot;
749 }
751 else if (inventoryType == "animation") 750 else if (inventoryType == "animation")
752 { 751 {
753 inType = (sbyte)InventoryType.Animation; 752 inType = (sbyte)InventoryType.Animation;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index eb40eb1..ffb53af 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -65,6 +65,13 @@ namespace OpenSim.Region.ClientStack.Linden
65 /// </value> 65 /// </value>
66 public int DebugLevel { get; set; } 66 public int DebugLevel { get; set; }
67 67
68 // Viewer post requests timeout in 60 secs
69 // https://bitbucket.org/lindenlab/viewer-release/src/421c20423df93d650cc305dc115922bb30040999/indra/llmessage/llhttpclient.cpp?at=default#cl-44
70 //
71 private const int VIEWER_TIMEOUT = 60 * 1000;
72 // Just to be safe, we work on a 10 sec shorter cycle
73 private const int SERVER_EQ_TIME_NO_EVENTS = VIEWER_TIMEOUT - (10 * 1000);
74
68 protected Scene m_scene; 75 protected Scene m_scene;
69 76
70 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>(); 77 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
@@ -84,7 +91,6 @@ namespace OpenSim.Region.ClientStack.Linden
84 scene.RegisterModuleInterface<IEventQueue>(this); 91 scene.RegisterModuleInterface<IEventQueue>(this);
85 92
86 scene.EventManager.OnClientClosed += ClientClosed; 93 scene.EventManager.OnClientClosed += ClientClosed;
87 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
88 scene.EventManager.OnRegisterCaps += OnRegisterCaps; 94 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
89 95
90 MainConsole.Instance.Commands.AddCommand( 96 MainConsole.Instance.Commands.AddCommand(
@@ -113,7 +119,6 @@ namespace OpenSim.Region.ClientStack.Linden
113 return; 119 return;
114 120
115 scene.EventManager.OnClientClosed -= ClientClosed; 121 scene.EventManager.OnClientClosed -= ClientClosed;
116 scene.EventManager.OnMakeChildAgent -= MakeChildAgent;
117 scene.EventManager.OnRegisterCaps -= OnRegisterCaps; 122 scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
118 123
119 scene.UnregisterModuleInterface<IEventQueue>(this); 124 scene.UnregisterModuleInterface<IEventQueue>(this);
@@ -182,14 +187,12 @@ namespace OpenSim.Region.ClientStack.Linden
182 { 187 {
183 if (!queues.ContainsKey(agentId)) 188 if (!queues.ContainsKey(agentId))
184 { 189 {
185 /*
186 m_log.DebugFormat( 190 m_log.DebugFormat(
187 "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}", 191 "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}",
188 agentId, m_scene.RegionInfo.RegionName); 192 agentId, m_scene.RegionInfo.RegionName);
189 */
190 queues[agentId] = new Queue<OSD>(); 193 queues[agentId] = new Queue<OSD>();
191 } 194 }
192 195
193 return queues[agentId]; 196 return queues[agentId];
194 } 197 }
195 } 198 }
@@ -221,8 +224,17 @@ namespace OpenSim.Region.ClientStack.Linden
221 { 224 {
222 Queue<OSD> queue = GetQueue(avatarID); 225 Queue<OSD> queue = GetQueue(avatarID);
223 if (queue != null) 226 if (queue != null)
227 {
224 lock (queue) 228 lock (queue)
225 queue.Enqueue(ev); 229 queue.Enqueue(ev);
230 }
231 else
232 {
233 OSDMap evMap = (OSDMap)ev;
234 m_log.WarnFormat(
235 "[EVENTQUEUE]: (Enqueue) No queue found for agent {0} when placing message {1} in region {2}",
236 avatarID, evMap["message"], m_scene.Name);
237 }
226 } 238 }
227 catch (NullReferenceException e) 239 catch (NullReferenceException e)
228 { 240 {
@@ -237,44 +249,14 @@ namespace OpenSim.Region.ClientStack.Linden
237 249
238 private void ClientClosed(UUID agentID, Scene scene) 250 private void ClientClosed(UUID agentID, Scene scene)
239 { 251 {
240// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); 252 //m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
241
242 int count = 0;
243 while (queues.ContainsKey(agentID) && queues[agentID].Count > 0 && count++ < 5)
244 {
245 Thread.Sleep(1000);
246 }
247 253
248 lock (queues) 254 lock (queues)
249 {
250 queues.Remove(agentID); 255 queues.Remove(agentID);
251 }
252 256
253 List<UUID> removeitems = new List<UUID>(); 257 List<UUID> removeitems = new List<UUID>();
254 lock (m_AvatarQueueUUIDMapping) 258 lock (m_AvatarQueueUUIDMapping)
255 { 259 m_AvatarQueueUUIDMapping.Remove(agentID);
256 foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
257 {
258// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID);
259 if (ky == agentID)
260 {
261 removeitems.Add(ky);
262 }
263 }
264
265 foreach (UUID ky in removeitems)
266 {
267 UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping[ky];
268 m_AvatarQueueUUIDMapping.Remove(ky);
269
270 string eqgPath = GenerateEqgCapPath(eventQueueGetUuid);
271 MainServer.Instance.RemovePollServiceHTTPHandler("", eqgPath);
272
273// m_log.DebugFormat(
274// "[EVENT QUEUE GET MODULE]: Removed EQG handler {0} for {1} in {2}",
275// eqgPath, agentID, m_scene.RegionInfo.RegionName);
276 }
277 }
278 260
279 UUID searchval = UUID.Zero; 261 UUID searchval = UUID.Zero;
280 262
@@ -295,19 +277,9 @@ namespace OpenSim.Region.ClientStack.Linden
295 foreach (UUID ky in removeitems) 277 foreach (UUID ky in removeitems)
296 m_QueueUUIDAvatarMapping.Remove(ky); 278 m_QueueUUIDAvatarMapping.Remove(ky);
297 } 279 }
298 }
299 280
300 private void MakeChildAgent(ScenePresence avatar) 281 // m_log.DebugFormat("[EVENTQUEUE]: Deleted queues for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
301 { 282
302 //m_log.DebugFormat("[EVENTQUEUE]: Make Child agent {0} in region {1}.", avatar.UUID, m_scene.RegionInfo.RegionName);
303 //lock (m_ids)
304 // {
305 //if (m_ids.ContainsKey(avatar.UUID))
306 //{
307 // close the event queue.
308 //m_ids[avatar.UUID] = -1;
309 //}
310 //}
311 } 283 }
312 284
313 /// <summary> 285 /// <summary>
@@ -323,9 +295,9 @@ namespace OpenSim.Region.ClientStack.Linden
323 { 295 {
324 // Register an event queue for the client 296 // Register an event queue for the client
325 297
326 //m_log.DebugFormat( 298 m_log.DebugFormat(
327 // "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}", 299 "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
328 // agentID, caps, m_scene.RegionInfo.RegionName); 300 agentID, caps, m_scene.RegionInfo.RegionName);
329 301
330 // Let's instantiate a Queue for this agent right now 302 // Let's instantiate a Queue for this agent right now
331 TryGetQueue(agentID); 303 TryGetQueue(agentID);
@@ -359,28 +331,9 @@ namespace OpenSim.Region.ClientStack.Linden
359 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID); 331 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
360 } 332 }
361 333
362 string eventQueueGetPath = GenerateEqgCapPath(eventQueueGetUUID); 334 caps.RegisterPollHandler(
363 335 "EventQueueGet",
364 // Register this as a caps handler 336 new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS));
365 // FIXME: Confusingly, we need to register separate as a capability so that the client is told about
366 // EventQueueGet when it receive capability information, but then we replace the rest handler immediately
367 // afterwards with the poll service. So for now, we'll pass a null instead to simplify code reading, but
368 // really it should be possible to directly register the poll handler as a capability.
369 caps.RegisterHandler("EventQueueGet", new RestHTTPHandler("POST", eventQueueGetPath, null));
370// delegate(Hashtable m_dhttpMethod)
371// {
372// return ProcessQueue(m_dhttpMethod, agentID, caps);
373// }));
374
375 // This will persist this beyond the expiry of the caps handlers
376 // TODO: Add EventQueueGet name/description for diagnostics
377 MainServer.Instance.AddPollServiceHTTPHandler(
378 eventQueueGetPath,
379 new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID, 40000));
380
381// m_log.DebugFormat(
382// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}",
383// eventQueueGetPath, agentID, m_scene.RegionInfo.RegionName);
384 337
385 Random rnd = new Random(Environment.TickCount); 338 Random rnd = new Random(Environment.TickCount);
386 lock (m_ids) 339 lock (m_ids)
@@ -398,7 +351,10 @@ namespace OpenSim.Region.ClientStack.Linden
398 Queue<OSD> queue = GetQueue(agentID); 351 Queue<OSD> queue = GetQueue(agentID);
399 if (queue != null) 352 if (queue != null)
400 lock (queue) 353 lock (queue)
354 {
355 //m_log.WarnFormat("POLLED FOR EVENTS BY {0} in {1} -- {2}", agentID, m_scene.RegionInfo.RegionName, queue.Count);
401 return queue.Count > 0; 356 return queue.Count > 0;
357 }
402 358
403 return false; 359 return false;
404 } 360 }
@@ -414,16 +370,21 @@ namespace OpenSim.Region.ClientStack.Linden
414 OSDMap ev = (OSDMap)element; 370 OSDMap ev = (OSDMap)element;
415 m_log.DebugFormat( 371 m_log.DebugFormat(
416 "Eq OUT {0,-30} to {1,-20} {2,-20}", 372 "Eq OUT {0,-30} to {1,-20} {2,-20}",
417 ev["message"], m_scene.GetScenePresence(agentId).Name, m_scene.RegionInfo.RegionName); 373 ev["message"], m_scene.GetScenePresence(agentId).Name, m_scene.Name);
418 } 374 }
419 } 375 }
420 376
421 public Hashtable GetEvents(UUID requestID, UUID pAgentId) 377 public Hashtable GetEvents(UUID requestID, UUID pAgentId)
422 { 378 {
423 if (DebugLevel >= 2) 379 if (DebugLevel >= 2)
424 m_log.DebugFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.RegionInfo.RegionName); 380 m_log.WarnFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.Name);
381
382 Queue<OSD> queue = GetQueue(pAgentId);
383 if (queue == null)
384 {
385 return NoEvents(requestID, pAgentId);
386 }
425 387
426 Queue<OSD> queue = TryGetQueue(pAgentId);
427 OSD element; 388 OSD element;
428 lock (queue) 389 lock (queue)
429 { 390 {
@@ -750,34 +711,46 @@ namespace OpenSim.Region.ClientStack.Linden
750 Enqueue(item, avatarID); 711 Enqueue(item, avatarID);
751 } 712 }
752 713
753 public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID) 714 public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY)
754 { 715 {
755 OSD item = EventQueueHelper.EnableSimulator(handle, endPoint); 716 m_log.DebugFormat("{0} EnableSimulator. handle={1}, avatarID={2}, regionSize={3},{4}>",
717 "[EVENT QUEUE GET MODULE]", handle, avatarID, regionSizeX, regionSizeY);
718
719 OSD item = EventQueueHelper.EnableSimulator(handle, endPoint, regionSizeX, regionSizeY);
756 Enqueue(item, avatarID); 720 Enqueue(item, avatarID);
757 } 721 }
758 722
759 public virtual void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath) 723 public virtual void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath,
724 ulong regionHandle, int regionSizeX, int regionSizeY)
760 { 725 {
761 OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath); 726 m_log.DebugFormat("{0} EstablishAgentCommunication. handle={1}, avatarID={2}, regionSize={3},{4}>",
727 "[EVENT QUEUE GET MODULE]", regionHandle, avatarID, regionSizeX, regionSizeY);
728 OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath, regionHandle, regionSizeX, regionSizeY);
762 Enqueue(item, avatarID); 729 Enqueue(item, avatarID);
763 } 730 }
764 731
765 public virtual void TeleportFinishEvent(ulong regionHandle, byte simAccess, 732 public virtual void TeleportFinishEvent(ulong regionHandle, byte simAccess,
766 IPEndPoint regionExternalEndPoint, 733 IPEndPoint regionExternalEndPoint,
767 uint locationID, uint flags, string capsURL, 734 uint locationID, uint flags, string capsURL,
768 UUID avatarID) 735 UUID avatarID, int regionSizeX, int regionSizeY)
769 { 736 {
737 m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, avatarID={2}, regionSize={3},{4}>",
738 "[EVENT QUEUE GET MODULE]", regionHandle, avatarID, regionSizeX, regionSizeY);
739
770 OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint, 740 OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint,
771 locationID, flags, capsURL, avatarID); 741 locationID, flags, capsURL, avatarID, regionSizeX, regionSizeY);
772 Enqueue(item, avatarID); 742 Enqueue(item, avatarID);
773 } 743 }
774 744
775 public virtual void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, 745 public virtual void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
776 IPEndPoint newRegionExternalEndPoint, 746 IPEndPoint newRegionExternalEndPoint,
777 string capsURL, UUID avatarID, UUID sessionID) 747 string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY)
778 { 748 {
749 m_log.DebugFormat("{0} CrossRegion. handle={1}, avatarID={2}, regionSize={3},{4}>",
750 "[EVENT QUEUE GET MODULE]", handle, avatarID, regionSizeX, regionSizeY);
751
779 OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint, 752 OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint,
780 capsURL, avatarID, sessionID); 753 capsURL, avatarID, sessionID, regionSizeX, regionSizeY);
781 Enqueue(item, avatarID); 754 Enqueue(item, avatarID);
782 } 755 }
783 756
@@ -794,12 +767,12 @@ namespace OpenSim.Region.ClientStack.Linden
794 767
795 } 768 }
796 769
797 public void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat, 770 public void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, bool canVoiceChat,
798 bool isModerator, bool textMute) 771 bool isModerator, bool textMute)
799 { 772 {
800 OSD item = EventQueueHelper.ChatterBoxSessionAgentListUpdates(sessionID, fromAgent, canVoiceChat, 773 OSD item = EventQueueHelper.ChatterBoxSessionAgentListUpdates(sessionID, fromAgent, canVoiceChat,
801 isModerator, textMute); 774 isModerator, textMute);
802 Enqueue(item, toAgent); 775 Enqueue(item, fromAgent);
803 //m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item); 776 //m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item);
804 } 777 }
805 778
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
index 7dcf137..3fb7de2 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
@@ -70,13 +70,15 @@ namespace OpenSim.Region.ClientStack.Linden
70 return llsdEvent; 70 return llsdEvent;
71 } 71 }
72 72
73 public static OSD EnableSimulator(ulong handle, IPEndPoint endPoint) 73 public static OSD EnableSimulator(ulong handle, IPEndPoint endPoint, int regionSizeX, int regionSizeY)
74 { 74 {
75 OSDMap llsdSimInfo = new OSDMap(3); 75 OSDMap llsdSimInfo = new OSDMap(5);
76 76
77 llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle))); 77 llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle)));
78 llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes())); 78 llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes()));
79 llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port)); 79 llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port));
80 llsdSimInfo.Add("RegionSizeX", new OSDInteger(regionSizeX));
81 llsdSimInfo.Add("RegionSizeY", new OSDInteger(regionSizeY));
80 82
81 OSDArray arr = new OSDArray(1); 83 OSDArray arr = new OSDArray(1);
82 arr.Add(llsdSimInfo); 84 arr.Add(llsdSimInfo);
@@ -104,7 +106,8 @@ namespace OpenSim.Region.ClientStack.Linden
104 106
105 public static OSD CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, 107 public static OSD CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
106 IPEndPoint newRegionExternalEndPoint, 108 IPEndPoint newRegionExternalEndPoint,
107 string capsURL, UUID agentID, UUID sessionID) 109 string capsURL, UUID agentID, UUID sessionID,
110 int regionSizeX, int regionSizeY)
108 { 111 {
109 OSDArray lookAtArr = new OSDArray(3); 112 OSDArray lookAtArr = new OSDArray(3);
110 lookAtArr.Add(OSD.FromReal(lookAt.X)); 113 lookAtArr.Add(OSD.FromReal(lookAt.X));
@@ -130,11 +133,13 @@ namespace OpenSim.Region.ClientStack.Linden
130 OSDArray agentDataArr = new OSDArray(1); 133 OSDArray agentDataArr = new OSDArray(1);
131 agentDataArr.Add(agentDataMap); 134 agentDataArr.Add(agentDataMap);
132 135
133 OSDMap regionDataMap = new OSDMap(4); 136 OSDMap regionDataMap = new OSDMap(6);
134 regionDataMap.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(handle))); 137 regionDataMap.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(handle)));
135 regionDataMap.Add("SeedCapability", OSD.FromString(capsURL)); 138 regionDataMap.Add("SeedCapability", OSD.FromString(capsURL));
136 regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes())); 139 regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes()));
137 regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port)); 140 regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port));
141 regionDataMap.Add("RegionSizeX", new OSDInteger(regionSizeX));
142 regionDataMap.Add("RegionSizeY", new OSDInteger(regionSizeY));
138 143
139 OSDArray regionDataArr = new OSDArray(1); 144 OSDArray regionDataArr = new OSDArray(1);
140 regionDataArr.Add(regionDataMap); 145 regionDataArr.Add(regionDataMap);
@@ -148,8 +153,9 @@ namespace OpenSim.Region.ClientStack.Linden
148 } 153 }
149 154
150 public static OSD TeleportFinishEvent( 155 public static OSD TeleportFinishEvent(
151 ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, 156 ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
152 uint locationID, uint flags, string capsURL, UUID agentID) 157 uint locationID, uint flags, string capsURL, UUID agentID,
158 int regionSizeX, int regionSizeY)
153 { 159 {
154 // not sure why flags get overwritten here 160 // not sure why flags get overwritten here
155 if ((flags & (uint)TeleportFlags.IsFlying) != 0) 161 if ((flags & (uint)TeleportFlags.IsFlying) != 0)
@@ -167,6 +173,8 @@ namespace OpenSim.Region.ClientStack.Linden
167 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port)); 173 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port));
168// info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation 174// info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation
169 info.Add("TeleportFlags", OSD.FromUInteger(flags)); 175 info.Add("TeleportFlags", OSD.FromUInteger(flags));
176 info.Add("RegionSizeX", new OSDInteger(regionSizeX));
177 info.Add("RegionSizeY", new OSDInteger(regionSizeY));
170 178
171 OSDArray infoArr = new OSDArray(); 179 OSDArray infoArr = new OSDArray();
172 infoArr.Add(info); 180 infoArr.Add(info);
@@ -194,12 +202,18 @@ namespace OpenSim.Region.ClientStack.Linden
194 return BuildEvent("ScriptRunningReply", body); 202 return BuildEvent("ScriptRunningReply", body);
195 } 203 }
196 204
197 public static OSD EstablishAgentCommunication(UUID agentID, string simIpAndPort, string seedcap) 205 public static OSD EstablishAgentCommunication(UUID agentID, string simIpAndPort, string seedcap,
206 ulong regionHandle, int regionSizeX, int regionSizeY)
198 { 207 {
199 OSDMap body = new OSDMap(3); 208 OSDMap body = new OSDMap(6)
200 body.Add("agent-id", new OSDUUID(agentID)); 209 {
201 body.Add("sim-ip-and-port", new OSDString(simIpAndPort)); 210 {"agent-id", new OSDUUID(agentID)},
202 body.Add("seed-capability", new OSDString(seedcap)); 211 {"sim-ip-and-port", new OSDString(simIpAndPort)},
212 {"seed-capability", new OSDString(seedcap)},
213 {"region-handle", OSD.FromULong(regionHandle)},
214 {"region-size-x", OSD.FromInteger(regionSizeX)},
215 {"region-size-y", OSD.FromInteger(regionSizeY)}
216 };
203 217
204 return BuildEvent("EstablishAgentCommunication", body); 218 return BuildEvent("EstablishAgentCommunication", body);
205 } 219 }
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index 141af8a..9e24bce 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
76 } 76 }
77 77
78 [Test] 78 [Test]
79 public void AddForClient() 79 public void TestAddForClient()
80 { 80 {
81 TestHelpers.InMethod(); 81 TestHelpers.InMethod();
82// log4net.Config.XmlConfigurator.Configure(); 82// log4net.Config.XmlConfigurator.Configure();
@@ -88,15 +88,15 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
88 } 88 }
89 89
90 [Test] 90 [Test]
91 public void RemoveForClient() 91 public void TestRemoveForClient()
92 { 92 {
93 TestHelpers.InMethod(); 93 TestHelpers.InMethod();
94// log4net.Config.XmlConfigurator.Configure(); 94// TestHelpers.EnableLogging();
95 95
96 UUID spId = TestHelpers.ParseTail(0x1); 96 UUID spId = TestHelpers.ParseTail(0x1);
97 97
98 SceneHelpers.AddScenePresence(m_scene, spId); 98 SceneHelpers.AddScenePresence(m_scene, spId);
99 m_scene.IncomingCloseAgent(spId, false); 99 m_scene.CloseAgent(spId, false);
100 100
101 // TODO: Add more assertions for the other aspects of event queues 101 // TODO: Add more assertions for the other aspects of event queues
102 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); 102 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
index 6ec1115..7b15284 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs
@@ -246,8 +246,8 @@ namespace OpenSim.Region.ClientStack.Linden
246 246
247 private Scene m_scene; 247 private Scene m_scene;
248 private MeshCapsDataThrottler m_throttler; 248 private MeshCapsDataThrottler m_throttler;
249 public PollServiceMeshEventArgs(UUID pId, Scene scene) : 249 public PollServiceMeshEventArgs(string uri, UUID pId, Scene scene) :
250 base(null, null, null, null, pId, int.MaxValue) 250 base(null, uri, null, null, null, pId, int.MaxValue)
251 { 251 {
252 m_scene = scene; 252 m_scene = scene;
253 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId); 253 m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId);
@@ -361,7 +361,7 @@ namespace OpenSim.Region.ClientStack.Linden
361 string capUrl = "/CAPS/" + UUID.Random() + "/"; 361 string capUrl = "/CAPS/" + UUID.Random() + "/";
362 362
363 // Register this as a poll service 363 // Register this as a poll service
364 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(agentID, m_scene); 364 PollServiceMeshEventArgs args = new PollServiceMeshEventArgs(capUrl, agentID, m_scene);
365 365
366 args.Type = PollServiceEventArgs.EventType.Mesh; 366 args.Type = PollServiceEventArgs.EventType.Mesh;
367 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); 367 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
index 0570144..e053054 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs
@@ -84,6 +84,8 @@ namespace OpenSim.Region.ClientStack.Linden
84 84
85 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>(); 85 private Dictionary<UUID,PollServiceTextureEventArgs> m_pollservices = new Dictionary<UUID,PollServiceTextureEventArgs>();
86 86
87 private string m_URL;
88
87 #region ISharedRegionModule Members 89 #region ISharedRegionModule Members
88 90
89 public void Initialise(IConfigSource source) 91 public void Initialise(IConfigSource source)
@@ -215,7 +217,7 @@ namespace OpenSim.Region.ClientStack.Linden
215 private Scene m_scene; 217 private Scene m_scene;
216 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000); 218 private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000);
217 public PollServiceTextureEventArgs(UUID pId, Scene scene) : 219 public PollServiceTextureEventArgs(UUID pId, Scene scene) :
218 base(null, null, null, null, pId, int.MaxValue) 220 base(null, "", null, null, null, pId, int.MaxValue)
219 { 221 {
220 m_scene = scene; 222 m_scene = scene;
221 // x is request id, y is userid 223 // x is request id, y is userid
@@ -368,7 +370,11 @@ namespace OpenSim.Region.ClientStack.Linden
368 port = MainServer.Instance.SSLPort; 370 port = MainServer.Instance.SSLPort;
369 protocol = "https"; 371 protocol = "https";
370 } 372 }
371 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl)); 373 IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>();
374 if (handler != null)
375 handler.RegisterExternalUserCapsHandler(agentID, caps, "GetTexture", capUrl);
376 else
377 caps.RegisterHandler("GetTexture", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
372 m_pollservices[agentID] = args; 378 m_pollservices[agentID] = args;
373 m_capsDict[agentID] = capUrl; 379 m_capsDict[agentID] = capUrl;
374 } 380 }
@@ -380,13 +386,11 @@ namespace OpenSim.Region.ClientStack.Linden
380 386
381 private void DeregisterCaps(UUID agentID, Caps caps) 387 private void DeregisterCaps(UUID agentID, Caps caps)
382 { 388 {
383 string capUrl;
384 PollServiceTextureEventArgs args; 389 PollServiceTextureEventArgs args;
385 if (m_capsDict.TryGetValue(agentID, out capUrl)) 390
386 { 391 MainServer.Instance.RemoveHTTPHandler("", m_URL);
387 MainServer.Instance.RemoveHTTPHandler("", capUrl); 392 m_capsDict.Remove(agentID);
388 m_capsDict.Remove(agentID); 393
389 }
390 if (m_pollservices.TryGetValue(agentID, out args)) 394 if (m_pollservices.TryGetValue(agentID, out args))
391 { 395 {
392 m_pollservices.Remove(agentID); 396 m_pollservices.Remove(agentID);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
index 92805e2..94f8bc1 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
@@ -155,6 +155,7 @@ namespace OpenSim.Region.ClientStack.Linden
155 Quaternion rotation = Quaternion.Identity; 155 Quaternion rotation = Quaternion.Identity;
156 Vector3 scale = Vector3.Zero; 156 Vector3 scale = Vector3.Zero;
157 int state = 0; 157 int state = 0;
158 int lastattach = 0;
158 159
159 if (r.Type != OSDType.Map) // not a proper req 160 if (r.Type != OSDType.Map) // not a proper req
160 return responsedata; 161 return responsedata;
@@ -224,6 +225,7 @@ namespace OpenSim.Region.ClientStack.Linden
224 225
225 ray_target_id = ObjMap["RayTargetId"].AsUUID(); 226 ray_target_id = ObjMap["RayTargetId"].AsUUID();
226 state = ObjMap["State"].AsInteger(); 227 state = ObjMap["State"].AsInteger();
228 lastattach = ObjMap["LastAttachPoint"].AsInteger();
227 try 229 try
228 { 230 {
229 ray_end = ((OSDArray)ObjMap["RayEnd"]).AsVector3(); 231 ray_end = ((OSDArray)ObjMap["RayEnd"]).AsVector3();
@@ -290,6 +292,7 @@ namespace OpenSim.Region.ClientStack.Linden
290 292
291 //session_id = rm["session_id"].AsUUID(); 293 //session_id = rm["session_id"].AsUUID();
292 state = rm["state"].AsInteger(); 294 state = rm["state"].AsInteger();
295 lastattach = rm["last_attach_point"].AsInteger();
293 try 296 try
294 { 297 {
295 ray_end = ((OSDArray)rm["ray_end"]).AsVector3(); 298 ray_end = ((OSDArray)rm["ray_end"]).AsVector3();
@@ -331,6 +334,7 @@ namespace OpenSim.Region.ClientStack.Linden
331 pbs.ProfileEnd = (ushort)profile_end; 334 pbs.ProfileEnd = (ushort)profile_end;
332 pbs.Scale = scale; 335 pbs.Scale = scale;
333 pbs.State = (byte)state; 336 pbs.State = (byte)state;
337 pbs.LastAttachPoint = (byte)lastattach;
334 338
335 SceneObjectGroup obj = null; ; 339 SceneObjectGroup obj = null; ;
336 340
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
index 55a503e..769fe28 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
@@ -277,6 +277,7 @@ namespace OpenSim.Region.ClientStack.Linden
277 pbs.ProfileEnd = (ushort) obj.ProfileEnd; 277 pbs.ProfileEnd = (ushort) obj.ProfileEnd;
278 pbs.Scale = obj.Scale; 278 pbs.Scale = obj.Scale;
279 pbs.State = (byte) 0; 279 pbs.State = (byte) 0;
280 pbs.LastAttachPoint = (byte) 0;
280 SceneObjectPart prim = new SceneObjectPart(); 281 SceneObjectPart prim = new SceneObjectPart();
281 prim.UUID = UUID.Random(); 282 prim.UUID = UUID.Random();
282 prim.CreatorID = AgentId; 283 prim.CreatorID = AgentId;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
index 595d01a..112608b 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
index 79d56c4..5196368 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
@@ -183,7 +183,7 @@ namespace OpenSim.Region.ClientStack.Linden
183 m_isGod = m_scene.Permissions.IsGod(agentID); 183 m_isGod = m_scene.Permissions.IsGod(agentID);
184 } 184 }
185 185
186 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 186 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
187 { 187 {
188 StreamReader reader = new StreamReader(request); 188 StreamReader reader = new StreamReader(request);
189 string message = reader.ReadToEnd(); 189 string message = reader.ReadToEnd();
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
index 7d9f935..e4d8a20 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
@@ -68,7 +68,6 @@ namespace OpenSim.Region.ClientStack.Linden
68 /// </summary> 68 /// </summary>
69 private OSDMap m_features = new OSDMap(); 69 private OSDMap m_features = new OSDMap();
70 70
71 private string m_MapImageServerURL = string.Empty;
72 private string m_SearchURL = string.Empty; 71 private string m_SearchURL = string.Empty;
73 private bool m_ExportSupported = false; 72 private bool m_ExportSupported = false;
74 73
@@ -78,15 +77,7 @@ namespace OpenSim.Region.ClientStack.Linden
78 { 77 {
79 IConfig config = source.Configs["SimulatorFeatures"]; 78 IConfig config = source.Configs["SimulatorFeatures"];
80 if (config != null) 79 if (config != null)
81 { 80 {
82 m_MapImageServerURL = config.GetString("MapImageServerURI", string.Empty);
83 if (m_MapImageServerURL != string.Empty)
84 {
85 m_MapImageServerURL = m_MapImageServerURL.Trim();
86 if (!m_MapImageServerURL.EndsWith("/"))
87 m_MapImageServerURL = m_MapImageServerURL + "/";
88 }
89
90 m_SearchURL = config.GetString("SearchServerURI", string.Empty); 81 m_SearchURL = config.GetString("SearchServerURI", string.Empty);
91 82
92 m_ExportSupported = config.GetBoolean("ExportSupported", m_ExportSupported); 83 m_ExportSupported = config.GetBoolean("ExportSupported", m_ExportSupported);
@@ -149,15 +140,16 @@ namespace OpenSim.Region.ClientStack.Linden
149 m_features["PhysicsShapeTypes"] = typesMap; 140 m_features["PhysicsShapeTypes"] = typesMap;
150 141
151 // Extra information for viewers that want to use it 142 // Extra information for viewers that want to use it
152 OSDMap gridServicesMap = new OSDMap(); 143 // TODO: Take these out of here into their respective modules, like map-server-url
153 if (m_MapImageServerURL != string.Empty) 144 OSDMap extrasMap = new OSDMap();
154 gridServicesMap["map-server-url"] = m_MapImageServerURL;
155 if (m_SearchURL != string.Empty) 145 if (m_SearchURL != string.Empty)
156 gridServicesMap["search"] = m_SearchURL; 146 extrasMap["search-server-url"] = m_SearchURL;
157 m_features["GridServices"] = gridServicesMap;
158
159 if (m_ExportSupported) 147 if (m_ExportSupported)
160 m_features["ExportSupported"] = true; 148 extrasMap["ExportSupported"] = true;
149
150 if (extrasMap.Count > 0)
151 m_features["OpenSimExtras"] = extrasMap;
152
161 } 153 }
162 } 154 }
163 155
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
index eca576d..47988dd 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
@@ -64,11 +64,18 @@ namespace OpenSim.Region.ClientStack.Linden
64 64
65 private Scene m_scene; 65 private Scene m_scene;
66 private bool m_persistBakedTextures; 66 private bool m_persistBakedTextures;
67 private string m_URL;
67 68
68 private IBakedTextureModule m_BakedTextureModule; 69 private IBakedTextureModule m_BakedTextureModule;
69 70
70 public void Initialise(IConfigSource source) 71 public void Initialise(IConfigSource source)
71 { 72 {
73 IConfig config = source.Configs["ClientStack.LindenCaps"];
74 if (config == null)
75 return;
76
77 m_URL = config.GetString("Cap_UploadBakedTexture", string.Empty);
78
72 IConfig appearanceConfig = source.Configs["Appearance"]; 79 IConfig appearanceConfig = source.Configs["Appearance"];
73 if (appearanceConfig != null) 80 if (appearanceConfig != null)
74 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); 81 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
@@ -280,23 +287,28 @@ namespace OpenSim.Region.ClientStack.Linden
280 287
281 public void RegisterCaps(UUID agentID, Caps caps) 288 public void RegisterCaps(UUID agentID, Caps caps)
282 { 289 {
283 UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler( 290// UUID capID = UUID.Random();
284 caps, m_scene.AssetService, m_persistBakedTextures);
285 291
286 292 //caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture));
287 293 if (m_URL == "localhost")
288 caps.RegisterHandler( 294 {
289 "UploadBakedTexture", 295 UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler(
290 new RestStreamHandler( 296 caps, m_scene.AssetService, m_persistBakedTextures);
291 "POST",
292 "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
293 avatarhandler.UploadBakedTexture,
294 "UploadBakedTexture",
295 agentID.ToString()));
296
297
298
299 297
298 caps.RegisterHandler(
299 "UploadBakedTexture",
300 new RestStreamHandler(
301 "POST",
302 "/CAPS/" + caps.CapsObjectPath + m_uploadBakedTexturePath,
303 avatarhandler.UploadBakedTexture,
304 "UploadBakedTexture",
305 agentID.ToString()));
306
307 }
308 else
309 {
310 caps.RegisterHandler("UploadBakedTexture", m_URL);
311 }
300 } 312 }
301 } 313 }
302} \ No newline at end of file 314}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 707cc93..6fc35cd 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -71,9 +71,13 @@ namespace OpenSim.Region.ClientStack.Linden
71 private IInventoryService m_InventoryService; 71 private IInventoryService m_InventoryService;
72 private ILibraryService m_LibraryService; 72 private ILibraryService m_LibraryService;
73 73
74 private bool m_Enabled;
75
76 private string m_fetchInventoryDescendents2Url;
77 private string m_webFetchInventoryDescendentsUrl;
78
74 private static WebFetchInvDescHandler m_webFetchHandler; 79 private static WebFetchInvDescHandler m_webFetchHandler;
75 80
76 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
77 private static Thread[] m_workerThreads = null; 81 private static Thread[] m_workerThreads = null;
78 82
79 private static DoubleQueue<aPollRequest> m_queue = 83 private static DoubleQueue<aPollRequest> m_queue =
@@ -83,22 +87,45 @@ namespace OpenSim.Region.ClientStack.Linden
83 87
84 public void Initialise(IConfigSource source) 88 public void Initialise(IConfigSource source)
85 { 89 {
90 IConfig config = source.Configs["ClientStack.LindenCaps"];
91 if (config == null)
92 return;
93
94 m_fetchInventoryDescendents2Url = config.GetString("Cap_FetchInventoryDescendents2", string.Empty);
95 m_webFetchInventoryDescendentsUrl = config.GetString("Cap_WebFetchInventoryDescendents", string.Empty);
96
97 if (m_fetchInventoryDescendents2Url != string.Empty || m_webFetchInventoryDescendentsUrl != string.Empty)
98 {
99 m_Enabled = true;
100 }
86 } 101 }
87 102
88 public void AddRegion(Scene s) 103 public void AddRegion(Scene s)
89 { 104 {
105 if (!m_Enabled)
106 return;
107
90 m_scene = s; 108 m_scene = s;
91 } 109 }
92 110
93 public void RemoveRegion(Scene s) 111 public void RemoveRegion(Scene s)
94 { 112 {
113 if (!m_Enabled)
114 return;
115
95 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 116 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
96 m_scene.EventManager.OnDeregisterCaps -= DeregisterCaps; 117
118 foreach (Thread t in m_workerThreads)
119 Watchdog.AbortThread(t.ManagedThreadId);
120
97 m_scene = null; 121 m_scene = null;
98 } 122 }
99 123
100 public void RegionLoaded(Scene s) 124 public void RegionLoaded(Scene s)
101 { 125 {
126 if (!m_Enabled)
127 return;
128
102 m_InventoryService = m_scene.InventoryService; 129 m_InventoryService = m_scene.InventoryService;
103 m_LibraryService = m_scene.LibraryService; 130 m_LibraryService = m_scene.LibraryService;
104 131
@@ -106,7 +133,6 @@ namespace OpenSim.Region.ClientStack.Linden
106 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService); 133 m_webFetchHandler = new WebFetchInvDescHandler(m_InventoryService, m_LibraryService);
107 134
108 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 135 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
109 m_scene.EventManager.OnDeregisterCaps += DeregisterCaps;
110 136
111 if (m_workerThreads == null) 137 if (m_workerThreads == null)
112 { 138 {
@@ -140,12 +166,6 @@ namespace OpenSim.Region.ClientStack.Linden
140 166
141 #endregion 167 #endregion
142 168
143 ~WebFetchInvDescModule()
144 {
145 foreach (Thread t in m_workerThreads)
146 Watchdog.AbortThread(t.ManagedThreadId);
147 }
148
149 private class PollServiceInventoryEventArgs : PollServiceEventArgs 169 private class PollServiceInventoryEventArgs : PollServiceEventArgs
150 { 170 {
151 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 171 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -155,8 +175,8 @@ namespace OpenSim.Region.ClientStack.Linden
155 175
156 private Scene m_scene; 176 private Scene m_scene;
157 177
158 public PollServiceInventoryEventArgs(Scene scene, UUID pId) : 178 public PollServiceInventoryEventArgs(Scene scene, string url, UUID pId) :
159 base(null, null, null, null, pId, int.MaxValue) 179 base(null, url, null, null, null, pId, int.MaxValue)
160 { 180 {
161 m_scene = scene; 181 m_scene = scene;
162 182
@@ -278,53 +298,72 @@ namespace OpenSim.Region.ClientStack.Linden
278 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null); 298 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
279 299
280 lock (responses) 300 lock (responses)
281 responses[requestID] = response; 301 responses[requestID] = response;
282 } 302 }
283 } 303 }
284 304
285 private void RegisterCaps(UUID agentID, Caps caps) 305 private void RegisterCaps(UUID agentID, Caps caps)
286 { 306 {
287 string capUrl = "/CAPS/" + UUID.Random() + "/"; 307 RegisterFetchDescendentsCap(agentID, caps, "FetchInventoryDescendents2", m_fetchInventoryDescendents2Url);
288
289 // Register this as a poll service
290 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(m_scene, agentID);
291
292 args.Type = PollServiceEventArgs.EventType.Inventory;
293 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
294
295 string hostName = m_scene.RegionInfo.ExternalHostName;
296 uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
297 string protocol = "http";
298
299 if (MainServer.Instance.UseSSL)
300 {
301 hostName = MainServer.Instance.SSLCommonName;
302 port = MainServer.Instance.SSLPort;
303 protocol = "https";
304 }
305 caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
306
307 m_capsDict[agentID] = capUrl;
308 } 308 }
309 309
310 private void DeregisterCaps(UUID agentID, Caps caps) 310 private void RegisterFetchDescendentsCap(UUID agentID, Caps caps, string capName, string url)
311 { 311 {
312 string capUrl; 312 string capUrl;
313 313
314 if (m_capsDict.TryGetValue(agentID, out capUrl)) 314 // disable the cap clause
315 if (url == "")
316 {
317 return;
318 }
319 // handled by the simulator
320 else if (url == "localhost")
321 {
322 capUrl = "/CAPS/" + UUID.Random() + "/";
323
324 // Register this as a poll service
325 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(m_scene, capUrl, agentID);
326 args.Type = PollServiceEventArgs.EventType.Inventory;
327
328 caps.RegisterPollHandler(capName, args);
329 }
330 // external handler
331 else
315 { 332 {
316 MainServer.Instance.RemoveHTTPHandler("", capUrl); 333 capUrl = url;
317 m_capsDict.Remove(agentID); 334 IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>();
335 if (handler != null)
336 handler.RegisterExternalUserCapsHandler(agentID,caps,capName,capUrl);
337 else
338 caps.RegisterHandler(capName, capUrl);
318 } 339 }
340
341 // m_log.DebugFormat(
342 // "[FETCH INVENTORY DESCENDENTS2 MODULE]: Registered capability {0} at {1} in region {2} for {3}",
343 // capName, capUrl, m_scene.RegionInfo.RegionName, agentID);
319 } 344 }
320 345
346// private void DeregisterCaps(UUID agentID, Caps caps)
347// {
348// string capUrl;
349//
350// if (m_capsDict.TryGetValue(agentID, out capUrl))
351// {
352// MainServer.Instance.RemoveHTTPHandler("", capUrl);
353// m_capsDict.Remove(agentID);
354// }
355// }
356
321 private void DoInventoryRequests() 357 private void DoInventoryRequests()
322 { 358 {
323 while (true) 359 while (true)
324 { 360 {
361 Watchdog.UpdateThread();
362
325 aPollRequest poolreq = m_queue.Dequeue(); 363 aPollRequest poolreq = m_queue.Dequeue();
326 364
327 poolreq.thepoll.Process(poolreq); 365 if (poolreq != null && poolreq.thepoll != null)
366 poolreq.thepoll.Process(poolreq);
328 } 367 }
329 } 368 }
330 } 369 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
index 3995620..15d6f7f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
@@ -424,12 +424,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
424 // foreign user is visiting, we need to try again after the first fail to the local 424 // foreign user is visiting, we need to try again after the first fail to the local
425 // asset service. 425 // asset service.
426 string assetServerURL = string.Empty; 426 string assetServerURL = string.Empty;
427 if (InventoryAccessModule.IsForeignUser(AgentID, out assetServerURL)) 427 if (InventoryAccessModule.IsForeignUser(AgentID, out assetServerURL) && !string.IsNullOrEmpty(assetServerURL))
428 { 428 {
429 if (!assetServerURL.EndsWith("/") && !assetServerURL.EndsWith("=")) 429 if (!assetServerURL.EndsWith("/") && !assetServerURL.EndsWith("="))
430 assetServerURL = assetServerURL + "/"; 430 assetServerURL = assetServerURL + "/";
431 431
432 m_log.DebugFormat("[J2KIMAGE]: texture {0} not found in local asset storage. Trying user's storage.", assetServerURL + id); 432// m_log.DebugFormat("[J2KIMAGE]: texture {0} not found in local asset storage. Trying user's storage.", assetServerURL + id);
433 AssetService.Get(assetServerURL + id, InventoryAccessModule, AssetReceived); 433 AssetService.Get(assetServerURL + id, InventoryAccessModule, AssetReceived);
434 return; 434 return;
435 } 435 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 7c62f90..f599342 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -84,6 +84,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
84 public event ModifyTerrain OnModifyTerrain; 84 public event ModifyTerrain OnModifyTerrain;
85 public event Action<IClientAPI> OnRegionHandShakeReply; 85 public event Action<IClientAPI> OnRegionHandShakeReply;
86 public event GenericCall1 OnRequestWearables; 86 public event GenericCall1 OnRequestWearables;
87 public event CachedTextureRequest OnCachedTextureRequest;
87 public event SetAppearance OnSetAppearance; 88 public event SetAppearance OnSetAppearance;
88 public event AvatarNowWearing OnAvatarNowWearing; 89 public event AvatarNowWearing OnAvatarNowWearing;
89 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; 90 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
@@ -95,6 +96,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
95 public event Action<IClientAPI, bool> OnCompleteMovementToRegion; 96 public event Action<IClientAPI, bool> OnCompleteMovementToRegion;
96 public event UpdateAgent OnPreAgentUpdate; 97 public event UpdateAgent OnPreAgentUpdate;
97 public event UpdateAgent OnAgentUpdate; 98 public event UpdateAgent OnAgentUpdate;
99 public event UpdateAgent OnAgentCameraUpdate;
98 public event AgentRequestSit OnAgentRequestSit; 100 public event AgentRequestSit OnAgentRequestSit;
99 public event AgentSit OnAgentSit; 101 public event AgentSit OnAgentSit;
100 public event AvatarPickerRequest OnAvatarPickerRequest; 102 public event AvatarPickerRequest OnAvatarPickerRequest;
@@ -335,6 +337,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
335 private bool m_VelocityInterpolate = false; 337 private bool m_VelocityInterpolate = false;
336 private const uint MaxTransferBytesPerPacket = 600; 338 private const uint MaxTransferBytesPerPacket = 600;
337 339
340 private volatile bool m_justEditedTerrain = false;
338 341
339 /// <value> 342 /// <value>
340 /// List used in construction of data blocks for an object update packet. This is to stop us having to 343 /// List used in construction of data blocks for an object update packet. This is to stop us having to
@@ -367,7 +370,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
367 /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods 370 /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods
368 /// cannot retain a reference to it outside of that method. 371 /// cannot retain a reference to it outside of that method.
369 /// </remarks> 372 /// </remarks>
370 private AgentUpdateArgs m_lastAgentUpdateArgs; 373 private AgentUpdateArgs m_thisAgentUpdateArgs = new AgentUpdateArgs();
371 374
372 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 375 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
373 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 376 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -504,6 +507,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
504 m_udpServer = udpServer; 507 m_udpServer = udpServer;
505 m_udpClient = udpClient; 508 m_udpClient = udpClient;
506 m_udpClient.OnQueueEmpty += HandleQueueEmpty; 509 m_udpClient.OnQueueEmpty += HandleQueueEmpty;
510 m_udpClient.HasUpdates += HandleHasUpdates;
507 m_udpClient.OnPacketStats += PopulateStats; 511 m_udpClient.OnPacketStats += PopulateStats;
508 512
509 m_prioritizer = new Prioritizer(m_scene); 513 m_prioritizer = new Prioritizer(m_scene);
@@ -533,7 +537,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
533 // We still perform a force close inside the sync lock since this is intended to attempt close where 537 // We still perform a force close inside the sync lock since this is intended to attempt close where
534 // there is some unidentified connection problem, not where we have issues due to deadlock 538 // there is some unidentified connection problem, not where we have issues due to deadlock
535 if (!IsActive && !force) 539 if (!IsActive && !force)
540 {
541 m_log.DebugFormat(
542 "[CLIENT]: Not attempting to close inactive client {0} in {1} since force flag is not set",
543 Name, m_scene.Name);
544
536 return; 545 return;
546 }
537 547
538 IsActive = false; 548 IsActive = false;
539 CloseWithoutChecks(sendStop); 549 CloseWithoutChecks(sendStop);
@@ -709,12 +719,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
709 //there is a local handler for this packet type 719 //there is a local handler for this packet type
710 if (pprocessor.Async) 720 if (pprocessor.Async)
711 { 721 {
722 ClientInfo cinfo = UDPClient.GetClientInfo();
723 if (!cinfo.AsyncRequests.ContainsKey(packet.Type.ToString()))
724 cinfo.AsyncRequests[packet.Type.ToString()] = 0;
725 cinfo.AsyncRequests[packet.Type.ToString()]++;
726
712 object obj = new AsyncPacketProcess(this, pprocessor.method, packet); 727 object obj = new AsyncPacketProcess(this, pprocessor.method, packet);
713 Util.FireAndForget(ProcessSpecificPacketAsync, obj); 728 Util.FireAndForget(ProcessSpecificPacketAsync, obj);
714 result = true; 729 result = true;
715 } 730 }
716 else 731 else
717 { 732 {
733 ClientInfo cinfo = UDPClient.GetClientInfo();
734 if (!cinfo.SyncRequests.ContainsKey(packet.Type.ToString()))
735 cinfo.SyncRequests[packet.Type.ToString()] = 0;
736 cinfo.SyncRequests[packet.Type.ToString()]++;
737
718 result = pprocessor.method(this, packet); 738 result = pprocessor.method(this, packet);
719 } 739 }
720 } 740 }
@@ -729,6 +749,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
729 } 749 }
730 if (found) 750 if (found)
731 { 751 {
752 ClientInfo cinfo = UDPClient.GetClientInfo();
753 if (!cinfo.GenericRequests.ContainsKey(packet.Type.ToString()))
754 cinfo.GenericRequests[packet.Type.ToString()] = 0;
755 cinfo.GenericRequests[packet.Type.ToString()]++;
756
732 result = method(this, packet); 757 result = method(this, packet);
733 } 758 }
734 } 759 }
@@ -758,7 +783,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
758 783
759 public virtual void Start() 784 public virtual void Start()
760 { 785 {
761 m_scene.AddNewClient(this, PresenceType.User); 786 m_scene.AddNewAgent(this, PresenceType.User);
762 787
763 RefreshGroupMembership(); 788 RefreshGroupMembership();
764 } 789 }
@@ -820,12 +845,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
820 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType); 845 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType);
821 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes; 846 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes;
822 847
823 handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[0]; 848 handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[1];
824// OutPacket(handshake, ThrottleOutPacketType.Task); 849 handshake.RegionInfo4[0] = new RegionHandshakePacket.RegionInfo4Block();
825 // use same as MoveAgentIntoRegion (both should be task ) 850 handshake.RegionInfo4[0].RegionFlagsExtended = args.regionFlags;
851 handshake.RegionInfo4[0].RegionProtocols = 0; // 1 here would indicate that SSB is supported
852
826 OutPacket(handshake, ThrottleOutPacketType.Unknown); 853 OutPacket(handshake, ThrottleOutPacketType.Unknown);
827 } 854 }
828 855
856
829 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) 857 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
830 { 858 {
831 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete); 859 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete);
@@ -1210,9 +1238,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1210 LLHeightFieldMoronize(map); 1238 LLHeightFieldMoronize(map);
1211 1239
1212 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1240 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1213 layerpack.Header.Reliable = true; 1241
1242 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience.
1243 // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain.
1244 // We also make them unreliable because it's extremely likely that multiple packets will be sent for a terrain patch area
1245 // invalidating previous packets for that area.
1246
1247 // It's possible for an editing user to flood themselves with edited packets but the majority of use cases are such that only a
1248 // tiny percentage of users will be editing the terrain. Other, non-editing users will see the edits much slower.
1249
1250 // One last note on this topic, by the time users are going to be editing the terrain, it's extremely likely that the sim will
1251 // have rezzed already and therefore this is not likely going to cause any additional issues with lost packets, objects or terrain
1252 // patches.
1214 1253
1215 OutPacket(layerpack, ThrottleOutPacketType.Task); 1254 // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we only have one cache miss.
1255 if (m_justEditedTerrain)
1256 {
1257 layerpack.Header.Reliable = false;
1258 OutPacket(layerpack,
1259 ThrottleOutPacketType.Unknown );
1260 }
1261 else
1262 {
1263 layerpack.Header.Reliable = true;
1264 OutPacket(layerpack,
1265 ThrottleOutPacketType.Task);
1266 }
1216 } 1267 }
1217 catch (Exception e) 1268 catch (Exception e)
1218 { 1269 {
@@ -1405,6 +1456,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1405 1456
1406 mapReply.AgentData.AgentID = AgentId; 1457 mapReply.AgentData.AgentID = AgentId;
1407 mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length]; 1458 mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length];
1459 mapReply.Size = new MapBlockReplyPacket.SizeBlock[mapBlocks2.Length];
1408 mapReply.AgentData.Flags = flag; 1460 mapReply.AgentData.Flags = flag;
1409 1461
1410 for (int i = 0; i < mapBlocks2.Length; i++) 1462 for (int i = 0; i < mapBlocks2.Length; i++)
@@ -1419,6 +1471,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1419 mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags; 1471 mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags;
1420 mapReply.Data[i].Access = mapBlocks2[i].Access; 1472 mapReply.Data[i].Access = mapBlocks2[i].Access;
1421 mapReply.Data[i].Agents = mapBlocks2[i].Agents; 1473 mapReply.Data[i].Agents = mapBlocks2[i].Agents;
1474
1475 // TODO: hookup varregion sim size here
1476 mapReply.Size[i] = new MapBlockReplyPacket.SizeBlock();
1477 mapReply.Size[i].SizeX = 256;
1478 mapReply.Size[i].SizeY = 256;
1422 } 1479 }
1423 OutPacket(mapReply, ThrottleOutPacketType.Land); 1480 OutPacket(mapReply, ThrottleOutPacketType.Land);
1424 } 1481 }
@@ -1580,7 +1637,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1580 OutPacket(pc, ThrottleOutPacketType.Unknown); 1637 OutPacket(pc, ThrottleOutPacketType.Unknown);
1581 } 1638 }
1582 1639
1583 public void SendKillObject(ulong regionHandle, List<uint> localIDs) 1640 public void SendKillObject(List<uint> localIDs)
1584 { 1641 {
1585// foreach (uint id in localIDs) 1642// foreach (uint id in localIDs)
1586// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle); 1643// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
@@ -2594,11 +2651,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2594 { 2651 {
2595 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); 2652 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket();
2596 avatarSitResponse.SitObject.ID = TargetID; 2653 avatarSitResponse.SitObject.ID = TargetID;
2597 if (CameraAtOffset != Vector3.Zero) 2654 avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
2598 { 2655 avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
2599 avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
2600 avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
2601 }
2602 avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; 2656 avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook;
2603 avatarSitResponse.SitTransform.AutoPilot = autopilot; 2657 avatarSitResponse.SitTransform.AutoPilot = autopilot;
2604 avatarSitResponse.SitTransform.SitPosition = OffsetPos; 2658 avatarSitResponse.SitTransform.SitPosition = OffsetPos;
@@ -3794,12 +3848,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3794 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); 3848 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
3795 3849
3796 // Count this as a resent packet since we are going to requeue all of the updates contained in it 3850 // Count this as a resent packet since we are going to requeue all of the updates contained in it
3797 Interlocked.Increment(ref m_udpClient.PacketsResent); 3851 Interlocked.Increment(ref m_udpClient.PacketsResent);
3852
3853 // We're not going to worry about interlock yet since its not currently critical that this total count
3854 // is 100% correct
3855 m_udpServer.PacketsResentCount++;
3798 3856
3799 foreach (EntityUpdate update in updates) 3857 foreach (EntityUpdate update in updates)
3800 ResendPrimUpdate(update); 3858 ResendPrimUpdate(update);
3801 } 3859 }
3802 3860
3861// OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
3862// OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
3863// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3864// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3865//
3866// OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3867// OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3868// OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3869// OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3870
3871
3803 private void ProcessEntityUpdates(int maxUpdates) 3872 private void ProcessEntityUpdates(int maxUpdates)
3804 { 3873 {
3805 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); 3874 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@@ -3812,6 +3881,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3812 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 3881 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3813 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 3882 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3814 3883
3884// objectUpdateBlocks.Value.Clear();
3885// compressedUpdateBlocks.Value.Clear();
3886// terseUpdateBlocks.Value.Clear();
3887// terseAgentUpdateBlocks.Value.Clear();
3888// objectUpdates.Value.Clear();
3889// compressedUpdates.Value.Clear();
3890// terseUpdates.Value.Clear();
3891// terseAgentUpdates.Value.Clear();
3892
3815 // Check to see if this is a flush 3893 // Check to see if this is a flush
3816 if (maxUpdates <= 0) 3894 if (maxUpdates <= 0)
3817 { 3895 {
@@ -4140,8 +4218,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4140 4218
4141 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) 4219 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
4142 { 4220 {
4221// if (!m_udpServer.IsRunningOutbound)
4222// return;
4223
4143 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) 4224 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
4144 { 4225 {
4226// if (!m_udpServer.IsRunningOutbound)
4227// return;
4228
4145 if (m_maxUpdates == 0 || m_LastQueueFill == 0) 4229 if (m_maxUpdates == 0 || m_LastQueueFill == 0)
4146 { 4230 {
4147 m_maxUpdates = m_udpServer.PrimUpdatesPerCallback; 4231 m_maxUpdates = m_udpServer.PrimUpdatesPerCallback;
@@ -4167,6 +4251,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4167 ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); 4251 ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
4168 } 4252 }
4169 4253
4254 internal bool HandleHasUpdates(ThrottleOutPacketTypeFlags categories)
4255 {
4256 bool hasUpdates = false;
4257
4258 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
4259 {
4260 if (m_entityUpdates.Count > 0)
4261 hasUpdates = true;
4262 else if (m_entityProps.Count > 0)
4263 hasUpdates = true;
4264 }
4265
4266 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
4267 {
4268 if (ImageManager.HasUpdates())
4269 hasUpdates = true;
4270 }
4271
4272 return hasUpdates;
4273 }
4274
4170 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) 4275 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
4171 { 4276 {
4172 AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); 4277 AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
@@ -4312,6 +4417,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4312 // Count this as a resent packet since we are going to requeue all of the updates contained in it 4417 // Count this as a resent packet since we are going to requeue all of the updates contained in it
4313 Interlocked.Increment(ref m_udpClient.PacketsResent); 4418 Interlocked.Increment(ref m_udpClient.PacketsResent);
4314 4419
4420 // We're not going to worry about interlock yet since its not currently critical that this total count
4421 // is 100% correct
4422 m_udpServer.PacketsResentCount++;
4423
4315 foreach (ObjectPropertyUpdate update in updates) 4424 foreach (ObjectPropertyUpdate update in updates)
4316 ResendPropertyUpdate(update); 4425 ResendPropertyUpdate(update);
4317 } 4426 }
@@ -4499,6 +4608,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4499 SceneObjectPart root = sop.ParentGroup.RootPart; 4608 SceneObjectPart root = sop.ParentGroup.RootPart;
4500 4609
4501 block.TouchName = Util.StringToBytes256(root.TouchName); 4610 block.TouchName = Util.StringToBytes256(root.TouchName);
4611
4612 // SL 3.3.4, at least, appears to read this information as a concatenated byte[] stream of UUIDs but
4613 // it's not yet clear whether this is actually used. If this is done in the future then a pre-cached
4614 // copy is really needed since it's less efficient to be constantly recreating this byte array.
4615// using (MemoryStream memStream = new MemoryStream())
4616// {
4617// using (BinaryWriter binWriter = new BinaryWriter(memStream))
4618// {
4619// for (int i = 0; i < sop.GetNumberOfSides(); i++)
4620// {
4621// Primitive.TextureEntryFace teFace = sop.Shape.Textures.FaceTextures[i];
4622//
4623// UUID textureID;
4624//
4625// if (teFace != null)
4626// textureID = teFace.TextureID;
4627// else
4628// textureID = sop.Shape.Textures.DefaultTexture.TextureID;
4629//
4630// binWriter.Write(textureID.GetBytes());
4631// }
4632//
4633// block.TextureID = memStream.ToArray();
4634// }
4635// }
4636
4502 block.TextureID = new byte[0]; // TextureID ??? 4637 block.TextureID = new byte[0]; // TextureID ???
4503 block.SitName = Util.StringToBytes256(root.SitName); 4638 block.SitName = Util.StringToBytes256(root.SitName);
4504 block.OwnerMask = root.OwnerMask; 4639 block.OwnerMask = root.OwnerMask;
@@ -4877,7 +5012,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4877 5012
4878 public void SendForceClientSelectObjects(List<uint> ObjectIDs) 5013 public void SendForceClientSelectObjects(List<uint> ObjectIDs)
4879 { 5014 {
4880 m_log.WarnFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count); 5015// m_log.DebugFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count);
4881 5016
4882 bool firstCall = true; 5017 bool firstCall = true;
4883 const int MAX_OBJECTS_PER_PACKET = 251; 5018 const int MAX_OBJECTS_PER_PACKET = 251;
@@ -5015,15 +5150,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5015 } 5150 }
5016 5151
5017 attachPoint = 0; 5152 attachPoint = 0;
5153// m_log.DebugFormat(
5154// "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
5155
5156 // attachPoint = presence.State; // Core: commented
5018 collisionPlane = presence.CollisionPlane; 5157 collisionPlane = presence.CollisionPlane;
5019 velocity = presence.Velocity; 5158 velocity = presence.Velocity;
5020 acceleration = Vector3.Zero; 5159 acceleration = Vector3.Zero;
5021 5160
5022 // Interestingly, sending this to non-zero will cause the client's avatar to start moving & accelerating
5023 // in that direction, even though we don't model this on the server. Implementing this in the future
5024 // may improve movement smoothness.
5025// acceleration = new Vector3(1, 0, 0);
5026
5027 if (sendTexture) 5161 if (sendTexture)
5028 textureEntry = presence.Appearance.Texture.GetBytes(); 5162 textureEntry = presence.Appearance.Texture.GetBytes();
5029 else 5163 else
@@ -5034,7 +5168,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5034 SceneObjectPart part = (SceneObjectPart)entity; 5168 SceneObjectPart part = (SceneObjectPart)entity;
5035 5169
5036 attachPoint = part.ParentGroup.AttachmentPoint; 5170 attachPoint = part.ParentGroup.AttachmentPoint;
5037 5171 attachPoint = ((attachPoint % 16) * 16 + (attachPoint / 16));
5038// m_log.DebugFormat( 5172// m_log.DebugFormat(
5039// "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}", 5173// "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}",
5040// attachPoint, part.Name, part.LocalId, Name); 5174// attachPoint, part.Name, part.LocalId, Name);
@@ -5062,7 +5196,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5062 pos += 4; 5196 pos += 4;
5063 5197
5064 // Avatar/CollisionPlane 5198 // Avatar/CollisionPlane
5065 data[pos++] = (byte)((attachPoint % 16) * 16 + (attachPoint / 16)); ; 5199 data[pos++] = (byte) attachPoint;
5066 if (avatar) 5200 if (avatar)
5067 { 5201 {
5068 data[pos++] = 1; 5202 data[pos++] = 1;
@@ -5143,6 +5277,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5143 parentID = part.ParentGroup.RootPart.LocalId; 5277 parentID = part.ParentGroup.RootPart.LocalId;
5144 } 5278 }
5145 } 5279 }
5280// m_log.DebugFormat(
5281// "[LLCLIENTVIEW]: Sending full update to {0} with position {1} in {2}", Name, data.OffsetPosition, m_scene.Name);
5146 5282
5147 byte[] objectData = new byte[76]; 5283 byte[] objectData = new byte[76];
5148 5284
@@ -5168,7 +5304,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5168 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + 5304 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
5169 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); 5305 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
5170 update.ObjectData = objectData; 5306 update.ObjectData = objectData;
5171 update.ParentID = parentID; 5307
5308 SceneObjectPart parentPart = data.ParentPart;
5309 if (parentPart != null)
5310 update.ParentID = parentPart.ParentGroup.LocalId;
5311 else
5312 update.ParentID = 0;
5313
5172 update.PathCurve = 16; 5314 update.PathCurve = 16;
5173 update.PathScaleX = 100; 5315 update.PathScaleX = 100;
5174 update.PathScaleY = 100; 5316 update.PathScaleY = 100;
@@ -5387,7 +5529,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5387 AddLocalPacketHandler(PacketType.RezObject, HandlerRezObject); 5529 AddLocalPacketHandler(PacketType.RezObject, HandlerRezObject);
5388 AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject); 5530 AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject);
5389 AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand); 5531 AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand);
5390 AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply); 5532 AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply, false);
5391 AddLocalPacketHandler(PacketType.AgentWearablesRequest, HandlerAgentWearablesRequest); 5533 AddLocalPacketHandler(PacketType.AgentWearablesRequest, HandlerAgentWearablesRequest);
5392 AddLocalPacketHandler(PacketType.AgentSetAppearance, HandlerAgentSetAppearance); 5534 AddLocalPacketHandler(PacketType.AgentSetAppearance, HandlerAgentSetAppearance);
5393 AddLocalPacketHandler(PacketType.AgentIsNowWearing, HandlerAgentIsNowWearing); 5535 AddLocalPacketHandler(PacketType.AgentIsNowWearing, HandlerAgentIsNowWearing);
@@ -5448,8 +5590,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5448 AddLocalPacketHandler(PacketType.ScriptAnswerYes, HandleScriptAnswerYes, false); 5590 AddLocalPacketHandler(PacketType.ScriptAnswerYes, HandleScriptAnswerYes, false);
5449 AddLocalPacketHandler(PacketType.ObjectClickAction, HandleObjectClickAction, false); 5591 AddLocalPacketHandler(PacketType.ObjectClickAction, HandleObjectClickAction, false);
5450 AddLocalPacketHandler(PacketType.ObjectMaterial, HandleObjectMaterial, false); 5592 AddLocalPacketHandler(PacketType.ObjectMaterial, HandleObjectMaterial, false);
5451 AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage); 5593 AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage, false);
5452 AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest); 5594 AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest, false);
5453 AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest); 5595 AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest);
5454 AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer); 5596 AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer);
5455 AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket); 5597 AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket);
@@ -5481,7 +5623,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5481 AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel); 5623 AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel);
5482 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest); 5624 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest);
5483 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false); 5625 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false);
5484 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest); 5626 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest, false);
5485 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest); 5627 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest);
5486 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false); 5628 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false);
5487 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false); 5629 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false);
@@ -5594,83 +5736,137 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5594 5736
5595 #region Packet Handlers 5737 #region Packet Handlers
5596 5738
5739 public int TotalAgentUpdates { get; set; }
5740
5597 #region Scene/Avatar 5741 #region Scene/Avatar
5598 5742
5599 private bool HandleAgentUpdate(IClientAPI sener, Packet packet) 5743 // Threshold for body rotation to be a significant agent update
5744 private const float QDELTA = 0.000001f;
5745 // Threshold for camera rotation to be a significant agent update
5746 private const float VDELTA = 0.01f;
5747
5748 /// <summary>
5749 /// This checks the update significance against the last update made.
5750 /// </summary>
5751 /// <remarks>Can only be called by one thread at a time</remarks>
5752 /// <returns></returns>
5753 /// <param name='x'></param>
5754 public bool CheckAgentUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5600 { 5755 {
5601 if (OnAgentUpdate != null) 5756 return CheckAgentMovementUpdateSignificance(x) || CheckAgentCameraUpdateSignificance(x);
5602 { 5757 }
5603 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5604 5758
5605 #region Packet Session and User Check 5759 /// <summary>
5606 if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) 5760 /// This checks the movement/state update significance against the last update made.
5607 { 5761 /// </summary>
5608 PacketPool.Instance.ReturnPacket(packet); 5762 /// <remarks>Can only be called by one thread at a time</remarks>
5609 return false; 5763 /// <returns></returns>
5610 } 5764 /// <param name='x'></param>
5611 #endregion 5765 private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5766 {
5767 float qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2);
5768 //qdelta2 = 1 - (float)Math.Pow(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation), 2);
5769
5770 bool movementSignificant =
5771 (qdelta1 > QDELTA) // significant if body rotation above threshold
5772 // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack
5773 // || (qdelta2 > QDELTA * 10) // significant if head rotation above threshold
5774 || (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed
5775 || (x.ControlFlags != (byte)AgentManager.ControlFlags.NONE) // significant if user supplying any movement update commands
5776 || (x.Far != m_thisAgentUpdateArgs.Far) // significant if far distance changed
5777 || (x.Flags != m_thisAgentUpdateArgs.Flags) // significant if Flags changed
5778 || (x.State != m_thisAgentUpdateArgs.State) // significant if Stats changed
5779 ;
5780 //if (movementSignificant)
5781 //{
5782 //m_log.DebugFormat("[LLCLIENTVIEW]: Bod {0} {1}",
5783 // qdelta1, qdelta2);
5784 //m_log.DebugFormat("[LLCLIENTVIEW]: St {0} {1} {2} {3}",
5785 // x.ControlFlags, x.Flags, x.Far, x.State);
5786 //}
5787 return movementSignificant;
5788 }
5612 5789
5613 bool update = false; 5790 /// <summary>
5614 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; 5791 /// This checks the camera update significance against the last update made.
5615 5792 /// </summary>
5616 if (m_lastAgentUpdateArgs != null) 5793 /// <remarks>Can only be called by one thread at a time</remarks>
5617 { 5794 /// <returns></returns>
5618 // These should be ordered from most-likely to 5795 /// <param name='x'></param>
5619 // least likely to change. I've made an initial 5796 private bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5620 // guess at that. 5797 {
5621 update = 5798 float vdelta1 = Vector3.Distance(x.CameraAtAxis, m_thisAgentUpdateArgs.CameraAtAxis);
5622 ( 5799 float vdelta2 = Vector3.Distance(x.CameraCenter, m_thisAgentUpdateArgs.CameraCenter);
5623 (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || 5800 float vdelta3 = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis);
5624 (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || 5801 float vdelta4 = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis);
5625 (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) ||
5626 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) ||
5627 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) ||
5628 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) ||
5629 (x.ControlFlags != 0) ||
5630 (x.Far != m_lastAgentUpdateArgs.Far) ||
5631 (x.Flags != m_lastAgentUpdateArgs.Flags) ||
5632 (x.State != m_lastAgentUpdateArgs.State) ||
5633 (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) ||
5634 (x.SessionID != m_lastAgentUpdateArgs.SessionID) ||
5635 (x.AgentID != m_lastAgentUpdateArgs.AgentID)
5636 );
5637 }
5638 else
5639 {
5640 m_lastAgentUpdateArgs = new AgentUpdateArgs();
5641 update = true;
5642 }
5643 5802
5644 if (update) 5803 bool cameraSignificant =
5645 { 5804 (vdelta1 > VDELTA) ||
5646// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); 5805 (vdelta2 > VDELTA) ||
5806 (vdelta3 > VDELTA) ||
5807 (vdelta4 > VDELTA)
5808 ;
5647 5809
5648 m_lastAgentUpdateArgs.AgentID = x.AgentID; 5810 //if (cameraSignificant)
5649 m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; 5811 //{
5650 m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; 5812 //m_log.DebugFormat("[LLCLIENTVIEW]: Cam1 {0} {1}",
5651 m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; 5813 // x.CameraAtAxis, x.CameraCenter);
5652 m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; 5814 //m_log.DebugFormat("[LLCLIENTVIEW]: Cam2 {0} {1}",
5653 m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; 5815 // x.CameraLeftAxis, x.CameraUpAxis);
5654 m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; 5816 //}
5655 m_lastAgentUpdateArgs.Far = x.Far;
5656 m_lastAgentUpdateArgs.Flags = x.Flags;
5657 m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation;
5658 m_lastAgentUpdateArgs.SessionID = x.SessionID;
5659 m_lastAgentUpdateArgs.State = x.State;
5660 5817
5661 UpdateAgent handlerAgentUpdate = OnAgentUpdate; 5818 return cameraSignificant;
5662 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; 5819 }
5663 5820
5664 if (handlerPreAgentUpdate != null) 5821 private bool HandleAgentUpdate(IClientAPI sener, Packet packet)
5665 OnPreAgentUpdate(this, m_lastAgentUpdateArgs); 5822 {
5823 // We got here, which means that something in agent update was significant
5666 5824
5667 if (handlerAgentUpdate != null) 5825 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5668 OnAgentUpdate(this, m_lastAgentUpdateArgs); 5826 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
5669 5827
5670 handlerAgentUpdate = null; 5828 if (x.AgentID != AgentId || x.SessionID != SessionId)
5671 handlerPreAgentUpdate = null; 5829 return false;
5672 } 5830
5673 } 5831 // Before we update the current m_thisAgentUpdateArgs, let's check this again
5832 // to see what exactly changed
5833 bool movement = CheckAgentMovementUpdateSignificance(x);
5834 bool camera = CheckAgentCameraUpdateSignificance(x);
5835
5836 m_thisAgentUpdateArgs.AgentID = x.AgentID;
5837 m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation;
5838 m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
5839 m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter;
5840 m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
5841 m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
5842 m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags;
5843 m_thisAgentUpdateArgs.Far = x.Far;
5844 m_thisAgentUpdateArgs.Flags = x.Flags;
5845 m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation;
5846 m_thisAgentUpdateArgs.SessionID = x.SessionID;
5847 m_thisAgentUpdateArgs.State = x.State;
5848
5849 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5850 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5851 UpdateAgent handlerAgentCameraUpdate = OnAgentCameraUpdate;
5852
5853 // Was there a significant movement/state change?
5854 if (movement)
5855 {
5856 if (handlerPreAgentUpdate != null)
5857 OnPreAgentUpdate(this, m_thisAgentUpdateArgs);
5858
5859 if (handlerAgentUpdate != null)
5860 OnAgentUpdate(this, m_thisAgentUpdateArgs);
5861 }
5862 // Was there a significant camera(s) change?
5863 if (camera)
5864 if (handlerAgentCameraUpdate != null)
5865 handlerAgentCameraUpdate(this, m_thisAgentUpdateArgs);
5866
5867 handlerAgentUpdate = null;
5868 handlerPreAgentUpdate = null;
5869 handlerAgentCameraUpdate = null;
5674 5870
5675 PacketPool.Instance.ReturnPacket(packet); 5871 PacketPool.Instance.ReturnPacket(packet);
5676 5872
@@ -6260,6 +6456,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6260 //m_log.Info("[LAND]: LAND:" + modify.ToString()); 6456 //m_log.Info("[LAND]: LAND:" + modify.ToString());
6261 if (modify.ParcelData.Length > 0) 6457 if (modify.ParcelData.Length > 0)
6262 { 6458 {
6459 // Note: the ModifyTerrain event handler sends out updated packets before the end of this event. Therefore,
6460 // a simple boolean value should work and perhaps queue up just a few terrain patch packets at the end of the edit.
6461 m_justEditedTerrain = true; // Prevent terrain packet (Land layer) from being queued, make it unreliable
6263 if (OnModifyTerrain != null) 6462 if (OnModifyTerrain != null)
6264 { 6463 {
6265 for (int i = 0; i < modify.ParcelData.Length; i++) 6464 for (int i = 0; i < modify.ParcelData.Length; i++)
@@ -6275,6 +6474,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6275 } 6474 }
6276 } 6475 }
6277 } 6476 }
6477 m_justEditedTerrain = false; // Queue terrain packet (Land layer) if necessary, make it reliable again
6278 } 6478 }
6279 6479
6280 return true; 6480 return true;
@@ -6636,6 +6836,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6636 } 6836 }
6637 #endregion 6837 #endregion
6638 6838
6839 if (SceneAgent.IsChildAgent)
6840 {
6841 SendCantSitBecauseChildAgentResponse();
6842 return true;
6843 }
6844
6639 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; 6845 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit;
6640 6846
6641 if (handlerAgentRequestSit != null) 6847 if (handlerAgentRequestSit != null)
@@ -6660,6 +6866,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6660 } 6866 }
6661 #endregion 6867 #endregion
6662 6868
6869 if (SceneAgent.IsChildAgent)
6870 {
6871 SendCantSitBecauseChildAgentResponse();
6872 return true;
6873 }
6874
6663 AgentSit handlerAgentSit = OnAgentSit; 6875 AgentSit handlerAgentSit = OnAgentSit;
6664 if (handlerAgentSit != null) 6876 if (handlerAgentSit != null)
6665 { 6877 {
@@ -6669,6 +6881,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6669 return true; 6881 return true;
6670 } 6882 }
6671 6883
6884 /// <summary>
6885 /// Used when a child agent gets a sit response which should not be fulfilled.
6886 /// </summary>
6887 private void SendCantSitBecauseChildAgentResponse()
6888 {
6889 SendAlertMessage("Try moving closer. Can't sit on object because it is not in the same region as you.");
6890 }
6891
6672 private bool HandleSoundTrigger(IClientAPI sender, Packet Pack) 6892 private bool HandleSoundTrigger(IClientAPI sender, Packet Pack)
6673 { 6893 {
6674 SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; 6894 SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack;
@@ -7879,129 +8099,145 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7879 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); 8099 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request");
7880 8100
7881 TransferRequestPacket transfer = (TransferRequestPacket)Pack; 8101 TransferRequestPacket transfer = (TransferRequestPacket)Pack;
7882 //m_log.Debug("Transfer Request: " + transfer.ToString());
7883 // Validate inventory transfers
7884 // Has to be done here, because AssetCache can't do it
7885 //
7886 UUID taskID = UUID.Zero; 8102 UUID taskID = UUID.Zero;
7887 if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) 8103 if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
7888 { 8104 {
7889 taskID = new UUID(transfer.TransferInfo.Params, 48);
7890 UUID itemID = new UUID(transfer.TransferInfo.Params, 64);
7891 UUID requestID = new UUID(transfer.TransferInfo.Params, 80);
7892
7893// m_log.DebugFormat(
7894// "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}",
7895// requestID, itemID, taskID, Name);
7896
7897 if (!(((Scene)m_scene).Permissions.BypassPermissions())) 8105 if (!(((Scene)m_scene).Permissions.BypassPermissions()))
7898 { 8106 {
7899 if (taskID != UUID.Zero) // Prim 8107 // We're spawning a thread because the permissions check can block this thread
8108 Util.FireAndForget(delegate
7900 { 8109 {
7901 SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); 8110 // This requests the asset if needed
8111 HandleSimInventoryTransferRequestWithPermsCheck(sender, transfer);
8112 });
8113 return true;
8114 }
8115 }
8116 else if (transfer.TransferInfo.SourceType == (int)SourceType.SimEstate)
8117 {
8118 //TransferRequestPacket does not include covenant uuid?
8119 //get scene covenant uuid
8120 taskID = m_scene.RegionInfo.RegionSettings.Covenant;
8121 }
7902 8122
7903 if (part == null) 8123 // This is non-blocking
7904 { 8124 MakeAssetRequest(transfer, taskID);
7905 m_log.WarnFormat(
7906 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist",
7907 Name, requestID, itemID, taskID);
7908 return true;
7909 }
7910 8125
7911 TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID); 8126 return true;
7912 if (tii == null) 8127 }
7913 {
7914 m_log.WarnFormat(
7915 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist",
7916 Name, requestID, itemID, taskID);
7917 return true;
7918 }
7919 8128
7920 if (tii.Type == (int)AssetType.LSLText) 8129 private void HandleSimInventoryTransferRequestWithPermsCheck(IClientAPI sender, TransferRequestPacket transfer)
7921 { 8130 {
7922 if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId)) 8131 UUID taskID = new UUID(transfer.TransferInfo.Params, 48);
7923 return true; 8132 UUID itemID = new UUID(transfer.TransferInfo.Params, 64);
7924 } 8133 UUID requestID = new UUID(transfer.TransferInfo.Params, 80);
7925 else if (tii.Type == (int)AssetType.Notecard)
7926 {
7927 if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId))
7928 return true;
7929 }
7930 else
7931 {
7932 // TODO: Change this code to allow items other than notecards and scripts to be successfully
7933 // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule
7934 if (part.OwnerID != AgentId)
7935 {
7936 m_log.WarnFormat(
7937 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}",
7938 Name, requestID, itemID, taskID, part.OwnerID);
7939 return true;
7940 }
7941 8134
7942 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) 8135 //m_log.DebugFormat(
7943 { 8136 // "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}",
7944 m_log.WarnFormat( 8137 // requestID, itemID, taskID, Name);
7945 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set",
7946 Name, requestID, itemID, taskID);
7947 return true;
7948 }
7949 8138
7950 if (tii.OwnerID != AgentId) 8139 //m_log.Debug("Transfer Request: " + transfer.ToString());
7951 { 8140 // Validate inventory transfers
7952 m_log.WarnFormat( 8141 // Has to be done here, because AssetCache can't do it
7953 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}", 8142 //
7954 Name, requestID, itemID, taskID, tii.OwnerID); 8143 if (taskID != UUID.Zero) // Prim
7955 return true; 8144 {
7956 } 8145 SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID);
7957 8146
7958 if (( 8147 if (part == null)
7959 tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) 8148 {
7960 != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) 8149 m_log.WarnFormat(
7961 { 8150 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist",
7962 m_log.WarnFormat( 8151 Name, requestID, itemID, taskID);
7963 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer", 8152 return;
7964 Name, requestID, itemID, taskID); 8153 }
7965 return true;
7966 }
7967 8154
7968 if (tii.AssetID != requestID) 8155 TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID);
7969 { 8156 if (tii == null)
7970 m_log.WarnFormat( 8157 {
7971 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}", 8158 m_log.WarnFormat(
7972 Name, requestID, itemID, taskID, tii.AssetID); 8159 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist",
7973 return true; 8160 Name, requestID, itemID, taskID);
7974 } 8161 return;
7975 } 8162 }
8163
8164 if (tii.Type == (int)AssetType.LSLText)
8165 {
8166 if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId))
8167 return;
8168 }
8169 else if (tii.Type == (int)AssetType.Notecard)
8170 {
8171 if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId))
8172 return;
8173 }
8174 else
8175 {
8176 // TODO: Change this code to allow items other than notecards and scripts to be successfully
8177 // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule
8178 if (part.OwnerID != AgentId)
8179 {
8180 m_log.WarnFormat(
8181 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}",
8182 Name, requestID, itemID, taskID, part.OwnerID);
8183 return;
7976 } 8184 }
7977 else // Agent 8185
8186 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
7978 { 8187 {
7979 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 8188 m_log.WarnFormat(
7980 if (invAccess != null) 8189 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set",
7981 { 8190 Name, requestID, itemID, taskID);
7982 if (!invAccess.CanGetAgentInventoryItem(this, itemID, requestID)) 8191 return;
7983 return false; 8192 }
7984 } 8193
7985 else 8194 if (tii.OwnerID != AgentId)
7986 { 8195 {
7987 return false; 8196 m_log.WarnFormat(
7988 } 8197 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}",
8198 Name, requestID, itemID, taskID, tii.OwnerID);
8199 return;
8200 }
8201
8202 if ((
8203 tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
8204 != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
8205 {
8206 m_log.WarnFormat(
8207 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer",
8208 Name, requestID, itemID, taskID);
8209 return;
8210 }
8211
8212 if (tii.AssetID != requestID)
8213 {
8214 m_log.WarnFormat(
8215 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}",
8216 Name, requestID, itemID, taskID, tii.AssetID);
8217 return;
7989 } 8218 }
7990 } 8219 }
7991 } 8220 }
7992 else 8221 else // Agent
7993 if (transfer.TransferInfo.SourceType == (int)SourceType.SimEstate) 8222 {
8223 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
8224 if (invAccess != null)
7994 { 8225 {
7995 //TransferRequestPacket does not include covenant uuid? 8226 if (!invAccess.CanGetAgentInventoryItem(this, itemID, requestID))
7996 //get scene covenant uuid 8227 return;
7997 taskID = m_scene.RegionInfo.RegionSettings.Covenant;
7998 } 8228 }
8229 else
8230 {
8231 return;
8232 }
8233 }
7999 8234
8235 // Permissions out of the way, let's request the asset
8000 MakeAssetRequest(transfer, taskID); 8236 MakeAssetRequest(transfer, taskID);
8001 8237
8002 return true;
8003 } 8238 }
8004 8239
8240
8005 private bool HandleAssetUploadRequest(IClientAPI sender, Packet Pack) 8241 private bool HandleAssetUploadRequest(IClientAPI sender, Packet Pack)
8006 { 8242 {
8007 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; 8243 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
@@ -11732,8 +11968,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11732 } 11968 }
11733 11969
11734 /// <summary> 11970 /// <summary>
11735 /// Send a response back to a client when it asks the asset server (via the region server) if it has
11736 /// its appearance texture cached.
11737 /// </summary> 11971 /// </summary>
11738 /// <remarks> 11972 /// <remarks>
11739 /// At the moment, we always reply that there is no cached texture. 11973 /// At the moment, we always reply that there is no cached texture.
@@ -11741,6 +11975,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11741 /// <param name="simclient"></param> 11975 /// <param name="simclient"></param>
11742 /// <param name="packet"></param> 11976 /// <param name="packet"></param>
11743 /// <returns></returns> 11977 /// <returns></returns>
11978 // TODO: Convert old handler to use new method
11979 /*protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11980 {
11981 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
11982
11983 if (cachedtex.AgentData.SessionID != SessionId)
11984 return false;
11985
11986
11987 List<CachedTextureRequestArg> requestArgs = new List<CachedTextureRequestArg>();
11988
11989 for (int i = 0; i < cachedtex.WearableData.Length; i++)
11990 {
11991 CachedTextureRequestArg arg = new CachedTextureRequestArg();
11992 arg.BakedTextureIndex = cachedtex.WearableData[i].TextureIndex;
11993 arg.WearableHashID = cachedtex.WearableData[i].ID;
11994
11995 requestArgs.Add(arg);
11996 }
11997
11998 CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest;
11999 if (handlerCachedTextureRequest != null)
12000 {
12001 handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs);
12002 }
12003
12004 return true;
12005 }*/
12006
11744 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet) 12007 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11745 { 12008 {
11746 //m_log.Debug("texture cached: " + packet.ToString()); 12009 //m_log.Debug("texture cached: " + packet.ToString());
@@ -11899,6 +12162,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11899 return true; 12162 return true;
11900 } 12163 }
11901 12164
12165 /// <summary>
12166 /// Send a response back to a client when it asks the asset server (via the region server) if it has
12167 /// its appearance texture cached.
12168 /// </summary>
12169 /// <param name="avatar"></param>
12170 /// <param name="serial"></param>
12171 /// <param name="cachedTextures"></param>
12172 /// <returns></returns>
12173 public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures)
12174 {
12175 ScenePresence presence = avatar as ScenePresence;
12176 if (presence == null)
12177 return;
12178
12179 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
12180
12181 // TODO: don't create new blocks if recycling an old packet
12182 cachedresp.AgentData.AgentID = m_agentId;
12183 cachedresp.AgentData.SessionID = m_sessionId;
12184 cachedresp.AgentData.SerialNum = serial;
12185 cachedresp.WearableData = new AgentCachedTextureResponsePacket.WearableDataBlock[cachedTextures.Count];
12186
12187 for (int i = 0; i < cachedTextures.Count; i++)
12188 {
12189 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
12190 cachedresp.WearableData[i].TextureIndex = (byte)cachedTextures[i].BakedTextureIndex;
12191 cachedresp.WearableData[i].TextureID = cachedTextures[i].BakedTextureID;
12192 cachedresp.WearableData[i].HostName = new byte[0];
12193 }
12194
12195 cachedresp.Header.Zerocoded = true;
12196 OutPacket(cachedresp, ThrottleOutPacketType.Task);
12197 }
12198
11902 protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet) 12199 protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet)
11903 { 12200 {
11904 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; 12201 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet;
@@ -11924,8 +12221,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11924 if (part == null) 12221 if (part == null)
11925 { 12222 {
11926 // It's a ghost! tell the client to delete it from view. 12223 // It's a ghost! tell the client to delete it from view.
11927 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 12224 simClient.SendKillObject(new List<uint> { localId });
11928 new List<uint> { localId });
11929 } 12225 }
11930 else 12226 else
11931 { 12227 {
@@ -12299,6 +12595,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12299 12595
12300 shape.PCode = addPacket.ObjectData.PCode; 12596 shape.PCode = addPacket.ObjectData.PCode;
12301 shape.State = addPacket.ObjectData.State; 12597 shape.State = addPacket.ObjectData.State;
12598 shape.LastAttachPoint = addPacket.ObjectData.State;
12302 shape.PathBegin = addPacket.ObjectData.PathBegin; 12599 shape.PathBegin = addPacket.ObjectData.PathBegin;
12303 shape.PathEnd = addPacket.ObjectData.PathEnd; 12600 shape.PathEnd = addPacket.ObjectData.PathEnd;
12304 shape.PathScaleX = addPacket.ObjectData.PathScaleX; 12601 shape.PathScaleX = addPacket.ObjectData.PathScaleX;
@@ -12329,7 +12626,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12329 ClientInfo info = m_udpClient.GetClientInfo(); 12626 ClientInfo info = m_udpClient.GetClientInfo();
12330 12627
12331 info.proxyEP = null; 12628 info.proxyEP = null;
12332 info.agentcircuit = RequestClientInfo(); 12629 if (info.agentcircuit == null)
12630 info.agentcircuit = RequestClientInfo();
12333 12631
12334 return info; 12632 return info;
12335 } 12633 }
@@ -12712,11 +13010,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12712 OutPacket(dialog, ThrottleOutPacketType.Task); 13010 OutPacket(dialog, ThrottleOutPacketType.Task);
12713 } 13011 }
12714 13012
12715 public void StopFlying(ISceneEntity p) 13013 public void SendAgentTerseUpdate(ISceneEntity p)
12716 { 13014 {
12717 if (p is ScenePresence) 13015 if (p is ScenePresence)
12718 { 13016 {
12719 ScenePresence presence = p as ScenePresence; 13017// m_log.DebugFormat(
13018// "[LLCLIENTVIEW]: Immediately sending terse agent update for {0} to {1} in {2}",
13019// p.Name, Name, Scene.Name);
13020
12720 // It turns out to get the agent to stop flying, you have to feed it stop flying velocities 13021 // It turns out to get the agent to stop flying, you have to feed it stop flying velocities
12721 // There's no explicit message to send the client to tell it to stop flying.. it relies on the 13022 // There's no explicit message to send the client to tell it to stop flying.. it relies on the
12722 // velocity, collision plane and avatar height 13023 // velocity, collision plane and avatar height
@@ -12724,34 +13025,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12724 // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air 13025 // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air
12725 // when the avatar stands up 13026 // when the avatar stands up
12726 13027
12727 Vector3 pos = presence.AbsolutePosition;
12728
12729 if (presence.Appearance.AvatarHeight != 127.0f)
12730 pos += new Vector3(0f, 0f, (presence.Appearance.AvatarHeight/6f));
12731 else
12732 pos += new Vector3(0f, 0f, (1.56f/6f));
12733
12734 presence.AbsolutePosition = pos;
12735
12736 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
12737 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
12738 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
12739 // certain amount.. because the LLClient wouldn't land in that situation anyway.
12740
12741 // why are we still testing for this really old height value default???
12742 if (presence.Appearance.AvatarHeight != 127.0f)
12743 presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - presence.Appearance.AvatarHeight/6f);
12744 else
12745 presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f/6f));
12746
12747
12748 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = 13028 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block =
12749 CreateImprovedTerseBlock(p, false); 13029 CreateImprovedTerseBlock(p, false);
12750 13030
12751 const float TIME_DILATION = 1.0f; 13031 const float TIME_DILATION = 1.0f;
12752 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 13032 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
12753 13033
12754
12755 ImprovedTerseObjectUpdatePacket packet 13034 ImprovedTerseObjectUpdatePacket packet
12756 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( 13035 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
12757 PacketType.ImprovedTerseObjectUpdate); 13036 PacketType.ImprovedTerseObjectUpdate);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs
index 073c357..41dd4d1 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs
@@ -206,6 +206,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
206 } 206 }
207 } 207 }
208 208
209 public bool HasUpdates()
210 {
211 J2KImage image = GetHighestPriorityImage();
212
213 return image != null && image.IsDecoded;
214 }
215
209 public bool ProcessImageQueue(int packetsToSend) 216 public bool ProcessImageQueue(int packetsToSend)
210 { 217 {
211 int packetsSent = 0; 218 int packetsSent = 0;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index e52ac37..bd4e617 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -31,6 +31,7 @@ using System.Net;
31using System.Threading; 31using System.Threading;
32using log4net; 32using log4net;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Monitoring;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenMetaverse.Packets; 36using OpenMetaverse.Packets;
36 37
@@ -81,6 +82,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
81 /// hooked to put more data on the empty queue</summary> 82 /// hooked to put more data on the empty queue</summary>
82 public event QueueEmpty OnQueueEmpty; 83 public event QueueEmpty OnQueueEmpty;
83 84
85 public event Func<ThrottleOutPacketTypeFlags, bool> HasUpdates;
86
84 /// <summary>AgentID for this client</summary> 87 /// <summary>AgentID for this client</summary>
85 public readonly UUID AgentID; 88 public readonly UUID AgentID;
86 /// <summary>The remote address of the connected client</summary> 89 /// <summary>The remote address of the connected client</summary>
@@ -161,6 +164,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
161 public bool m_deliverPackets = true; 164 public bool m_deliverPackets = true;
162 165
163 /// <summary> 166 /// <summary>
167 /// This is the percentage of the udp texture queue to add to the task queue since
168 /// textures are now generally handled through http.
169 /// </summary>
170 private double m_cannibalrate = 0.0;
171
172 private ClientInfo m_info = new ClientInfo();
173
174 /// <summary>
164 /// Default constructor 175 /// Default constructor
165 /// </summary> 176 /// </summary>
166 /// <param name="server">Reference to the UDP server this client is connected to</param> 177 /// <param name="server">Reference to the UDP server this client is connected to</param>
@@ -197,6 +208,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
197 // Create an array of token buckets for this clients different throttle categories 208 // Create an array of token buckets for this clients different throttle categories
198 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT]; 209 m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
199 210
211 m_cannibalrate = rates.CannibalizeTextureRate;
212
200 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 213 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
201 { 214 {
202 ThrottleOutPacketType type = (ThrottleOutPacketType)i; 215 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
@@ -241,20 +254,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
241 // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists 254 // TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
242 // of pending and needed ACKs for every client every time some method wants information about 255 // of pending and needed ACKs for every client every time some method wants information about
243 // this connection is a recipe for poor performance 256 // this connection is a recipe for poor performance
244 ClientInfo info = new ClientInfo(); 257
245 info.pendingAcks = new Dictionary<uint, uint>(); 258 m_info.resendThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate;
246 info.needAck = new Dictionary<uint, byte[]>(); 259 m_info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
247 260 m_info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
248 info.resendThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate; 261 m_info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
249 info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate; 262 m_info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
250 info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate; 263 m_info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
251 info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate; 264 m_info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
252 info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate; 265 m_info.totalThrottle = (int)m_throttleCategory.DripRate;
253 info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate; 266
254 info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate; 267 return m_info;
255 info.totalThrottle = (int)m_throttleCategory.DripRate;
256
257 return info;
258 } 268 }
259 269
260 /// <summary> 270 /// <summary>
@@ -348,6 +358,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
348 texture = Math.Max(texture, LLUDPServer.MTU); 358 texture = Math.Max(texture, LLUDPServer.MTU);
349 asset = Math.Max(asset, LLUDPServer.MTU); 359 asset = Math.Max(asset, LLUDPServer.MTU);
350 360
361 // Since most textures are now delivered through http, make it possible
362 // to cannibalize some of the bw from the texture throttle to use for
363 // the task queue (e.g. object updates)
364 task = task + (int)(m_cannibalrate * texture);
365 texture = (int)((1 - m_cannibalrate) * texture);
366
351 //int total = resend + land + wind + cloud + task + texture + asset; 367 //int total = resend + land + wind + cloud + task + texture + asset;
352 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}", 368 //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
353 // AgentID, resend, land, wind, cloud, task, texture, asset, total); 369 // AgentID, resend, land, wind, cloud, task, texture, asset, total);
@@ -646,15 +662,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
646 /// <param name="categories">Throttle categories to fire the callback for</param> 662 /// <param name="categories">Throttle categories to fire the callback for</param>
647 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories) 663 private void BeginFireQueueEmpty(ThrottleOutPacketTypeFlags categories)
648 { 664 {
649 if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty) 665// if (m_nextOnQueueEmpty != 0 && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
666 if (!m_isQueueEmptyRunning && (Environment.TickCount & Int32.MaxValue) >= m_nextOnQueueEmpty)
650 { 667 {
668 m_isQueueEmptyRunning = true;
669
670 int start = Environment.TickCount & Int32.MaxValue;
671 const int MIN_CALLBACK_MS = 30;
672
673 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
674 if (m_nextOnQueueEmpty == 0)
675 m_nextOnQueueEmpty = 1;
676
651 // Use a value of 0 to signal that FireQueueEmpty is running 677 // Use a value of 0 to signal that FireQueueEmpty is running
652 m_nextOnQueueEmpty = 0; 678// m_nextOnQueueEmpty = 0;
653 // Asynchronously run the callback 679
654 Util.FireAndForget(FireQueueEmpty, categories); 680 m_categories = categories;
681
682 if (HasUpdates(m_categories))
683 {
684 // Asynchronously run the callback
685 Util.FireAndForget(FireQueueEmpty, categories);
686 }
687 else
688 {
689 m_isQueueEmptyRunning = false;
690 }
655 } 691 }
656 } 692 }
657 693
694 private bool m_isQueueEmptyRunning;
695 private ThrottleOutPacketTypeFlags m_categories = 0;
696
658 /// <summary> 697 /// <summary>
659 /// Fires the OnQueueEmpty callback and sets the minimum time that it 698 /// Fires the OnQueueEmpty callback and sets the minimum time that it
660 /// can be called again 699 /// can be called again
@@ -664,22 +703,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
664 /// signature</param> 703 /// signature</param>
665 private void FireQueueEmpty(object o) 704 private void FireQueueEmpty(object o)
666 { 705 {
667 const int MIN_CALLBACK_MS = 30; 706// int start = Environment.TickCount & Int32.MaxValue;
707// const int MIN_CALLBACK_MS = 30;
668 708
669 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o; 709// if (m_udpServer.IsRunningOutbound)
670 QueueEmpty callback = OnQueueEmpty; 710// {
671 711 ThrottleOutPacketTypeFlags categories = (ThrottleOutPacketTypeFlags)o;
672 int start = Environment.TickCount & Int32.MaxValue; 712 QueueEmpty callback = OnQueueEmpty;
673 713
674 if (callback != null) 714 if (callback != null)
675 { 715 {
676 try { callback(categories); } 716// if (m_udpServer.IsRunningOutbound)
677 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); } 717// {
678 } 718 try { callback(categories); }
719 catch (Exception e) { m_log.Error("[LLUDPCLIENT]: OnQueueEmpty(" + categories + ") threw an exception: " + e.Message, e); }
720// }
721 }
722// }
723
724// m_nextOnQueueEmpty = start + MIN_CALLBACK_MS;
725// if (m_nextOnQueueEmpty == 0)
726// m_nextOnQueueEmpty = 1;
727
728// }
679 729
680 m_nextOnQueueEmpty = start + MIN_CALLBACK_MS; 730 m_isQueueEmptyRunning = false;
681 if (m_nextOnQueueEmpty == 0)
682 m_nextOnQueueEmpty = 1;
683 } 731 }
684 internal void ForceThrottleSetting(int throttle, int setting) 732 internal void ForceThrottleSetting(int throttle, int setting)
685 { 733 {
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 4154ef2..50dae2a 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -34,6 +34,7 @@ using System.Net.Sockets;
34using System.Reflection; 34using System.Reflection;
35using System.Threading; 35using System.Threading;
36using log4net; 36using log4net;
37using NDesk.Options;
37using Nini.Config; 38using Nini.Config;
38using OpenMetaverse.Packets; 39using OpenMetaverse.Packets;
39using OpenSim.Framework; 40using OpenSim.Framework;
@@ -62,20 +63,41 @@ namespace OpenSim.Region.ClientStack.LindenUDP
62 m_udpServer = new LLUDPServer(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager); 63 m_udpServer = new LLUDPServer(listenIP, ref port, proxyPortOffsetParm, allow_alternate_port, configSource, circuitManager);
63 } 64 }
64 65
65 public void NetworkStop()
66 {
67 m_udpServer.Stop();
68 }
69
70 public void AddScene(IScene scene) 66 public void AddScene(IScene scene)
71 { 67 {
72 m_udpServer.AddScene(scene); 68 m_udpServer.AddScene(scene);
73 69
74 StatsManager.RegisterStat( 70 StatsManager.RegisterStat(
75 new Stat( 71 new Stat(
72 "ClientLogoutsDueToNoReceives",
73 "Number of times a client has been logged out because no packets were received before the timeout.",
74 "",
75 "",
76 "clientstack",
77 scene.Name,
78 StatType.Pull,
79 MeasuresOfInterest.None,
80 stat => stat.Value = m_udpServer.ClientLogoutsDueToNoReceives,
81 StatVerbosity.Debug));
82
83 StatsManager.RegisterStat(
84 new Stat(
85 "IncomingUDPReceivesCount",
86 "Number of UDP receives performed",
87 "",
88 "",
89 "clientstack",
90 scene.Name,
91 StatType.Pull,
92 MeasuresOfInterest.AverageChangeOverTime,
93 stat => stat.Value = m_udpServer.UdpReceives,
94 StatVerbosity.Debug));
95
96 StatsManager.RegisterStat(
97 new Stat(
76 "IncomingPacketsProcessedCount", 98 "IncomingPacketsProcessedCount",
77 "Number of inbound UDP packets processed", 99 "Number of inbound LL protocol packets processed",
78 "Number of inbound UDP packets processed", 100 "",
79 "", 101 "",
80 "clientstack", 102 "clientstack",
81 scene.Name, 103 scene.Name,
@@ -83,6 +105,86 @@ namespace OpenSim.Region.ClientStack.LindenUDP
83 MeasuresOfInterest.AverageChangeOverTime, 105 MeasuresOfInterest.AverageChangeOverTime,
84 stat => stat.Value = m_udpServer.IncomingPacketsProcessed, 106 stat => stat.Value = m_udpServer.IncomingPacketsProcessed,
85 StatVerbosity.Debug)); 107 StatVerbosity.Debug));
108
109 StatsManager.RegisterStat(
110 new Stat(
111 "IncomingPacketsMalformedCount",
112 "Number of inbound UDP packets that could not be recognized as LL protocol packets.",
113 "",
114 "",
115 "clientstack",
116 scene.Name,
117 StatType.Pull,
118 MeasuresOfInterest.AverageChangeOverTime,
119 stat => stat.Value = m_udpServer.IncomingMalformedPacketCount,
120 StatVerbosity.Info));
121
122 StatsManager.RegisterStat(
123 new Stat(
124 "IncomingPacketsOrphanedCount",
125 "Number of inbound packets that were not initial connections packets and could not be associated with a viewer.",
126 "",
127 "",
128 "clientstack",
129 scene.Name,
130 StatType.Pull,
131 MeasuresOfInterest.AverageChangeOverTime,
132 stat => stat.Value = m_udpServer.IncomingOrphanedPacketCount,
133 StatVerbosity.Info));
134
135 StatsManager.RegisterStat(
136 new Stat(
137 "IncomingPacketsResentCount",
138 "Number of inbound packets that clients indicate are resends.",
139 "",
140 "",
141 "clientstack",
142 scene.Name,
143 StatType.Pull,
144 MeasuresOfInterest.AverageChangeOverTime,
145 stat => stat.Value = m_udpServer.IncomingPacketsResentCount,
146 StatVerbosity.Debug));
147
148 StatsManager.RegisterStat(
149 new Stat(
150 "OutgoingUDPSendsCount",
151 "Number of UDP sends performed",
152 "",
153 "",
154 "clientstack",
155 scene.Name,
156 StatType.Pull,
157 MeasuresOfInterest.AverageChangeOverTime,
158 stat => stat.Value = m_udpServer.UdpSends,
159 StatVerbosity.Debug));
160
161 StatsManager.RegisterStat(
162 new Stat(
163 "OutgoingPacketsResentCount",
164 "Number of packets resent because a client did not acknowledge receipt",
165 "",
166 "",
167 "clientstack",
168 scene.Name,
169 StatType.Pull,
170 MeasuresOfInterest.AverageChangeOverTime,
171 stat => stat.Value = m_udpServer.PacketsResentCount,
172 StatVerbosity.Debug));
173
174 StatsManager.RegisterStat(
175 new Stat(
176 "AverageUDPProcessTime",
177 "Average number of milliseconds taken to process each incoming UDP packet in a sample.",
178 "This is for initial receive processing which is separate from the later client LL packet processing stage.",
179 "ms",
180 "clientstack",
181 scene.Name,
182 StatType.Pull,
183 MeasuresOfInterest.None,
184 stat => stat.Value = m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond,
185// stat =>
186// stat.Value = Math.Round(m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond, 7),
187 StatVerbosity.Debug));
86 } 188 }
87 189
88 public bool HandlesRegion(Location x) 190 public bool HandlesRegion(Location x)
@@ -107,10 +209,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
107 /// </summary> 209 /// </summary>
108 public class LLUDPServer : OpenSimUDPBase 210 public class LLUDPServer : OpenSimUDPBase
109 { 211 {
212 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
213
110 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary> 214 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
111 public const int MTU = 1400; 215 public const int MTU = 1400;
112 216
113 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 217 /// <summary>Number of forced client logouts due to no receipt of packets before timeout.</summary>
218 public int ClientLogoutsDueToNoReceives { get; private set; }
219
220 /// <summary>
221 /// Default packet debug level given to new clients
222 /// </summary>
223 public int DefaultClientPacketDebugLevel { get; set; }
114 224
115 /// <summary>The measured resolution of Environment.TickCount</summary> 225 /// <summary>The measured resolution of Environment.TickCount</summary>
116 public readonly float TickCountResolution; 226 public readonly float TickCountResolution;
@@ -184,6 +294,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
184 protected bool m_sendPing; 294 protected bool m_sendPing;
185 295
186 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 296 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
297
298 /// <summary>
299 /// Event used to signal when queued packets are available for sending.
300 /// </summary>
301 /// <remarks>
302 /// This allows the outbound loop to only operate when there is data to send rather than continuously polling.
303 /// Some data is sent immediately and not queued. That data would not trigger this event.
304 /// </remarks>
305 private AutoResetEvent m_dataPresentEvent = new AutoResetEvent(false);
306
187 private Pool<IncomingPacket> m_incomingPacketPool; 307 private Pool<IncomingPacket> m_incomingPacketPool;
188 308
189 /// <summary> 309 /// <summary>
@@ -204,7 +324,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
204 324
205 public Socket Server { get { return null; } } 325 public Socket Server { get { return null; } }
206 326
207 private int m_malformedCount = 0; // Guard against a spamming attack 327 /// <summary>
328 /// Record how many packets have been resent
329 /// </summary>
330 internal int PacketsResentCount { get; set; }
331
332 /// <summary>
333 /// Record how many packets have been sent
334 /// </summary>
335 internal int PacketsSentCount { get; set; }
336
337 /// <summary>
338 /// Record how many incoming packets are indicated as resends by clients.
339 /// </summary>
340 internal int IncomingPacketsResentCount { get; set; }
341
342 /// <summary>
343 /// Record how many inbound packets could not be recognized as LLUDP packets.
344 /// </summary>
345 public int IncomingMalformedPacketCount { get; private set; }
346
347 /// <summary>
348 /// Record how many inbound packets could not be associated with a simulator circuit.
349 /// </summary>
350 public int IncomingOrphanedPacketCount { get; private set; }
208 351
209 /// <summary> 352 /// <summary>
210 /// Record current outgoing client for monitoring purposes. 353 /// Record current outgoing client for monitoring purposes.
@@ -461,6 +604,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
461 m_scene = (Scene)scene; 604 m_scene = (Scene)scene;
462 m_location = new Location(m_scene.RegionInfo.RegionHandle); 605 m_location = new Location(m_scene.RegionInfo.RegionHandle);
463 606
607 StatsManager.RegisterStat(
608 new Stat(
609 "InboxPacketsCount",
610 "Number of LL protocol packets waiting for the second stage of processing after initial receive.",
611 "Number of LL protocol packets waiting for the second stage of processing after initial receive.",
612 "",
613 "clientstack",
614 scene.Name,
615 StatType.Pull,
616 MeasuresOfInterest.AverageChangeOverTime,
617 stat => stat.Value = packetInbox.Count,
618 StatVerbosity.Debug));
619
464 // XXX: These stats are also pool stats but we register them separately since they are currently not 620 // XXX: These stats are also pool stats but we register them separately since they are currently not
465 // turned on and off by EnablePools()/DisablePools() 621 // turned on and off by EnablePools()/DisablePools()
466 StatsManager.RegisterStat( 622 StatsManager.RegisterStat(
@@ -521,6 +677,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
521 EnablePoolStats(); 677 EnablePoolStats();
522 678
523 MainConsole.Instance.Commands.AddCommand( 679 MainConsole.Instance.Commands.AddCommand(
680 "Debug", false, "debug lludp packet",
681 "debug lludp packet [--default] <level> [<avatar-first-name> <avatar-last-name>]",
682 "Turn on packet debugging",
683 "If level > 255 then all incoming and outgoing packets are logged.\n"
684 + "If level <= 255 then incoming AgentUpdate and outgoing SimStats and SimulatorViewerTimeMessage packets are not logged.\n"
685 + "If level <= 200 then incoming RequestImage and outgoing ImagePacket, ImageData, LayerData and CoarseLocationUpdate packets are not logged.\n"
686 + "If level <= 100 then incoming ViewerEffect and AgentAnimation and outgoing ViewerEffect and AvatarAnimation packets are not logged.\n"
687 + "If level <= 50 then outgoing ImprovedTerseObjectUpdate packets are not logged.\n"
688 + "If level <= 0 then no packets are logged.\n"
689 + "If --default is specified then the level becomes the default logging level for all subsequent agents.\n"
690 + "In this case, you cannot also specify an avatar name.\n"
691 + "If an avatar name is given then only packets from that avatar are logged.",
692 HandlePacketCommand);
693
694 MainConsole.Instance.Commands.AddCommand(
524 "Debug", 695 "Debug",
525 false, 696 false,
526 "debug lludp start", 697 "debug lludp start",
@@ -559,10 +730,78 @@ namespace OpenSim.Region.ClientStack.LindenUDP
559 "debug lludp status", 730 "debug lludp status",
560 "Return status of LLUDP packet processing.", 731 "Return status of LLUDP packet processing.",
561 HandleStatusCommand); 732 HandleStatusCommand);
733
734 MainConsole.Instance.Commands.AddCommand(
735 "Debug",
736 false,
737 "debug lludp toggle agentupdate",
738 "debug lludp toggle agentupdate",
739 "Toggle whether agentupdate packets are processed or simply discarded.",
740 HandleAgentUpdateCommand);
741 }
742
743 private void HandlePacketCommand(string module, string[] args)
744 {
745 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
746 return;
747
748 bool setAsDefaultLevel = false;
749 OptionSet optionSet = new OptionSet().Add("default", o => setAsDefaultLevel = o != null);
750 List<string> filteredArgs = optionSet.Parse(args);
751
752 string name = null;
753
754 if (filteredArgs.Count == 6)
755 {
756 if (!setAsDefaultLevel)
757 {
758 name = string.Format("{0} {1}", filteredArgs[4], filteredArgs[5]);
759 }
760 else
761 {
762 MainConsole.Instance.OutputFormat("ERROR: Cannot specify a user name when setting default logging level");
763 return;
764 }
765 }
766
767 if (filteredArgs.Count > 3)
768 {
769 int newDebug;
770 if (int.TryParse(filteredArgs[3], out newDebug))
771 {
772 if (setAsDefaultLevel)
773 {
774 DefaultClientPacketDebugLevel = newDebug;
775 MainConsole.Instance.OutputFormat(
776 "Debug packet debug for new clients set to {0} in {1}", DefaultClientPacketDebugLevel, m_scene.Name);
777 }
778 else
779 {
780 m_scene.ForEachScenePresence(sp =>
781 {
782 if (name == null || sp.Name == name)
783 {
784 MainConsole.Instance.OutputFormat(
785 "Packet debug for {0} ({1}) set to {2} in {3}",
786 sp.Name, sp.IsChildAgent ? "child" : "root", newDebug, m_scene.Name);
787
788 sp.ControllingClient.DebugPacketLevel = newDebug;
789 }
790 });
791 }
792 }
793 else
794 {
795 MainConsole.Instance.Output("Usage: debug lludp packet [--default] 0..255 [<first-name> <last-name>]");
796 }
797 }
562 } 798 }
563 799
564 private void HandleStartCommand(string module, string[] args) 800 private void HandleStartCommand(string module, string[] args)
565 { 801 {
802 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
803 return;
804
566 if (args.Length != 4) 805 if (args.Length != 4)
567 { 806 {
568 MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>"); 807 MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>");
@@ -580,6 +819,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
580 819
581 private void HandleStopCommand(string module, string[] args) 820 private void HandleStopCommand(string module, string[] args)
582 { 821 {
822 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
823 return;
824
583 if (args.Length != 4) 825 if (args.Length != 4)
584 { 826 {
585 MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>"); 827 MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>");
@@ -597,6 +839,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
597 839
598 private void HandlePoolCommand(string module, string[] args) 840 private void HandlePoolCommand(string module, string[] args)
599 { 841 {
842 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
843 return;
844
600 if (args.Length != 4) 845 if (args.Length != 4)
601 { 846 {
602 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>"); 847 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
@@ -627,8 +872,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
627 } 872 }
628 } 873 }
629 874
875 bool m_discardAgentUpdates;
876
877 private void HandleAgentUpdateCommand(string module, string[] args)
878 {
879 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
880 return;
881
882 m_discardAgentUpdates = !m_discardAgentUpdates;
883
884 MainConsole.Instance.OutputFormat(
885 "Discard AgentUpdates now {0} for {1}", m_discardAgentUpdates, m_scene.Name);
886 }
887
630 private void HandleStatusCommand(string module, string[] args) 888 private void HandleStatusCommand(string module, string[] args)
631 { 889 {
890 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
891 return;
892
632 MainConsole.Instance.OutputFormat( 893 MainConsole.Instance.OutputFormat(
633 "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled"); 894 "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled");
634 895
@@ -636,6 +897,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
636 "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); 897 "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled");
637 898
638 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off"); 899 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off");
900
901 MainConsole.Instance.OutputFormat(
902 "Packet debug level for new clients is {0}", DefaultClientPacketDebugLevel);
639 } 903 }
640 904
641 public bool HandlesRegion(Location x) 905 public bool HandlesRegion(Location x)
@@ -643,44 +907,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
643 return x == m_location; 907 return x == m_location;
644 } 908 }
645 909
646 public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting) 910// public void BroadcastPacket(Packet packet, ThrottleOutPacketType category, bool sendToPausedAgents, bool allowSplitting)
647 { 911// {
648 // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way 912// // CoarseLocationUpdate and AvatarGroupsReply packets cannot be split in an automated way
649 if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting) 913// if ((packet.Type == PacketType.CoarseLocationUpdate || packet.Type == PacketType.AvatarGroupsReply) && allowSplitting)
650 allowSplitting = false; 914// allowSplitting = false;
651 915//
652 if (allowSplitting && packet.HasVariableBlocks) 916// if (allowSplitting && packet.HasVariableBlocks)
653 { 917// {
654 byte[][] datas = packet.ToBytesMultiple(); 918// byte[][] datas = packet.ToBytesMultiple();
655 int packetCount = datas.Length; 919// int packetCount = datas.Length;
656 920//
657 if (packetCount < 1) 921// if (packetCount < 1)
658 m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length); 922// m_log.Error("[LLUDPSERVER]: Failed to split " + packet.Type + " with estimated length " + packet.Length);
659 923//
660 for (int i = 0; i < packetCount; i++) 924// for (int i = 0; i < packetCount; i++)
661 { 925// {
662 byte[] data = datas[i]; 926// byte[] data = datas[i];
663 m_scene.ForEachClient( 927// m_scene.ForEachClient(
664 delegate(IClientAPI client) 928// delegate(IClientAPI client)
665 { 929// {
666 if (client is LLClientView) 930// if (client is LLClientView)
667 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); 931// SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
668 } 932// }
669 ); 933// );
670 } 934// }
671 } 935// }
672 else 936// else
673 { 937// {
674 byte[] data = packet.ToBytes(); 938// byte[] data = packet.ToBytes();
675 m_scene.ForEachClient( 939// m_scene.ForEachClient(
676 delegate(IClientAPI client) 940// delegate(IClientAPI client)
677 { 941// {
678 if (client is LLClientView) 942// if (client is LLClientView)
679 SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null); 943// SendPacketData(((LLClientView)client).UDPClient, data, packet.Type, category, null);
680 } 944// }
681 ); 945// );
682 } 946// }
683 } 947// }
684 948
685 /// <summary> 949 /// <summary>
686 /// Start the process of sending a packet to the client. 950 /// Start the process of sending a packet to the client.
@@ -700,6 +964,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
700 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting) 964 if (packet.Type == PacketType.CoarseLocationUpdate && allowSplitting)
701 allowSplitting = false; 965 allowSplitting = false;
702 966
967 bool packetQueued = false;
968
703 if (allowSplitting && packet.HasVariableBlocks) 969 if (allowSplitting && packet.HasVariableBlocks)
704 { 970 {
705 byte[][] datas = packet.ToBytesMultiple(); 971 byte[][] datas = packet.ToBytesMultiple();
@@ -711,16 +977,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
711 for (int i = 0; i < packetCount; i++) 977 for (int i = 0; i < packetCount; i++)
712 { 978 {
713 byte[] data = datas[i]; 979 byte[] data = datas[i];
714 SendPacketData(udpClient, data, packet.Type, category, method); 980
981 if (!SendPacketData(udpClient, data, packet.Type, category, method))
982 packetQueued = true;
715 } 983 }
716 } 984 }
717 else 985 else
718 { 986 {
719 byte[] data = packet.ToBytes(); 987 byte[] data = packet.ToBytes();
720 SendPacketData(udpClient, data, packet.Type, category, method); 988 packetQueued = SendPacketData(udpClient, data, packet.Type, category, method);
721 } 989 }
722 990
723 PacketPool.Instance.ReturnPacket(packet); 991 PacketPool.Instance.ReturnPacket(packet);
992
993 if (packetQueued)
994 m_dataPresentEvent.Set();
724 } 995 }
725 996
726 /// <summary> 997 /// <summary>
@@ -734,7 +1005,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
734 /// The method to call if the packet is not acked by the client. If null, then a standard 1005 /// The method to call if the packet is not acked by the client. If null, then a standard
735 /// resend of the packet is done. 1006 /// resend of the packet is done.
736 /// </param> 1007 /// </param>
737 public void SendPacketData( 1008 /// <returns>true if the data was sent immediately, false if it was queued for sending</returns>
1009 public bool SendPacketData(
738 LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method) 1010 LLUDPClient udpClient, byte[] data, PacketType type, ThrottleOutPacketType category, UnackedPacketMethod method)
739 { 1011 {
740 int dataLength = data.Length; 1012 int dataLength = data.Length;
@@ -807,7 +1079,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
807 // packet so that it isn't sent before a queued update packet. 1079 // packet so that it isn't sent before a queued update packet.
808 bool requestQueue = type == PacketType.KillObject; 1080 bool requestQueue = type == PacketType.KillObject;
809 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority)) 1081 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority))
1082 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue))
1083 {
810 SendPacketFinal(outgoingPacket); 1084 SendPacketFinal(outgoingPacket);
1085 return true;
1086 }
1087
1088 return false;
811 1089
812 #endregion Queue or Send 1090 #endregion Queue or Send
813 } 1091 }
@@ -883,7 +1161,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
883 // Fire this out on a different thread so that we don't hold up outgoing packet processing for 1161 // Fire this out on a different thread so that we don't hold up outgoing packet processing for
884 // everybody else if this is being called due to an ack timeout. 1162 // everybody else if this is being called due to an ack timeout.
885 // This is the same as processing as the async process of a logout request. 1163 // This is the same as processing as the async process of a logout request.
886 Util.FireAndForget(o => DeactivateClientDueToTimeout(client)); 1164 Util.FireAndForget(o => DeactivateClientDueToTimeout(client, timeoutTicks));
887 1165
888 return; 1166 return;
889 } 1167 }
@@ -988,6 +1266,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
988 else 1266 else
989 { 1267 {
990 Interlocked.Increment(ref udpClient.PacketsResent); 1268 Interlocked.Increment(ref udpClient.PacketsResent);
1269
1270 // We're not going to worry about interlock yet since its not currently critical that this total count
1271 // is 100% correct
1272 PacketsResentCount++;
991 } 1273 }
992 1274
993 #endregion Sequence Number Assignment 1275 #endregion Sequence Number Assignment
@@ -995,6 +1277,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
995 // Stats tracking 1277 // Stats tracking
996 Interlocked.Increment(ref udpClient.PacketsSent); 1278 Interlocked.Increment(ref udpClient.PacketsSent);
997 1279
1280 // We're not going to worry about interlock yet since its not currently critical that this total count
1281 // is 100% correct
1282 PacketsSentCount++;
1283
998 // Put the UDP payload on the wire 1284 // Put the UDP payload on the wire
999 AsyncBeginSend(buffer); 1285 AsyncBeginSend(buffer);
1000 1286
@@ -1002,6 +1288,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1002 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; 1288 outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue;
1003 } 1289 }
1004 1290
1291 private void RecordMalformedInboundPacket(IPEndPoint endPoint)
1292 {
1293// if (m_malformedCount < 100)
1294// m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
1295
1296 IncomingMalformedPacketCount++;
1297
1298 if ((IncomingMalformedPacketCount % 10000) == 0)
1299 m_log.WarnFormat(
1300 "[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack. Last was from {1}",
1301 IncomingMalformedPacketCount, endPoint);
1302 }
1303
1005 public override void PacketReceived(UDPPacketBuffer buffer) 1304 public override void PacketReceived(UDPPacketBuffer buffer)
1006 { 1305 {
1007 // Debugging/Profiling 1306 // Debugging/Profiling
@@ -1023,6 +1322,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1023// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", 1322// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
1024// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1323// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1025 1324
1325 RecordMalformedInboundPacket(endPoint);
1326
1026 return; // Drop undersized packet 1327 return; // Drop undersized packet
1027 } 1328 }
1028 1329
@@ -1041,6 +1342,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1041// "[LLUDPSERVER]: Dropping packet with malformed header received from {0} in {1}", 1342// "[LLUDPSERVER]: Dropping packet with malformed header received from {0} in {1}",
1042// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 1343// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1043 1344
1345 RecordMalformedInboundPacket(endPoint);
1346
1044 return; // Malformed header 1347 return; // Malformed header
1045 } 1348 }
1046 1349
@@ -1056,34 +1359,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1056 // Only allocate a buffer for zerodecoding if the packet is zerocoded 1359 // Only allocate a buffer for zerodecoding if the packet is zerocoded
1057 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 1360 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
1058 } 1361 }
1059 catch (MalformedDataException)
1060 {
1061 }
1062 catch (IndexOutOfRangeException)
1063 {
1064// m_log.WarnFormat(
1065// "[LLUDPSERVER]: Dropping short packet received from {0} in {1}",
1066// buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
1067
1068 return; // Drop short packet
1069 }
1070 catch (Exception e) 1362 catch (Exception e)
1071 { 1363 {
1072 if (m_malformedCount < 100) 1364 if (IncomingMalformedPacketCount < 100)
1073 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); 1365 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
1074
1075 m_malformedCount++;
1076
1077 if ((m_malformedCount % 100000) == 0)
1078 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount);
1079 } 1366 }
1080 1367
1081 // Fail-safe check 1368 // Fail-safe check
1082 if (packet == null) 1369 if (packet == null)
1083 { 1370 {
1084 m_log.ErrorFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}:", 1371 if (IncomingMalformedPacketCount < 100)
1085 buffer.DataLength, buffer.RemoteEndPoint); 1372 {
1086 m_log.Error(Utils.BytesToHexString(buffer.Data, buffer.DataLength, null)); 1373 m_log.WarnFormat("[LLUDPSERVER]: Malformed data, cannot parse {0} byte packet from {1}, data {2}:",
1374 buffer.DataLength, buffer.RemoteEndPoint, Utils.BytesToHexString(buffer.Data, buffer.DataLength, null));
1375 }
1376
1377 RecordMalformedInboundPacket(endPoint);
1378
1087 return; 1379 return;
1088 } 1380 }
1089 1381
@@ -1127,12 +1419,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1127 queue.Enqueue(buffer); 1419 queue.Enqueue(buffer);
1128 return; 1420 return;
1129 } 1421 }
1422 else if (packet.Type == PacketType.CompleteAgentMovement)
1423 {
1424 // Send ack straight away to let the viewer know that we got it.
1425 SendAckImmediate(endPoint, packet.Header.Sequence);
1426
1427 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1428 // buffer.
1429 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1430
1431 Util.FireAndForget(HandleCompleteMovementIntoRegion, array);
1432
1433 return;
1434 }
1130 } 1435 }
1131 1436
1132 // Determine which agent this packet came from 1437 // Determine which agent this packet came from
1133 if (client == null || !(client is LLClientView)) 1438 if (client == null || !(client is LLClientView))
1134 { 1439 {
1135 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 1440 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
1441
1442 IncomingOrphanedPacketCount++;
1443
1444 if ((IncomingOrphanedPacketCount % 10000) == 0)
1445 m_log.WarnFormat(
1446 "[LLUDPSERVER]: Received {0} orphaned packets so far. Last was from {1}",
1447 IncomingOrphanedPacketCount, endPoint);
1448
1136 return; 1449 return;
1137 } 1450 }
1138 1451
@@ -1211,6 +1524,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1211 1524
1212 #region Incoming Packet Accounting 1525 #region Incoming Packet Accounting
1213 1526
1527 // We're not going to worry about interlock yet since its not currently critical that this total count
1528 // is 100% correct
1529 if (packet.Header.Resent)
1530 IncomingPacketsResentCount++;
1531
1214 // Check the archive of received reliable packet IDs to see whether we already received this packet 1532 // Check the archive of received reliable packet IDs to see whether we already received this packet
1215 if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence)) 1533 if (packet.Header.Reliable && !udpClient.PacketArchive.TryEnqueue(packet.Header.Sequence))
1216 { 1534 {
@@ -1233,6 +1551,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1233 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length); 1551 LogPacketHeader(true, udpClient.CircuitCode, 0, packet.Type, (ushort)packet.Length);
1234 #endregion BinaryStats 1552 #endregion BinaryStats
1235 1553
1554 if (packet.Type == PacketType.AgentUpdate)
1555 {
1556 if (m_discardAgentUpdates)
1557 return;
1558
1559 ((LLClientView)client).TotalAgentUpdates++;
1560
1561 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
1562
1563 LLClientView llClient = client as LLClientView;
1564 if (agentUpdate.AgentData.SessionID != client.SessionId
1565 || agentUpdate.AgentData.AgentID != client.AgentId
1566 || !(llClient == null || llClient.CheckAgentUpdateSignificance(agentUpdate.AgentData)) )
1567 {
1568 PacketPool.Instance.ReturnPacket(packet);
1569 return;
1570 }
1571 }
1572
1236 #region Ping Check Handling 1573 #region Ping Check Handling
1237 1574
1238 if (packet.Type == PacketType.StartPingCheck) 1575 if (packet.Type == PacketType.StartPingCheck)
@@ -1421,7 +1758,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1421 1758
1422 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1759 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1423 if (client != null) 1760 if (client != null)
1424 client.SceneAgent.SendInitialDataToMe(); 1761 {
1762 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(uccp.CircuitCode.Code);
1763 bool tp = (aCircuit.teleportFlags > 0);
1764 // Let's delay this for TP agents, otherwise the viewer doesn't know where to get resources from
1765 if (!tp)
1766 client.SceneAgent.SendInitialDataToMe();
1767 }
1425 1768
1426 // Now we know we can handle more data 1769 // Now we know we can handle more data
1427 Thread.Sleep(200); 1770 Thread.Sleep(200);
@@ -1476,6 +1819,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1476 } 1819 }
1477 } 1820 }
1478 1821
1822 private void HandleCompleteMovementIntoRegion(object o)
1823 {
1824 IPEndPoint endPoint = null;
1825 IClientAPI client = null;
1826
1827 try
1828 {
1829 object[] array = (object[])o;
1830 endPoint = (IPEndPoint)array[0];
1831 CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1];
1832
1833 m_log.DebugFormat(
1834 "[LLUDPSERVER]: Handling CompleteAgentMovement request from {0} in {1}", endPoint, m_scene.Name);
1835
1836 // Determine which agent this packet came from
1837 // We need to wait here because in when using the OpenSimulator V2 teleport protocol to travel to a destination
1838 // simulator with no existing child presence, the viewer (at least LL 3.3.4) will send UseCircuitCode
1839 // and then CompleteAgentMovement immediately without waiting for an ack. As we are now handling these
1840 // packets asynchronously, we need to account for this thread proceeding more quickly than the
1841 // UseCircuitCode thread.
1842 int count = 40;
1843 while (count-- > 0)
1844 {
1845 if (m_scene.TryGetClient(endPoint, out client))
1846 {
1847 if (!client.IsActive)
1848 {
1849 // This check exists to catch a condition where the client has been closed by another thread
1850 // but has not yet been removed from the client manager (and possibly a new connection has
1851 // not yet been established).
1852 m_log.DebugFormat(
1853 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active yet. Waiting.",
1854 endPoint, client.Name, m_scene.Name);
1855 }
1856 else if (client.SceneAgent == null)
1857 {
1858 // This check exists to catch a condition where the new client has been added to the client
1859 // manager but the SceneAgent has not yet been set in Scene.AddNewAgent(). If we are too
1860 // eager, then the new ScenePresence may not have registered a listener for this messsage
1861 // before we try to process it.
1862 // XXX: A better long term fix may be to add the SceneAgent before the client is added to
1863 // the client manager
1864 m_log.DebugFormat(
1865 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.",
1866 endPoint, client.Name, m_scene.Name);
1867 }
1868 else
1869 {
1870 break;
1871 }
1872 }
1873 else
1874 {
1875 m_log.DebugFormat(
1876 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.",
1877 endPoint, m_scene.Name);
1878 }
1879
1880 Thread.Sleep(200);
1881 }
1882
1883 if (client == null)
1884 {
1885 m_log.DebugFormat(
1886 "[LLUDPSERVER]: No client found for CompleteAgentMovement from {0} in {1} after wait. Dropping.",
1887 endPoint, m_scene.Name);
1888
1889 return;
1890 }
1891 else if (!client.IsActive || client.SceneAgent == null)
1892 {
1893 // This check exists to catch a condition where the client has been closed by another thread
1894 // but has not yet been removed from the client manager.
1895 // The packet could be simply ignored but it is useful to know if this condition occurred for other debugging
1896 // purposes.
1897 m_log.DebugFormat(
1898 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active after wait. Dropping.",
1899 endPoint, client.Name, m_scene.Name);
1900
1901 return;
1902 }
1903
1904 IncomingPacket incomingPacket1;
1905
1906 // Inbox insertion
1907 if (UsePools)
1908 {
1909 incomingPacket1 = m_incomingPacketPool.GetObject();
1910 incomingPacket1.Client = (LLClientView)client;
1911 incomingPacket1.Packet = packet;
1912 }
1913 else
1914 {
1915 incomingPacket1 = new IncomingPacket((LLClientView)client, packet);
1916 }
1917
1918 packetInbox.Enqueue(incomingPacket1);
1919 }
1920 catch (Exception e)
1921 {
1922 m_log.ErrorFormat(
1923 "[LLUDPSERVER]: CompleteAgentMovement handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
1924 endPoint != null ? endPoint.ToString() : "n/a",
1925 client != null ? client.Name : "unknown",
1926 client != null ? client.AgentId.ToString() : "unknown",
1927 e.Message,
1928 e.StackTrace);
1929 }
1930 }
1931
1479 /// <summary> 1932 /// <summary>
1480 /// Send an ack immediately to the given endpoint. 1933 /// Send an ack immediately to the given endpoint.
1481 /// </summary> 1934 /// </summary>
@@ -1544,6 +1997,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1544 1997
1545 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1998 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1546 client.OnLogout += LogoutHandler; 1999 client.OnLogout += LogoutHandler;
2000 client.DebugPacketLevel = DefaultClientPacketDebugLevel;
1547 2001
1548 ((LLClientView)client).DisableFacelights = m_disableFacelights; 2002 ((LLClientView)client).DisableFacelights = m_disableFacelights;
1549 2003
@@ -1562,21 +2016,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1562 /// regular client pings. 2016 /// regular client pings.
1563 /// </remarks> 2017 /// </remarks>
1564 /// <param name='client'></param> 2018 /// <param name='client'></param>
1565 private void DeactivateClientDueToTimeout(LLClientView client) 2019 /// <param name='timeoutTicks'></param>
2020 private void DeactivateClientDueToTimeout(LLClientView client, int timeoutTicks)
1566 { 2021 {
1567 lock (client.CloseSyncLock) 2022 lock (client.CloseSyncLock)
1568 { 2023 {
2024 ClientLogoutsDueToNoReceives++;
2025
1569 m_log.WarnFormat( 2026 m_log.WarnFormat(
1570 "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}", 2027 "[LLUDPSERVER]: No packets received from {0} agent of {1} for {2}ms in {3}. Disconnecting.",
1571 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName); 2028 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, timeoutTicks, m_scene.Name);
1572
1573 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
1574 2029
1575 if (!client.SceneAgent.IsChildAgent) 2030 if (!client.SceneAgent.IsChildAgent)
1576 client.Kick("Simulator logged you out due to connection timeout"); 2031 client.Kick("Simulator logged you out due to connection timeout.");
1577
1578 client.CloseWithoutChecks(true);
1579 } 2032 }
2033
2034 m_scene.CloseAgent(client.AgentId, true);
1580 } 2035 }
1581 2036
1582 private void IncomingPacketHandler() 2037 private void IncomingPacketHandler()
@@ -1592,6 +2047,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1592 { 2047 {
1593 IncomingPacket incomingPacket = null; 2048 IncomingPacket incomingPacket = null;
1594 2049
2050 /*
1595 // HACK: This is a test to try and rate limit packet handling on Mono. 2051 // HACK: This is a test to try and rate limit packet handling on Mono.
1596 // If it works, a more elegant solution can be devised 2052 // If it works, a more elegant solution can be devised
1597 if (Util.FireAndForgetCount() < 2) 2053 if (Util.FireAndForgetCount() < 2)
@@ -1599,6 +2055,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1599 //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping"); 2055 //m_log.Debug("[LLUDPSERVER]: Incoming packet handler is sleeping");
1600 Thread.Sleep(30); 2056 Thread.Sleep(30);
1601 } 2057 }
2058 */
1602 2059
1603 if (packetInbox.Dequeue(100, ref incomingPacket)) 2060 if (packetInbox.Dequeue(100, ref incomingPacket))
1604 { 2061 {
@@ -1694,8 +2151,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1694 2151
1695 // If nothing was sent, sleep for the minimum amount of time before a 2152 // If nothing was sent, sleep for the minimum amount of time before a
1696 // token bucket could get more tokens 2153 // token bucket could get more tokens
2154 //if (!m_packetSent)
2155 // Thread.Sleep((int)TickCountResolution);
2156 //
2157 // Instead, now wait for data present to be explicitly signalled. Evidence so far is that with
2158 // modern mono it reduces CPU base load since there is no more continuous polling.
1697 if (!m_packetSent) 2159 if (!m_packetSent)
1698 Thread.Sleep((int)TickCountResolution); 2160 m_dataPresentEvent.WaitOne(100);
1699 2161
1700 Watchdog.UpdateThread(); 2162 Watchdog.UpdateThread();
1701 } 2163 }
@@ -1912,7 +2374,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1912 if (!client.IsLoggingOut) 2374 if (!client.IsLoggingOut)
1913 { 2375 {
1914 client.IsLoggingOut = true; 2376 client.IsLoggingOut = true;
1915 client.Close(false, false); 2377 m_scene.CloseAgent(client.AgentId, false);
1916 } 2378 }
1917 } 2379 }
1918 } 2380 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 7035e38..881e768 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -78,6 +78,36 @@ namespace OpenMetaverse
78 public bool IsRunningOutbound { get; private set; } 78 public bool IsRunningOutbound { get; private set; }
79 79
80 /// <summary> 80 /// <summary>
81 /// Number of UDP receives.
82 /// </summary>
83 public int UdpReceives { get; private set; }
84
85 /// <summary>
86 /// Number of UDP sends
87 /// </summary>
88 public int UdpSends { get; private set; }
89
90 /// <summary>
91 /// Number of receives over which to establish a receive time average.
92 /// </summary>
93 private readonly static int s_receiveTimeSamples = 500;
94
95 /// <summary>
96 /// Current number of samples taken to establish a receive time average.
97 /// </summary>
98 private int m_currentReceiveTimeSamples;
99
100 /// <summary>
101 /// Cumulative receive time for the sample so far.
102 /// </summary>
103 private int m_receiveTicksInCurrentSamplePeriod;
104
105 /// <summary>
106 /// The average time taken for each require receive in the last sample.
107 /// </summary>
108 public float AverageReceiveTicksForLastSamplePeriod { get; private set; }
109
110 /// <summary>
81 /// Default constructor 111 /// Default constructor
82 /// </summary> 112 /// </summary>
83 /// <param name="bindAddress">Local IP address to bind the server to</param> 113 /// <param name="bindAddress">Local IP address to bind the server to</param>
@@ -111,6 +141,8 @@ namespace OpenMetaverse
111 141
112 if (!IsRunningInbound) 142 if (!IsRunningInbound)
113 { 143 {
144 m_log.DebugFormat("[UDPBASE]: Starting inbound UDP loop");
145
114 const int SIO_UDP_CONNRESET = -1744830452; 146 const int SIO_UDP_CONNRESET = -1744830452;
115 147
116 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 148 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
@@ -151,6 +183,8 @@ namespace OpenMetaverse
151 /// </summary> 183 /// </summary>
152 public void StartOutbound() 184 public void StartOutbound()
153 { 185 {
186 m_log.DebugFormat("[UDPBASE]: Starting outbound UDP loop");
187
154 IsRunningOutbound = true; 188 IsRunningOutbound = true;
155 } 189 }
156 190
@@ -158,10 +192,8 @@ namespace OpenMetaverse
158 { 192 {
159 if (IsRunningInbound) 193 if (IsRunningInbound)
160 { 194 {
161 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 195 m_log.DebugFormat("[UDPBASE]: Stopping inbound UDP loop");
162 // will deny any more reader locks, in effect blocking all other send/receive 196
163 // threads. Once we have the lock, we set IsRunningInbound = false to inform the other
164 // threads that the socket is closed.
165 IsRunningInbound = false; 197 IsRunningInbound = false;
166 m_udpSocket.Close(); 198 m_udpSocket.Close();
167 } 199 }
@@ -169,6 +201,8 @@ namespace OpenMetaverse
169 201
170 public void StopOutbound() 202 public void StopOutbound()
171 { 203 {
204 m_log.DebugFormat("[UDPBASE]: Stopping outbound UDP loop");
205
172 IsRunningOutbound = false; 206 IsRunningOutbound = false;
173 } 207 }
174 208
@@ -257,7 +291,16 @@ namespace OpenMetaverse
257 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort); 291 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
258 } 292 }
259 } 293 }
260 catch (ObjectDisposedException) { } 294 catch (ObjectDisposedException e)
295 {
296 m_log.Error(
297 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
298 }
299 catch (Exception e)
300 {
301 m_log.Error(
302 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
303 }
261 } 304 }
262 } 305 }
263 306
@@ -267,17 +310,21 @@ namespace OpenMetaverse
267 // to AsyncBeginReceive 310 // to AsyncBeginReceive
268 if (IsRunningInbound) 311 if (IsRunningInbound)
269 { 312 {
313 UdpReceives++;
314
270 // Asynchronous mode will start another receive before the 315 // Asynchronous mode will start another receive before the
271 // callback for this packet is even fired. Very parallel :-) 316 // callback for this packet is even fired. Very parallel :-)
272 if (m_asyncPacketHandling) 317 if (m_asyncPacketHandling)
273 AsyncBeginReceive(); 318 AsyncBeginReceive();
274 319
275 // get the buffer that was created in AsyncBeginReceive
276 // this is the received data
277 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
278
279 try 320 try
280 { 321 {
322 // get the buffer that was created in AsyncBeginReceive
323 // this is the received data
324 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
325
326 int startTick = Util.EnvironmentTickCount();
327
281 // get the length of data actually read from the socket, store it with the 328 // get the length of data actually read from the socket, store it with the
282 // buffer 329 // buffer
283 buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); 330 buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);
@@ -285,9 +332,42 @@ namespace OpenMetaverse
285 // call the abstract method PacketReceived(), passing the buffer that 332 // call the abstract method PacketReceived(), passing the buffer that
286 // has just been filled from the socket read. 333 // has just been filled from the socket read.
287 PacketReceived(buffer); 334 PacketReceived(buffer);
335
336 // If more than one thread can be calling AsyncEndReceive() at once (e.g. if m_asyncPacketHandler)
337 // then a particular stat may be inaccurate due to a race condition. We won't worry about this
338 // since this should be rare and won't cause a runtime problem.
339 if (m_currentReceiveTimeSamples >= s_receiveTimeSamples)
340 {
341 AverageReceiveTicksForLastSamplePeriod
342 = (float)m_receiveTicksInCurrentSamplePeriod / s_receiveTimeSamples;
343
344 m_receiveTicksInCurrentSamplePeriod = 0;
345 m_currentReceiveTimeSamples = 0;
346 }
347 else
348 {
349 m_receiveTicksInCurrentSamplePeriod += Util.EnvironmentTickCountSubtract(startTick);
350 m_currentReceiveTimeSamples++;
351 }
352 }
353 catch (SocketException se)
354 {
355 m_log.Error(
356 string.Format(
357 "[UDPBASE]: Error processing UDP end receive {0}, socket error code {1}. Exception ",
358 UdpReceives, se.ErrorCode),
359 se);
360 }
361 catch (ObjectDisposedException e)
362 {
363 m_log.Error(
364 string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e);
365 }
366 catch (Exception e)
367 {
368 m_log.Error(
369 string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e);
288 } 370 }
289 catch (SocketException) { }
290 catch (ObjectDisposedException) { }
291 finally 371 finally
292 { 372 {
293// if (UsePools) 373// if (UsePools)
@@ -298,14 +378,13 @@ namespace OpenMetaverse
298 if (!m_asyncPacketHandling) 378 if (!m_asyncPacketHandling)
299 AsyncBeginReceive(); 379 AsyncBeginReceive();
300 } 380 }
301
302 } 381 }
303 } 382 }
304 383
305 public void AsyncBeginSend(UDPPacketBuffer buf) 384 public void AsyncBeginSend(UDPPacketBuffer buf)
306 { 385 {
307 if (IsRunningOutbound) 386// if (IsRunningOutbound)
308 { 387// {
309 try 388 try
310 { 389 {
311 m_udpSocket.BeginSendTo( 390 m_udpSocket.BeginSendTo(
@@ -319,7 +398,7 @@ namespace OpenMetaverse
319 } 398 }
320 catch (SocketException) { } 399 catch (SocketException) { }
321 catch (ObjectDisposedException) { } 400 catch (ObjectDisposedException) { }
322 } 401// }
323 } 402 }
324 403
325 void AsyncEndSend(IAsyncResult result) 404 void AsyncEndSend(IAsyncResult result)
@@ -328,6 +407,8 @@ namespace OpenMetaverse
328 { 407 {
329// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; 408// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState;
330 m_udpSocket.EndSendTo(result); 409 m_udpSocket.EndSendTo(result);
410
411 UdpSends++;
331 } 412 }
332 catch (SocketException) { } 413 catch (SocketException) { }
333 catch (ObjectDisposedException) { } 414 catch (ObjectDisposedException) { }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
index 1fdc410..5a2bcee 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
@@ -145,39 +145,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
145 return packet; 145 return packet;
146 } 146 }
147 147
148 // private byte[] decoded_header = new byte[10];
149 private static PacketType GetType(byte[] bytes) 148 private static PacketType GetType(byte[] bytes)
150 { 149 {
151 byte[] decoded_header = new byte[10 + 8];
152 ushort id; 150 ushort id;
153 PacketFrequency freq; 151 PacketFrequency freq;
152 bool isZeroCoded = (bytes[0] & Helpers.MSG_ZEROCODED) != 0;
154 153
155 if ((bytes[0] & Helpers.MSG_ZEROCODED) != 0) 154 if (bytes[6] == 0xFF)
156 { 155 {
157 Helpers.ZeroDecode(bytes, 16, decoded_header); 156 if (bytes[7] == 0xFF)
158 }
159 else
160 {
161 Buffer.BlockCopy(bytes, 0, decoded_header, 0, 10);
162 }
163
164 if (decoded_header[6] == 0xFF)
165 {
166 if (decoded_header[7] == 0xFF)
167 { 157 {
168 id = (ushort) ((decoded_header[8] << 8) + decoded_header[9]);
169 freq = PacketFrequency.Low; 158 freq = PacketFrequency.Low;
159 if (isZeroCoded && bytes[8] == 0)
160 id = bytes[10];
161 else
162 id = (ushort)((bytes[8] << 8) + bytes[9]);
170 } 163 }
171 else 164 else
172 { 165 {
173 id = decoded_header[7];
174 freq = PacketFrequency.Medium; 166 freq = PacketFrequency.Medium;
167 id = bytes[7];
175 } 168 }
176 } 169 }
177 else 170 else
178 { 171 {
179 id = decoded_header[6];
180 freq = PacketFrequency.High; 172 freq = PacketFrequency.High;
173 id = bytes[6];
181 } 174 }
182 175
183 return Packet.GetType(id, freq); 176 return Packet.GetType(id, freq);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
index 98ef72f..f8d0c02 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
index 556df30..9700224 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
@@ -33,6 +33,7 @@ using NUnit.Framework;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Packets; 34using OpenMetaverse.Packets;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Monitoring;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using OpenSim.Tests.Common; 38using OpenSim.Tests.Common;
38using OpenSim.Tests.Common.Mock; 39using OpenSim.Tests.Common.Mock;
@@ -69,6 +70,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
69 { 70 {
70 base.SetUp(); 71 base.SetUp();
71 m_scene = new SceneHelpers().SetupScene(); 72 m_scene = new SceneHelpers().SetupScene();
73 StatsManager.SimExtraStats = new SimExtraStatsCollector();
72 } 74 }
73 75
74 /// <summary> 76 /// <summary>
@@ -198,7 +200,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
198 public void TestLogoutClientDueToAck() 200 public void TestLogoutClientDueToAck()
199 { 201 {
200 TestHelpers.InMethod(); 202 TestHelpers.InMethod();
201// TestHelpers.EnableLogging(); 203 TestHelpers.EnableLogging();
202 204
203 IniConfigSource ics = new IniConfigSource(); 205 IniConfigSource ics = new IniConfigSource();
204 IConfig config = ics.AddConfig("ClientStack.LindenUDP"); 206 IConfig config = ics.AddConfig("ClientStack.LindenUDP");
@@ -210,8 +212,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
210 212
211 ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID); 213 ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID);
212 Assert.That(spAfterAckTimeout, Is.Null); 214 Assert.That(spAfterAckTimeout, Is.Null);
213
214// TestHelpers.DisableLogging();
215 } 215 }
216 216
217// /// <summary> 217// /// <summary>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
index 7d9f581..575e54c 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
@@ -29,6 +29,7 @@ using System;
29using System.IO; 29using System.IO;
30using System.Net; 30using System.Net;
31using System.Reflection; 31using System.Reflection;
32using System.Threading;
32using log4net.Config; 33using log4net.Config;
33using Nini.Config; 34using Nini.Config;
34using NUnit.Framework; 35using NUnit.Framework;
@@ -53,6 +54,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
53 [TestFixtureSetUp] 54 [TestFixtureSetUp]
54 public void FixtureInit() 55 public void FixtureInit()
55 { 56 {
57 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
58 Util.FireAndForgetMethod = FireAndForgetMethod.None;
59
56 using ( 60 using (
57 Stream resource 61 Stream resource
58 = GetType().Assembly.GetManifestResourceStream( 62 = GetType().Assembly.GetManifestResourceStream(
@@ -72,9 +76,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
72 } 76 }
73 } 77 }
74 78
79 [TestFixtureTearDown]
80 public void TearDown()
81 {
82 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
83 // threads. Possibly, later tests should be rewritten not to worry about such things.
84 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
85 }
86
75 [SetUp] 87 [SetUp]
76 public void SetUp() 88 public override void SetUp()
77 { 89 {
90 base.SetUp();
91
78 UUID userId = TestHelpers.ParseTail(0x3); 92 UUID userId = TestHelpers.ParseTail(0x3);
79 93
80 J2KDecoderModule j2kdm = new J2KDecoderModule(); 94 J2KDecoderModule j2kdm = new J2KDecoderModule();
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
index 119a677..e2178e5 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
@@ -52,17 +52,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
52 public override void Update(int frames) {} 52 public override void Update(int frames) {}
53 public override void LoadWorldMap() {} 53 public override void LoadWorldMap() {}
54 54
55 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 55 public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type)
56 { 56 {
57 client.OnObjectName += RecordObjectNameCall; 57 client.OnObjectName += RecordObjectNameCall;
58 58
59 // FIXME 59 // FIXME
60 return null; 60 return null;
61 } 61 }
62 62
63 public override void RemoveClient(UUID agentID, bool someReason) {} 63 public override bool CloseAgent(UUID agentID, bool force) { return true; }
64// public override void CloseAllAgents(uint circuitcode) {} 64
65 public override bool CheckClient(UUID clientId, IPEndPoint endPoint) { return true; } 65 public override bool CheckClient(UUID clientId, IPEndPoint endPoint) { return true; }
66
66 public override void OtherRegionUp(GridRegion otherRegion) { } 67 public override void OtherRegionUp(GridRegion otherRegion) { }
67 68
68 public override bool TryGetScenePresence(UUID uuid, out ScenePresence sp) { sp = null; return false; } 69 public override bool TryGetScenePresence(UUID uuid, out ScenePresence sp) { sp = null; return false; }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
index c9aac0b..e5bae6e 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/ThrottleRates.cs
@@ -59,6 +59,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
59 /// <summary>Flag used to enable adaptive throttles</summary> 59 /// <summary>Flag used to enable adaptive throttles</summary>
60 public bool AdaptiveThrottlesEnabled; 60 public bool AdaptiveThrottlesEnabled;
61 61
62 /// <summary>Amount of the texture throttle to steal for the task throttle</summary>
63 public double CannibalizeTextureRate;
64
62 /// <summary> 65 /// <summary>
63 /// Default constructor 66 /// Default constructor
64 /// </summary> 67 /// </summary>
@@ -80,6 +83,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
80 Total = throttleConfig.GetInt("client_throttle_max_bps", 0); 83 Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
81 84
82 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false); 85 AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
86
87 CannibalizeTextureRate = (double)throttleConfig.GetFloat("CannibalizeTextureRate", 0.0f);
88 CannibalizeTextureRate = Util.Clamp<double>(CannibalizeTextureRate,0.0, 0.9);
83 } 89 }
84 catch (Exception) { } 90 catch (Exception) { }
85 } 91 }
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index da1ff2e..1e14f45 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -33,6 +33,7 @@ using OpenSim.Framework;
33 33
34using OpenSim.Region.Framework.Scenes; 34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Interfaces; 35using OpenSim.Services.Interfaces;
36using OpenSim.Region.Framework.Interfaces;
36 37
37namespace OpenSim.Region.CoreModules.Agent.AssetTransaction 38namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
38{ 39{
@@ -119,6 +120,14 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
119 } 120 }
120 else 121 else
121 { 122 {
123 // Check if the xfer is a terrain xfer
124 IEstateModule estateModule = m_Scene.RequestModuleInterface<IEstateModule>();
125 if (estateModule != null)
126 {
127 if (estateModule.IsTerrainXfer(xferID))
128 return;
129 }
130
122 m_log.ErrorFormat( 131 m_log.ErrorFormat(
123 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}", 132 "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}",
124 xferID, packetID, data.Length); 133 xferID, packetID, data.Length);
diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
index 3764685..d9b0eff 100644
--- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs
@@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender
166 166
167 // Do Decode! 167 // Do Decode!
168 if (decode) 168 if (decode)
169 Decode(assetID, j2kData); 169 Util.FireAndForget(delegate { Decode(assetID, j2kData); });
170 } 170 }
171 } 171 }
172 172
diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
index f43305f..9b0e1f4 100644
--- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs
@@ -194,10 +194,12 @@ namespace OpenSim.Region.CoreModules.Asset
194 194
195 #region IImprovedAssetCache Members 195 #region IImprovedAssetCache Members
196 196
197
198 public bool Check(string id) 197 public bool Check(string id)
199 { 198 {
200 return false; 199 AssetBase asset;
200
201 // XXX:This is probably not an efficient implementation.
202 return m_cache.TryGetValue(id, out asset);
201 } 203 }
202 204
203 /// <summary> 205 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
index 58ce61a..f720748 100644
--- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs
@@ -114,7 +114,8 @@ namespace OpenSim.Region.CoreModules.Asset
114 // 114 //
115 public bool Check(string id) 115 public bool Check(string id)
116 { 116 {
117 return false; 117 // XXX This is probably not an efficient implementation.
118 return Get(id) != null;
118 } 119 }
119 120
120 public void Cache(AssetBase asset) 121 public void Cache(AssetBase asset)
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index d510d82..b270de9 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -31,17 +31,16 @@
31using System; 31using System;
32using System.IO; 32using System.IO;
33using System.Collections.Generic; 33using System.Collections.Generic;
34using System.Linq;
34using System.Reflection; 35using System.Reflection;
35using System.Runtime.Serialization; 36using System.Runtime.Serialization;
36using System.Runtime.Serialization.Formatters.Binary; 37using System.Runtime.Serialization.Formatters.Binary;
37using System.Threading; 38using System.Threading;
38using System.Timers; 39using System.Timers;
39
40using log4net; 40using log4net;
41using Nini.Config; 41using Nini.Config;
42using Mono.Addins; 42using Mono.Addins;
43using OpenMetaverse; 43using OpenMetaverse;
44
45using OpenSim.Framework; 44using OpenSim.Framework;
46using OpenSim.Framework.Console; 45using OpenSim.Framework.Console;
47using OpenSim.Region.Framework.Interfaces; 46using OpenSim.Region.Framework.Interfaces;
@@ -76,8 +75,6 @@ namespace OpenSim.Region.CoreModules.Asset
76 private static ulong m_RequestsForInprogress; 75 private static ulong m_RequestsForInprogress;
77 private static ulong m_DiskHits; 76 private static ulong m_DiskHits;
78 private static ulong m_MemoryHits; 77 private static ulong m_MemoryHits;
79 private static double m_HitRateMemory;
80 private static double m_HitRateFile;
81 78
82#if WAIT_ON_INPROGRESS_REQUESTS 79#if WAIT_ON_INPROGRESS_REQUESTS
83 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>(); 80 private Dictionary<string, ManualResetEvent> m_CurrentlyWriting = new Dictionary<string, ManualResetEvent>();
@@ -251,71 +248,68 @@ namespace OpenSim.Region.CoreModules.Asset
251 248
252 private void UpdateFileCache(string key, AssetBase asset) 249 private void UpdateFileCache(string key, AssetBase asset)
253 { 250 {
254 // TODO: Spawn this off to some seperate thread to do the actual writing 251 string filename = GetFileName(key);
255 if (asset != null)
256 {
257 string filename = GetFileName(key);
258 252
259 try 253 try
254 {
255 // If the file is already cached, don't cache it, just touch it so access time is updated
256 if (File.Exists(filename))
260 { 257 {
261 // If the file is already cached, don't cache it, just touch it so access time is updated 258 // We don't really want to know about sharing
262 if (File.Exists(filename)) 259 // violations here. If the file is locked, then
260 // the other thread has updated the time for us.
261 try
263 { 262 {
264 // We don't really want to know about sharing 263 lock (m_CurrentlyWriting)
265 // violations here. If the file is locked, then
266 // the other thread has updated the time for us.
267 try
268 { 264 {
269 lock (m_CurrentlyWriting) 265 if (!m_CurrentlyWriting.Contains(filename))
270 { 266 File.SetLastAccessTime(filename, DateTime.Now);
271 if (!m_CurrentlyWriting.Contains(filename))
272 File.SetLastAccessTime(filename, DateTime.Now);
273 }
274 } 267 }
275 catch 268 }
269 catch
270 {
271 }
272 }
273 else
274 {
275 // Once we start writing, make sure we flag that we're writing
276 // that object to the cache so that we don't try to write the
277 // same file multiple times.
278 lock (m_CurrentlyWriting)
279 {
280#if WAIT_ON_INPROGRESS_REQUESTS
281 if (m_CurrentlyWriting.ContainsKey(filename))
276 { 282 {
283 return;
277 } 284 }
278 } else { 285 else
279
280 // Once we start writing, make sure we flag that we're writing
281 // that object to the cache so that we don't try to write the
282 // same file multiple times.
283 lock (m_CurrentlyWriting)
284 { 286 {
285#if WAIT_ON_INPROGRESS_REQUESTS 287 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
286 if (m_CurrentlyWriting.ContainsKey(filename)) 288 }
287 {
288 return;
289 }
290 else
291 {
292 m_CurrentlyWriting.Add(filename, new ManualResetEvent(false));
293 }
294 289
295#else 290#else
296 if (m_CurrentlyWriting.Contains(filename)) 291 if (m_CurrentlyWriting.Contains(filename))
297 { 292 {
298 return; 293 return;
299 }
300 else
301 {
302 m_CurrentlyWriting.Add(filename);
303 }
304#endif
305
306 } 294 }
295 else
296 {
297 m_CurrentlyWriting.Add(filename);
298 }
299#endif
307 300
308 Util.FireAndForget(
309 delegate { WriteFileCache(filename, asset); });
310 } 301 }
311 } 302
312 catch (Exception e) 303 Util.FireAndForget(
313 { 304 delegate { WriteFileCache(filename, asset); });
314 m_log.ErrorFormat(
315 "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}",
316 asset.ID, e.Message, e.StackTrace);
317 } 305 }
318 } 306 }
307 catch (Exception e)
308 {
309 m_log.ErrorFormat(
310 "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}",
311 asset.ID, e.Message, e.StackTrace);
312 }
319 } 313 }
320 314
321 public void Cache(AssetBase asset) 315 public void Cache(AssetBase asset)
@@ -350,15 +344,9 @@ namespace OpenSim.Region.CoreModules.Asset
350 344
351 private bool CheckFromMemoryCache(string id) 345 private bool CheckFromMemoryCache(string id)
352 { 346 {
353 AssetBase asset = null; 347 return m_MemoryCache.Contains(id);
354
355 if (m_MemoryCache.TryGetValue(id, out asset))
356 return true;
357
358 return false;
359 } 348 }
360 349
361
362 /// <summary> 350 /// <summary>
363 /// Try to get an asset from the file cache. 351 /// Try to get an asset from the file cache.
364 /// </summary> 352 /// </summary>
@@ -396,15 +384,16 @@ namespace OpenSim.Region.CoreModules.Asset
396 384
397 if (File.Exists(filename)) 385 if (File.Exists(filename))
398 { 386 {
399 FileStream stream = null;
400 try 387 try
401 { 388 {
402 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); 389 using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
403 BinaryFormatter bformatter = new BinaryFormatter(); 390 {
391 BinaryFormatter bformatter = new BinaryFormatter();
404 392
405 asset = (AssetBase)bformatter.Deserialize(stream); 393 asset = (AssetBase)bformatter.Deserialize(stream);
406 394
407 m_DiskHits++; 395 m_DiskHits++;
396 }
408 } 397 }
409 catch (System.Runtime.Serialization.SerializationException e) 398 catch (System.Runtime.Serialization.SerializationException e)
410 { 399 {
@@ -423,12 +412,6 @@ namespace OpenSim.Region.CoreModules.Asset
423 m_log.WarnFormat( 412 m_log.WarnFormat(
424 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", 413 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
425 filename, id, e.Message, e.StackTrace); 414 filename, id, e.Message, e.StackTrace);
426
427 }
428 finally
429 {
430 if (stream != null)
431 stream.Close();
432 } 415 }
433 } 416 }
434 417
@@ -440,36 +423,19 @@ namespace OpenSim.Region.CoreModules.Asset
440 bool found = false; 423 bool found = false;
441 424
442 string filename = GetFileName(id); 425 string filename = GetFileName(id);
426
443 if (File.Exists(filename)) 427 if (File.Exists(filename))
444 { 428 {
445 // actually check if we can open it, and so update expire
446 FileStream stream = null;
447 try 429 try
448 { 430 {
449 stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); 431 using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
450 if (stream != null)
451 { 432 {
452 found = true; 433 if (stream != null)
453 stream.Close(); 434 found = true;
454 } 435 }
455
456 }
457 catch (System.Runtime.Serialization.SerializationException e)
458 {
459 found = false;
460 m_log.ErrorFormat(
461 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}",
462 filename, id, e.Message, e.StackTrace);
463
464 // If there was a problem deserializing the asset, the asset may
465 // either be corrupted OR was serialized under an old format
466 // {different version of AssetBase} -- we should attempt to
467 // delete it and re-cache
468 File.Delete(filename);
469 } 436 }
470 catch (Exception e) 437 catch (Exception e)
471 { 438 {
472 found = false;
473 m_log.ErrorFormat( 439 m_log.ErrorFormat(
474 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}", 440 "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}",
475 filename, id, e.Message, e.StackTrace); 441 filename, id, e.Message, e.StackTrace);
@@ -498,18 +464,9 @@ namespace OpenSim.Region.CoreModules.Asset
498 464
499 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0)) 465 if (((m_LogLevel >= 1)) && (m_HitRateDisplay != 0) && (m_Requests % m_HitRateDisplay == 0))
500 { 466 {
501 m_HitRateFile = (double)m_DiskHits / m_Requests * 100.0;
502
503 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit"); 467 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Get :: {0} :: {1}", id, asset == null ? "Miss" : "Hit");
504 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Hit Rate {0}% for {1} requests", m_HitRateFile.ToString("0.00"), m_Requests);
505 468
506 if (m_MemoryCacheEnabled) 469 GenerateCacheHitReport().ForEach(l => m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0}", l));
507 {
508 m_HitRateMemory = (double)m_MemoryHits / m_Requests * 100.0;
509 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Hit Rate {0}% for {1} requests", m_HitRateMemory.ToString("0.00"), m_Requests);
510 }
511
512 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} unnessesary requests due to requests for assets that are currently downloading.", m_RequestsForInprogress);
513 } 470 }
514 471
515 return asset; 472 return asset;
@@ -530,11 +487,6 @@ namespace OpenSim.Region.CoreModules.Asset
530 return Get(id); 487 return Get(id);
531 } 488 }
532 489
533 public AssetBase CheckCached(string id)
534 {
535 return Get(id);
536 }
537
538 public void Expire(string id) 490 public void Expire(string id)
539 { 491 {
540 if (m_LogLevel >= 2) 492 if (m_LogLevel >= 2)
@@ -819,7 +771,7 @@ namespace OpenSim.Region.CoreModules.Asset
819 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 771 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
820 772
821 HashSet<UUID> uniqueUuids = new HashSet<UUID>(); 773 HashSet<UUID> uniqueUuids = new HashSet<UUID>();
822 Dictionary<UUID, AssetType> assets = new Dictionary<UUID, AssetType>(); 774 Dictionary<UUID, sbyte> assets = new Dictionary<UUID, sbyte>();
823 775
824 foreach (Scene s in m_Scenes) 776 foreach (Scene s in m_Scenes)
825 { 777 {
@@ -842,7 +794,7 @@ namespace OpenSim.Region.CoreModules.Asset
842 else if (storeUncached) 794 else if (storeUncached)
843 { 795 {
844 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); 796 AssetBase cachedAsset = m_AssetService.Get(assetID.ToString());
845 if (cachedAsset == null && assets[assetID] != AssetType.Unknown) 797 if (cachedAsset == null && assets[assetID] != (sbyte)AssetType.Unknown)
846 m_log.DebugFormat( 798 m_log.DebugFormat(
847 "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets", 799 "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets",
848 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name); 800 assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name);
@@ -891,45 +843,77 @@ namespace OpenSim.Region.CoreModules.Asset
891 } 843 }
892 } 844 }
893 845
846 private List<string> GenerateCacheHitReport()
847 {
848 List<string> outputLines = new List<string>();
849
850 double fileHitRate = (double)m_DiskHits / m_Requests * 100.0;
851 outputLines.Add(
852 string.Format("File Hit Rate: {0}% for {1} requests", fileHitRate.ToString("0.00"), m_Requests));
853
854 if (m_MemoryCacheEnabled)
855 {
856 double memHitRate = (double)m_MemoryHits / m_Requests * 100.0;
857
858 outputLines.Add(
859 string.Format("Memory Hit Rate: {0}% for {1} requests", memHitRate.ToString("0.00"), m_Requests));
860 }
861
862 outputLines.Add(
863 string.Format(
864 "Unnecessary requests due to requests for assets that are currently downloading: {0}",
865 m_RequestsForInprogress));
866
867 return outputLines;
868 }
869
894 #region Console Commands 870 #region Console Commands
895 private void HandleConsoleCommand(string module, string[] cmdparams) 871 private void HandleConsoleCommand(string module, string[] cmdparams)
896 { 872 {
873 ICommandConsole con = MainConsole.Instance;
874
897 if (cmdparams.Length >= 2) 875 if (cmdparams.Length >= 2)
898 { 876 {
899 string cmd = cmdparams[1]; 877 string cmd = cmdparams[1];
878
900 switch (cmd) 879 switch (cmd)
901 { 880 {
902 case "status": 881 case "status":
903 if (m_MemoryCacheEnabled) 882 if (m_MemoryCacheEnabled)
904 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory Cache : {0} assets", m_MemoryCache.Count); 883 con.OutputFormat("Memory Cache: {0} assets", m_MemoryCache.Count);
905 else 884 else
906 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Memory cache disabled"); 885 con.OutputFormat("Memory cache disabled");
907 886
908 if (m_FileCacheEnabled) 887 if (m_FileCacheEnabled)
909 { 888 {
910 int fileCount = GetFileCacheCount(m_CacheDirectory); 889 int fileCount = GetFileCacheCount(m_CacheDirectory);
911 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File Cache : {0} assets", fileCount); 890 con.OutputFormat("File Cache: {0} assets", fileCount);
891 }
892 else
893 {
894 con.Output("File cache disabled");
895 }
896
897 GenerateCacheHitReport().ForEach(l => con.Output(l));
898
899 if (m_FileCacheEnabled)
900 {
901 con.Output("Deep scans have previously been performed on the following regions:");
912 902
913 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac")) 903 foreach (string s in Directory.GetFiles(m_CacheDirectory, "*.fac"))
914 { 904 {
915 m_log.Info("[FLOTSAM ASSET CACHE]: Deep scans have previously been performed on the following regions:");
916
917 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac",""); 905 string RegionID = s.Remove(0,s.IndexOf("_")).Replace(".fac","");
918 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s); 906 DateTime RegionDeepScanTMStamp = File.GetLastWriteTime(s);
919 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss")); 907 con.OutputFormat("Region: {0}, {1}", RegionID, RegionDeepScanTMStamp.ToString("MM/dd/yyyy hh:mm:ss"));
920 } 908 }
921 } 909 }
922 else
923 {
924 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache disabled");
925 }
926 910
927 break; 911 break;
928 912
929 case "clear": 913 case "clear":
930 if (cmdparams.Length < 2) 914 if (cmdparams.Length < 2)
931 { 915 {
932 m_log.Warn("[FLOTSAM ASSET CACHE]: Usage is fcache clear [file] [memory]"); 916 con.Output("Usage is fcache clear [file] [memory]");
933 break; 917 break;
934 } 918 }
935 919
@@ -953,11 +937,11 @@ namespace OpenSim.Region.CoreModules.Asset
953 if (m_MemoryCacheEnabled) 937 if (m_MemoryCacheEnabled)
954 { 938 {
955 m_MemoryCache.Clear(); 939 m_MemoryCache.Clear();
956 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache cleared."); 940 con.Output("Memory cache cleared.");
957 } 941 }
958 else 942 else
959 { 943 {
960 m_log.Info("[FLOTSAM ASSET CACHE]: Memory cache not enabled."); 944 con.Output("Memory cache not enabled.");
961 } 945 }
962 } 946 }
963 947
@@ -966,24 +950,22 @@ namespace OpenSim.Region.CoreModules.Asset
966 if (m_FileCacheEnabled) 950 if (m_FileCacheEnabled)
967 { 951 {
968 ClearFileCache(); 952 ClearFileCache();
969 m_log.Info("[FLOTSAM ASSET CACHE]: File cache cleared."); 953 con.Output("File cache cleared.");
970 } 954 }
971 else 955 else
972 { 956 {
973 m_log.Info("[FLOTSAM ASSET CACHE]: File cache not enabled."); 957 con.Output("File cache not enabled.");
974 } 958 }
975 } 959 }
976 960
977 break; 961 break;
978 962
979 case "assets": 963 case "assets":
980 m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes."); 964 con.Output("Ensuring assets are cached for all scenes.");
981 965
982 Util.FireAndForget(delegate { 966 Util.FireAndForget(delegate {
983 int assetReferenceTotal = TouchAllSceneAssets(true); 967 int assetReferenceTotal = TouchAllSceneAssets(true);
984 m_log.InfoFormat( 968 con.OutputFormat("Completed check with {0} assets.", assetReferenceTotal);
985 "[FLOTSAM ASSET CACHE]: Completed check with {0} assets.",
986 assetReferenceTotal);
987 }); 969 });
988 970
989 break; 971 break;
@@ -991,7 +973,7 @@ namespace OpenSim.Region.CoreModules.Asset
991 case "expire": 973 case "expire":
992 if (cmdparams.Length < 3) 974 if (cmdparams.Length < 3)
993 { 975 {
994 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Invalid parameters for Expire, please specify a valid date & time", cmd); 976 con.OutputFormat("Invalid parameters for Expire, please specify a valid date & time", cmd);
995 break; 977 break;
996 } 978 }
997 979
@@ -1009,28 +991,27 @@ namespace OpenSim.Region.CoreModules.Asset
1009 991
1010 if (!DateTime.TryParse(s_expirationDate, out expirationDate)) 992 if (!DateTime.TryParse(s_expirationDate, out expirationDate))
1011 { 993 {
1012 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0} is not a valid date & time", cmd); 994 con.OutputFormat("{0} is not a valid date & time", cmd);
1013 break; 995 break;
1014 } 996 }
1015 997
1016 if (m_FileCacheEnabled) 998 if (m_FileCacheEnabled)
1017 CleanExpiredFiles(m_CacheDirectory, expirationDate); 999 CleanExpiredFiles(m_CacheDirectory, expirationDate);
1018 else 1000 else
1019 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: File cache not active, not clearing."); 1001 con.OutputFormat("File cache not active, not clearing.");
1020 1002
1021 break; 1003 break;
1022 default: 1004 default:
1023 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Unknown command {0}", cmd); 1005 con.OutputFormat("Unknown command {0}", cmd);
1024 break; 1006 break;
1025 } 1007 }
1026 } 1008 }
1027 else if (cmdparams.Length == 1) 1009 else if (cmdparams.Length == 1)
1028 { 1010 {
1029 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache status - Display cache status"); 1011 con.Output("fcache assets - Attempt a deep cache of all assets in all scenes");
1030 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearmem - Remove all assets cached in memory"); 1012 con.Output("fcache expire <datetime> - Purge assets older then the specified date & time");
1031 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache clearfile - Remove all assets cached on disk"); 1013 con.Output("fcache clear [file] [memory] - Remove cached assets");
1032 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache cachescenes - Attempt a deep cache of all assets in all scenes"); 1014 con.Output("fcache status - Display cache status");
1033 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: fcache <datetime> - Purge assets older then the specified date & time");
1034 } 1015 }
1035 } 1016 }
1036 1017
@@ -1050,11 +1031,6 @@ namespace OpenSim.Region.CoreModules.Asset
1050 return asset.Data; 1031 return asset.Data;
1051 } 1032 }
1052 1033
1053 public bool CheckData(string id)
1054 {
1055 return Check(id); ;
1056 }
1057
1058 public bool Get(string id, object sender, AssetRetrieved handler) 1034 public bool Get(string id, object sender, AssetRetrieved handler)
1059 { 1035 {
1060 AssetBase asset = Get(id); 1036 AssetBase asset = Get(id);
diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
index ce9b546..5f76ac2 100644
--- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs
@@ -117,7 +117,7 @@ namespace OpenSim.Region.CoreModules.Asset
117 117
118 public bool Check(string id) 118 public bool Check(string id)
119 { 119 {
120 return false; 120 return m_Cache.Contains(id);
121 } 121 }
122 122
123 public void Cache(AssetBase asset) 123 public void Cache(AssetBase asset)
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 6495f3f..d47ca4b 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.IO; 31using System.IO;
32using System.Threading;
32using System.Xml; 33using System.Xml;
33using log4net; 34using log4net;
34using Mono.Addins; 35using Mono.Addins;
@@ -51,6 +52,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 53
53 public int DebugLevel { get; set; } 54 public int DebugLevel { get; set; }
55
56 /// <summary>
57 /// Period to sleep per 100 prims in order to avoid CPU spikes when an avatar with many attachments logs in/changes
58 /// outfit or many avatars with a medium levels of attachments login/change outfit simultaneously.
59 /// </summary>
60 /// <remarks>
61 /// A value of 0 will apply no pause. The pause is specified in milliseconds.
62 /// </remarks>
63 public int ThrottlePer100PrimsRezzed { get; set; }
54 64
55 private Scene m_scene; 65 private Scene m_scene;
56 private IInventoryAccessModule m_invAccessModule; 66 private IInventoryAccessModule m_invAccessModule;
@@ -67,18 +77,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
67 { 77 {
68 IConfig config = source.Configs["Attachments"]; 78 IConfig config = source.Configs["Attachments"];
69 if (config != null) 79 if (config != null)
80 {
70 Enabled = config.GetBoolean("Enabled", true); 81 Enabled = config.GetBoolean("Enabled", true);
82
83 ThrottlePer100PrimsRezzed = config.GetInt("ThrottlePer100PrimsRezzed", 0);
84 }
71 else 85 else
86 {
72 Enabled = true; 87 Enabled = true;
88 }
73 } 89 }
74 90
75 public void AddRegion(Scene scene) 91 public void AddRegion(Scene scene)
76 { 92 {
77 m_scene = scene; 93 m_scene = scene;
78 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
79
80 if (Enabled) 94 if (Enabled)
81 { 95 {
96 // Only register module with scene if it is enabled. All callers check for a null attachments module.
97 // Ideally, there should be a null attachments module for when this core attachments module has been
98 // disabled. Registering only when enabled allows for other attachments module implementations.
99 m_scene.RegisterModuleInterface<IAttachmentsModule>(this);
82 m_scene.EventManager.OnNewClient += SubscribeToClientEvents; 100 m_scene.EventManager.OnNewClient += SubscribeToClientEvents;
83 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true); 101 m_scene.EventManager.OnStartScript += (localID, itemID) => HandleScriptStateChange(localID, true);
84 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false); 102 m_scene.EventManager.OnStopScript += (localID, itemID) => HandleScriptStateChange(localID, false);
@@ -86,24 +104,43 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
86 MainConsole.Instance.Commands.AddCommand( 104 MainConsole.Instance.Commands.AddCommand(
87 "Debug", 105 "Debug",
88 false, 106 false,
89 "debug attachments", 107 "debug attachments log",
90 "debug attachments [0|1]", 108 "debug attachments log [0|1]",
91 "Turn on attachments debugging\n" 109 "Turn on attachments debug logging",
92 + " <= 0 - turns off debugging\n" 110 " <= 0 - turns off debug logging\n"
93 + " >= 1 - turns on attachment message logging\n", 111 + " >= 1 - turns on attachment message debug logging",
94 HandleDebugAttachments); 112 HandleDebugAttachmentsLog);
113
114 MainConsole.Instance.Commands.AddCommand(
115 "Debug",
116 false,
117 "debug attachments throttle",
118 "debug attachments throttle <ms>",
119 "Turn on attachments throttling.",
120 "This requires a millisecond value. " +
121 " == 0 - disable throttling.\n"
122 + " > 0 - sleeps for this number of milliseconds per 100 prims rezzed.",
123 HandleDebugAttachmentsThrottle);
124
125 MainConsole.Instance.Commands.AddCommand(
126 "Debug",
127 false,
128 "debug attachments status",
129 "debug attachments status",
130 "Show current attachments debug status",
131 HandleDebugAttachmentsStatus);
95 } 132 }
96 133
97 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI 134 // TODO: Should probably be subscribing to CloseClient too, but this doesn't yet give us IClientAPI
98 } 135 }
99 136
100 private void HandleDebugAttachments(string module, string[] args) 137 private void HandleDebugAttachmentsLog(string module, string[] args)
101 { 138 {
102 int debugLevel; 139 int debugLevel;
103 140
104 if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel))) 141 if (!(args.Length == 4 && int.TryParse(args[3], out debugLevel)))
105 { 142 {
106 MainConsole.Instance.OutputFormat("Usage: debug attachments [0|1]"); 143 MainConsole.Instance.OutputFormat("Usage: debug attachments log [0|1]");
107 } 144 }
108 else 145 else
109 { 146 {
@@ -113,6 +150,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
113 } 150 }
114 } 151 }
115 152
153 private void HandleDebugAttachmentsThrottle(string module, string[] args)
154 {
155 int ms;
156
157 if (args.Length == 4 && int.TryParse(args[3], out ms))
158 {
159 ThrottlePer100PrimsRezzed = ms;
160 MainConsole.Instance.OutputFormat(
161 "Attachments rez throttle per 100 prims is now {0} in {1}", ThrottlePer100PrimsRezzed, m_scene.Name);
162
163 return;
164 }
165
166 MainConsole.Instance.OutputFormat("Usage: debug attachments throttle <ms>");
167 }
168
169 private void HandleDebugAttachmentsStatus(string module, string[] args)
170 {
171 MainConsole.Instance.OutputFormat("Settings for {0}", m_scene.Name);
172 MainConsole.Instance.OutputFormat("Debug logging level: {0}", DebugLevel);
173 MainConsole.Instance.OutputFormat("Throttle per 100 prims: {0}ms", ThrottlePer100PrimsRezzed);
174 }
175
116 /// <summary> 176 /// <summary>
117 /// Listen for client triggered running state changes so that we can persist the script's object if necessary. 177 /// Listen for client triggered running state changes so that we can persist the script's object if necessary.
118 /// </summary> 178 /// </summary>
@@ -273,7 +333,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
273 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments(); 333 List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
274 foreach (AvatarAttachment attach in attachments) 334 foreach (AvatarAttachment attach in attachments)
275 { 335 {
276 uint p = (uint)attach.AttachPoint; 336 uint attachmentPt = (uint)attach.AttachPoint;
277 337
278// m_log.DebugFormat( 338// m_log.DebugFormat(
279// "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}", 339// "[ATTACHMENTS MODULE]: Doing initial rez of attachment with itemID {0}, assetID {1}, point {2} for {3} in {4}",
@@ -302,13 +362,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
302 // If we're an NPC then skip all the item checks and manipulations since we don't have an 362 // If we're an NPC then skip all the item checks and manipulations since we don't have an
303 // inventory right now. 363 // inventory right now.
304 RezSingleAttachmentFromInventoryInternal( 364 RezSingleAttachmentFromInventoryInternal(
305 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, p, true, d); 365 sp, sp.PresenceType == PresenceType.Npc ? UUID.Zero : attach.ItemID, attach.AssetID, attachmentPt, true, d);
306 } 366 }
307 catch (Exception e) 367 catch (Exception e)
308 { 368 {
309 UUID agentId = (sp.ControllingClient == null) ? (UUID)null : sp.ControllingClient.AgentId; 369 UUID agentId = (sp.ControllingClient == null) ? default(UUID) : sp.ControllingClient.AgentId;
310 m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}", 370 m_log.ErrorFormat("[ATTACHMENTS MODULE]: Unable to rez attachment with itemID {0}, assetID {1}, point {2} for {3}: {4}\n{5}",
311 attach.ItemID, attach.AssetID, p, agentId, e.Message, e.StackTrace); 371 attach.ItemID, attach.AssetID, attachmentPt, agentId, e.Message, e.StackTrace);
312 } 372 }
313 } 373 }
314 } 374 }
@@ -422,13 +482,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
422 attachPos = Vector3.Zero; 482 attachPos = Vector3.Zero;
423 } 483 }
424 484
425 // AttachmentPt 0 (default) means the client chose to 'wear' the attachment. 485 // if the attachment point is the same as previous, make sure we get the saved
486 // position info.
487 if (attachmentPt != 0 && attachmentPt == group.RootPart.Shape.LastAttachPoint)
488 {
489 attachPos = group.RootPart.AttachedPos;
490 }
491
492 // AttachmentPt 0 means the client chose to 'wear' the attachment.
426 if (attachmentPt == (uint)AttachmentPoint.Default) 493 if (attachmentPt == (uint)AttachmentPoint.Default)
427 { 494 {
428 // Check object for stored attachment point 495 // Check object for stored attachment point
429 attachmentPt = group.AttachmentPoint; 496 attachmentPt = group.AttachmentPoint;
430 } 497 }
431 498
499 // if we didn't find an attach point, look for where it was last attached
500 if (attachmentPt == 0)
501 {
502 attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint;
503 attachPos = group.RootPart.AttachedPos;
504 group.HasGroupChanged = true;
505 }
506
432 // if we still didn't find a suitable attachment point....... 507 // if we still didn't find a suitable attachment point.......
433 if (attachmentPt == 0) 508 if (attachmentPt == 0)
434 { 509 {
@@ -610,6 +685,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
610 if (changed && m_scene.AvatarFactory != null) 685 if (changed && m_scene.AvatarFactory != null)
611 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 686 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
612 687
688 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
689
613 sp.RemoveAttachment(so); 690 sp.RemoveAttachment(so);
614 so.FromItemID = UUID.Zero; 691 so.FromItemID = UUID.Zero;
615 692
@@ -841,7 +918,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
841 m_scene.ForEachClient( 918 m_scene.ForEachClient(
842 client => 919 client =>
843 { if (client.AgentId != so.AttachedAvatar) 920 { if (client.AgentId != so.AttachedAvatar)
844 client.SendKillObject(m_scene.RegionInfo.RegionHandle, new List<uint>() { so.LocalId }); 921 client.SendKillObject(new List<uint>() { so.LocalId });
845 }); 922 });
846 } 923 }
847 924
@@ -982,8 +1059,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
982 1059
983 if (DebugLevel > 0) 1060 if (DebugLevel > 0)
984 m_log.DebugFormat( 1061 m_log.DebugFormat(
985 "[ATTACHMENTS MODULE]: Rezzed single object {0} for attachment to {1} on point {2} in {3}", 1062 "[ATTACHMENTS MODULE]: Rezzed single object {0} with {1} prims for attachment to {2} on point {3} in {4}",
986 objatt.Name, sp.Name, attachmentPt, m_scene.Name); 1063 objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name);
987 1064
988 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. 1065 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
989 objatt.HasGroupChanged = false; 1066 objatt.HasGroupChanged = false;
@@ -1020,7 +1097,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1020 } 1097 }
1021 1098
1022 if (tainted) 1099 if (tainted)
1023 objatt.HasGroupChanged = true; 1100 objatt.HasGroupChanged = true;
1101
1102 if (ThrottlePer100PrimsRezzed > 0)
1103 {
1104 int throttleMs = (int)Math.Round((float)objatt.PrimCount / 100 * ThrottlePer100PrimsRezzed);
1105
1106 if (DebugLevel > 0)
1107 m_log.DebugFormat(
1108 "[ATTACHMENTS MODULE]: Throttling by {0}ms after rez of {1} with {2} prims for attachment to {3} on point {4} in {5}",
1109 throttleMs, objatt.Name, objatt.PrimCount, sp.Name, attachmentPt, m_scene.Name);
1110
1111 Thread.Sleep(throttleMs);
1112 }
1024 1113
1025 return objatt; 1114 return objatt;
1026 } 1115 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 1a38619..f023e77 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -38,6 +38,8 @@ using NUnit.Framework;
38using OpenMetaverse; 38using OpenMetaverse;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Communications; 40using OpenSim.Framework.Communications;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Region.CoreModules.Avatar.Attachments; 43using OpenSim.Region.CoreModules.Avatar.Attachments;
42using OpenSim.Region.CoreModules.Framework; 44using OpenSim.Region.CoreModules.Framework;
43using OpenSim.Region.CoreModules.Framework.EntityTransfer; 45using OpenSim.Region.CoreModules.Framework.EntityTransfer;
@@ -717,7 +719,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
717 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; 719 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
718 720
719 m_numberOfAttachEventsFired = 0; 721 m_numberOfAttachEventsFired = 0;
720 scene.IncomingCloseAgent(presence.UUID, false); 722 scene.CloseAgent(presence.UUID, false);
721 723
722 // Check that we can't retrieve this attachment from the scene. 724 // Check that we can't retrieve this attachment from the scene.
723 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); 725 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);
@@ -797,11 +799,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
797 } 799 }
798 800
799 [Test] 801 [Test]
800 public void TestSameSimulatorNeighbouringRegionsTeleport() 802 public void TestSameSimulatorNeighbouringRegionsTeleportV1()
801 { 803 {
802 TestHelpers.InMethod(); 804 TestHelpers.InMethod();
803// TestHelpers.EnableLogging(); 805// TestHelpers.EnableLogging();
804 806
807 BaseHttpServer httpServer = new BaseHttpServer(99999);
808 MainServer.AddHttpServer(httpServer);
809 MainServer.Instance = httpServer;
810
805 AttachmentsModule attModA = new AttachmentsModule(); 811 AttachmentsModule attModA = new AttachmentsModule();
806 AttachmentsModule attModB = new AttachmentsModule(); 812 AttachmentsModule attModB = new AttachmentsModule();
807 EntityTransferModule etmA = new EntityTransferModule(); 813 EntityTransferModule etmA = new EntityTransferModule();
@@ -830,14 +836,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
830 SceneHelpers.SetupSceneModules( 836 SceneHelpers.SetupSceneModules(
831 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule()); 837 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
832 838
839 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour
840 lscm.ServiceVersion = "SIMULATION/0.1";
841
833 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1); 842 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
834 843
835 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); 844 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
836 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); 845 TestClient tc = new TestClient(acd, sceneA);
837 List<TestClient> destinationTestClients = new List<TestClient>(); 846 List<TestClient> destinationTestClients = new List<TestClient>();
838 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); 847 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
839 848
840 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); 849 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
841 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32); 850 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
842 851
843 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20); 852 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
@@ -895,5 +904,115 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
895 // Check events 904 // Check events
896 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); 905 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
897 } 906 }
907
908 [Test]
909 public void TestSameSimulatorNeighbouringRegionsTeleportV2()
910 {
911 TestHelpers.InMethod();
912// TestHelpers.EnableLogging();
913
914 BaseHttpServer httpServer = new BaseHttpServer(99999);
915 MainServer.AddHttpServer(httpServer);
916 MainServer.Instance = httpServer;
917
918 AttachmentsModule attModA = new AttachmentsModule();
919 AttachmentsModule attModB = new AttachmentsModule();
920 EntityTransferModule etmA = new EntityTransferModule();
921 EntityTransferModule etmB = new EntityTransferModule();
922 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
923
924 IConfigSource config = new IniConfigSource();
925 IConfig modulesConfig = config.AddConfig("Modules");
926 modulesConfig.Set("EntityTransferModule", etmA.Name);
927 modulesConfig.Set("SimulationServices", lscm.Name);
928
929 modulesConfig.Set("InventoryAccessModule", "BasicInventoryAccessModule");
930
931 SceneHelpers sh = new SceneHelpers();
932 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
933 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000);
934
935 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
936 SceneHelpers.SetupSceneModules(
937 sceneA, config, new CapabilitiesModule(), etmA, attModA, new BasicInventoryAccessModule());
938 SceneHelpers.SetupSceneModules(
939 sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
940
941 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
942
943 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
944 TestClient tc = new TestClient(acd, sceneA);
945 List<TestClient> destinationTestClients = new List<TestClient>();
946 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
947
948 ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
949 beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
950
951 Assert.That(destinationTestClients.Count, Is.EqualTo(1));
952 Assert.That(destinationTestClients[0], Is.Not.Null);
953
954 InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
955
956 sceneA.AttachmentsModule.RezSingleAttachmentFromInventory(
957 beforeTeleportSp, attItem.ID, (uint)AttachmentPoint.Chest);
958
959 Vector3 teleportPosition = new Vector3(10, 11, 12);
960 Vector3 teleportLookAt = new Vector3(20, 21, 22);
961
962 // Here, we need to make clientA's receipt of SendRegionTeleport trigger clientB's CompleteMovement(). This
963 // is to operate the teleport V2 mechanism where the EntityTransferModule will first request the client to
964 // CompleteMovement to the region and then call UpdateAgent to the destination region to confirm the receipt
965 // Both these operations will occur on different threads and will wait for each other.
966 // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1
967 // test protocol, where we are trying to avoid unpredictable async operations in regression tests.
968 tc.OnTestClientSendRegionTeleport
969 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL)
970 => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null);
971
972 m_numberOfAttachEventsFired = 0;
973 sceneA.RequestTeleportLocation(
974 beforeTeleportSp.ControllingClient,
975 sceneB.RegionInfo.RegionHandle,
976 teleportPosition,
977 teleportLookAt,
978 (uint)TeleportFlags.ViaLocation);
979
980 // Check attachments have made it into sceneB
981 ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID);
982
983 // This is appearance data, as opposed to actually rezzed attachments
984 List<AvatarAttachment> sceneBAttachments = afterTeleportSceneBSp.Appearance.GetAttachments();
985 Assert.That(sceneBAttachments.Count, Is.EqualTo(1));
986 Assert.That(sceneBAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest));
987 Assert.That(sceneBAttachments[0].ItemID, Is.EqualTo(attItem.ID));
988 Assert.That(sceneBAttachments[0].AssetID, Is.EqualTo(attItem.AssetID));
989 Assert.That(afterTeleportSceneBSp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
990
991 // This is the actual attachment
992 List<SceneObjectGroup> actualSceneBAttachments = afterTeleportSceneBSp.GetAttachments();
993 Assert.That(actualSceneBAttachments.Count, Is.EqualTo(1));
994 SceneObjectGroup actualSceneBAtt = actualSceneBAttachments[0];
995 Assert.That(actualSceneBAtt.Name, Is.EqualTo(attItem.Name));
996 Assert.That(actualSceneBAtt.AttachmentPoint, Is.EqualTo((uint)AttachmentPoint.Chest));
997
998 Assert.That(sceneB.GetSceneObjectGroups().Count, Is.EqualTo(1));
999
1000 // Check attachments have been removed from sceneA
1001 ScenePresence afterTeleportSceneASp = sceneA.GetScenePresence(ua1.PrincipalID);
1002
1003 // Since this is appearance data, it is still present on the child avatar!
1004 List<AvatarAttachment> sceneAAttachments = afterTeleportSceneASp.Appearance.GetAttachments();
1005 Assert.That(sceneAAttachments.Count, Is.EqualTo(1));
1006 Assert.That(afterTeleportSceneASp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
1007
1008 // This is the actual attachment, which should no longer exist
1009 List<SceneObjectGroup> actualSceneAAttachments = afterTeleportSceneASp.GetAttachments();
1010 Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0));
1011
1012 Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0));
1013
1014 // Check events
1015 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
1016 }
898 } 1017 }
899} 1018}
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index bc79944..09cc998 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -55,6 +55,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
55 55
56 private int m_savetime = 5; // seconds to wait before saving changed appearance 56 private int m_savetime = 5; // seconds to wait before saving changed appearance
57 private int m_sendtime = 2; // seconds to wait before sending changed appearance 57 private int m_sendtime = 2; // seconds to wait before sending changed appearance
58 private bool m_reusetextures = false;
58 59
59 private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates 60 private int m_checkTime = 500; // milliseconds to wait between checks for appearance updates
60 private System.Timers.Timer m_updateTimer = new System.Timers.Timer(); 61 private System.Timers.Timer m_updateTimer = new System.Timers.Timer();
@@ -73,6 +74,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
73 { 74 {
74 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime))); 75 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
75 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime))); 76 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
77 m_reusetextures = appearanceConfig.GetBoolean("ReuseTextures",m_reusetextures);
78
76 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime); 79 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
77 } 80 }
78 81
@@ -131,6 +134,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
131 client.OnRequestWearables += Client_OnRequestWearables; 134 client.OnRequestWearables += Client_OnRequestWearables;
132 client.OnSetAppearance += Client_OnSetAppearance; 135 client.OnSetAppearance += Client_OnSetAppearance;
133 client.OnAvatarNowWearing += Client_OnAvatarNowWearing; 136 client.OnAvatarNowWearing += Client_OnAvatarNowWearing;
137 client.OnCachedTextureRequest += Client_OnCachedTextureRequest;
134 } 138 }
135 139
136 #endregion 140 #endregion
@@ -1068,6 +1072,61 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
1068 QueueAppearanceSave(client.AgentId); 1072 QueueAppearanceSave(client.AgentId);
1069 } 1073 }
1070 } 1074 }
1075
1076 /// <summary>
1077 /// Respond to the cached textures request from the client
1078 /// </summary>
1079 /// <param name="client"></param>
1080 /// <param name="serial"></param>
1081 /// <param name="cachedTextureRequest"></param>
1082 private void Client_OnCachedTextureRequest(IClientAPI client, int serial, List<CachedTextureRequestArg> cachedTextureRequest)
1083 {
1084 // m_log.WarnFormat("[AVFACTORY]: Client_OnCachedTextureRequest called for {0} ({1})", client.Name, client.AgentId);
1085 ScenePresence sp = m_scene.GetScenePresence(client.AgentId);
1086
1087 List<CachedTextureResponseArg> cachedTextureResponse = new List<CachedTextureResponseArg>();
1088 foreach (CachedTextureRequestArg request in cachedTextureRequest)
1089 {
1090 UUID texture = UUID.Zero;
1091 int index = request.BakedTextureIndex;
1092
1093 if (m_reusetextures)
1094 {
1095 // this is the most insanely dumb way to do this... however it seems to
1096 // actually work. if the appearance has been reset because wearables have
1097 // changed then the texture entries are zero'd out until the bakes are
1098 // uploaded. on login, if the textures exist in the cache (eg if you logged
1099 // into the simulator recently, then the appearance will pull those and send
1100 // them back in the packet and you won't have to rebake. if the textures aren't
1101 // in the cache then the intial makeroot() call in scenepresence will zero
1102 // them out.
1103 //
1104 // a better solution (though how much better is an open question) is to
1105 // store the hashes in the appearance and compare them. Thats's coming.
1106
1107 Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index];
1108 if (face != null)
1109 texture = face.TextureID;
1110
1111 // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index);
1112 }
1113
1114 CachedTextureResponseArg response = new CachedTextureResponseArg();
1115 response.BakedTextureIndex = index;
1116 response.BakedTextureID = texture;
1117 response.HostName = null;
1118
1119 cachedTextureResponse.Add(response);
1120 }
1121
1122 // m_log.WarnFormat("[AVFACTORY]: serial is {0}",serial);
1123 // The serial number appears to be used to match requests and responses
1124 // in the texture transaction. We just send back the serial number
1125 // that was provided in the request. The viewer bumps this for us.
1126 client.SendCachedTextureResponse(sp, serial, cachedTextureResponse);
1127 }
1128
1129
1071 #endregion 1130 #endregion
1072 1131
1073 public void WriteBakedTexturesReport(IScenePresence sp, ReportOutputAction outputAction) 1132 public void WriteBakedTexturesReport(IScenePresence sp, ReportOutputAction outputAction)
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 174642d..5cbfec6 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -32,6 +32,7 @@ using log4net;
32using Nini.Config; 32using Nini.Config;
33using Mono.Addins; 33using Mono.Addins;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
@@ -103,6 +104,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
103 104
104 public virtual void RegionLoaded(Scene scene) 105 public virtual void RegionLoaded(Scene scene)
105 { 106 {
107 if (!m_enabled)
108 return;
109
110 ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
111
112 if (featuresModule != null)
113 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
114
106 } 115 }
107 116
108 public virtual void RemoveRegion(Scene scene) 117 public virtual void RemoveRegion(Scene scene)
@@ -372,21 +381,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
372 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, 381 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type,
373 string message, ChatSourceType src, bool ignoreDistance) 382 string message, ChatSourceType src, bool ignoreDistance)
374 { 383 {
375 // don't send chat to child agents 384 if (presence.LifecycleState != ScenePresenceState.Running)
376 if (presence.IsChildAgent) return false; 385 return false;
377
378 Vector3 fromRegionPos = fromPos + regionPos;
379 Vector3 toRegionPos = presence.AbsolutePosition +
380 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
381 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
382 386
383 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos); 387 if (!ignoreDistance)
384
385 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
386 type == ChatTypeEnum.Say && dis > m_saydistance ||
387 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
388 { 388 {
389 return false; 389 Vector3 fromRegionPos = fromPos + regionPos;
390 Vector3 toRegionPos = presence.AbsolutePosition +
391 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
392 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
393
394 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
395
396 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
397 type == ChatTypeEnum.Say && dis > m_saydistance ||
398 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
399 {
400 return false;
401 }
390 } 402 }
391 403
392 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView 404 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
@@ -426,5 +438,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
426 Timers.Remove(target); 438 Timers.Remove(target);
427 Timer.Dispose(); 439 Timer.Dispose();
428 } 440 }
441 #region SimulatorFeaturesRequest
442
443 static OSDInteger m_SayRange, m_WhisperRange, m_ShoutRange;
444
445 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
446 {
447 OSD extras = new OSDMap();
448 if (features.ContainsKey("OpenSimExtras"))
449 extras = features["OpenSimExtras"];
450 else
451 features["OpenSimExtras"] = extras;
452
453 if (m_SayRange == null)
454 {
455 // Do this only once
456 m_SayRange = new OSDInteger(m_saydistance);
457 m_WhisperRange = new OSDInteger(m_whisperdistance);
458 m_ShoutRange = new OSDInteger(m_shoutdistance);
459 }
460
461 ((OSDMap)extras)["say-range"] = m_SayRange;
462 ((OSDMap)extras)["whisper-range"] = m_WhisperRange;
463 ((OSDMap)extras)["shout-range"] = m_ShoutRange;
464
465 }
466
467 #endregion
429 } 468 }
430} 469}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 8056030..b693f2d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -371,7 +371,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
371 foreach (string fid in outstanding) 371 foreach (string fid in outstanding)
372 { 372 {
373 UUID fromAgentID; 373 UUID fromAgentID;
374 string firstname = "Unknown", lastname = "User"; 374 string firstname = "Unknown", lastname = "UserFMSFOIN";
375 if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname)) 375 if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname))
376 { 376 {
377 m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid); 377 m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid);
@@ -397,7 +397,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
397 397
398 protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) 398 protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
399 { 399 {
400 first = "Unknown"; last = "User"; 400 first = "Unknown"; last = "UserFMGAI";
401 if (!UUID.TryParse(fid, out agentID)) 401 if (!UUID.TryParse(fid, out agentID))
402 return false; 402 return false;
403 403
@@ -498,6 +498,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
498 498
499 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online) 499 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
500 { 500 {
501 //m_log.DebugFormat("[FRIENDS]: Entering StatusNotify for {0}", userID);
502
501 List<string> friendStringIds = friendList.ConvertAll<string>(friend => friend.Friend); 503 List<string> friendStringIds = friendList.ConvertAll<string>(friend => friend.Friend);
502 List<string> remoteFriendStringIds = new List<string>(); 504 List<string> remoteFriendStringIds = new List<string>();
503 foreach (string friendStringId in friendStringIds) 505 foreach (string friendStringId in friendStringIds)
@@ -523,12 +525,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
523 foreach (PresenceInfo friendSession in friendSessions) 525 foreach (PresenceInfo friendSession in friendSessions)
524 { 526 {
525 // let's guard against sessions-gone-bad 527 // let's guard against sessions-gone-bad
526 if (friendSession.RegionID != UUID.Zero) 528 if (friendSession != null && friendSession.RegionID != UUID.Zero)
527 { 529 {
530 //m_log.DebugFormat("[FRIENDS]: Get region {0}", friendSession.RegionID);
528 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); 531 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
529 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); 532 if (region != null)
530 m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online); 533 {
534 m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online);
535 }
531 } 536 }
537 //else
538 // m_log.DebugFormat("[FRIENDS]: friend session is null or the region is UUID.Zero");
532 } 539 }
533 } 540 }
534 541
@@ -685,7 +692,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
685 // 692 //
686 693
687 // Try local 694 // Try local
688 if (LocalFriendshipTerminated(exfriendID)) 695 if (LocalFriendshipTerminated(client.AgentId, exfriendID))
689 return; 696 return;
690 697
691 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() }); 698 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() });
@@ -827,13 +834,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
827 return false; 834 return false;
828 } 835 }
829 836
830 public bool LocalFriendshipTerminated(UUID exfriendID) 837 public bool LocalFriendshipTerminated(UUID userID, UUID exfriendID)
831 { 838 {
832 IClientAPI friendClient = LocateClientObject(exfriendID); 839 IClientAPI friendClient = LocateClientObject(exfriendID);
833 if (friendClient != null) 840 if (friendClient != null)
834 { 841 {
835 // the friend in this sim as root agent 842 // the friend in this sim as root agent
836 friendClient.SendTerminateFriend(exfriendID); 843 friendClient.SendTerminateFriend(userID);
837 // update local cache 844 // update local cache
838 RecacheFriends(friendClient); 845 RecacheFriends(friendClient);
839 // we're done 846 // we're done
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
index 637beef..ff87ece 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs
@@ -42,19 +42,27 @@ using log4net;
42 42
43namespace OpenSim.Region.CoreModules.Avatar.Friends 43namespace OpenSim.Region.CoreModules.Avatar.Friends
44{ 44{
45 public class FriendsRequestHandler : BaseStreamHandler 45 public class FriendsRequestHandler : BaseStreamHandlerBasicDOSProtector
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private FriendsModule m_FriendsModule; 49 private FriendsModule m_FriendsModule;
50 50
51 public FriendsRequestHandler(FriendsModule fmodule) 51 public FriendsRequestHandler(FriendsModule fmodule)
52 : base("POST", "/friends") 52 : base("POST", "/friends", new BasicDosProtectorOptions()
53 {
54 AllowXForwardedFor = true,
55 ForgetTimeSpan = TimeSpan.FromMinutes(2),
56 MaxRequestsInTimeframe = 20,
57 ReportingName = "FRIENDSDOSPROTECTOR",
58 RequestTimeSpan = TimeSpan.FromSeconds(5),
59 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod
60 })
53 { 61 {
54 m_FriendsModule = fmodule; 62 m_FriendsModule = fmodule;
55 } 63 }
56 64
57 public override byte[] Handle( 65 protected override byte[] ProcessRequest(
58 string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 66 string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 { 67 {
60 StreamReader sr = new StreamReader(requestData); 68 StreamReader sr = new StreamReader(requestData);
@@ -193,7 +201,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
193 if (!UUID.TryParse(request["ToID"].ToString(), out toID)) 201 if (!UUID.TryParse(request["ToID"].ToString(), out toID))
194 return FailureResult(); 202 return FailureResult();
195 203
196 if (m_FriendsModule.LocalFriendshipTerminated(toID)) 204 if (m_FriendsModule.LocalFriendshipTerminated(fromID, toID))
197 return SuccessResult(); 205 return SuccessResult();
198 206
199 return FailureResult(); 207 return FailureResult();
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index bf5c0bb..d00945e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -183,6 +183,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
183 if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp)) 183 if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp))
184 { 184 {
185 IUserManagement uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>(); 185 IUserManagement uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
186 m_log.DebugFormat("[HGFRIENDS MODULE]: caching {0}", finfo.Friend);
186 uMan.AddUser(id, url + ";" + first + " " + last); 187 uMan.AddUser(id, url + ";" + first + " " + last);
187 } 188 }
188 } 189 }
@@ -251,7 +252,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
251 252
252 protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online) 253 protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
253 { 254 {
254// m_log.DebugFormat("[HGFRIENDS MODULE]: Entering StatusNotify for {0}", userID); 255 //m_log.DebugFormat("[HGFRIENDS MODULE]: Entering StatusNotify for {0}", userID);
255 256
256 // First, let's divide the friends on a per-domain basis 257 // First, let's divide the friends on a per-domain basis
257 Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>(); 258 Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>();
@@ -293,7 +294,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
293 294
294 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) 295 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
295 { 296 {
296 first = "Unknown"; last = "User"; 297 first = "Unknown"; last = "UserHGGAI";
297 if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last)) 298 if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last))
298 return true; 299 return true;
299 300
@@ -349,7 +350,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
349 350
350 public override FriendInfo[] GetFriendsFromService(IClientAPI client) 351 public override FriendInfo[] GetFriendsFromService(IClientAPI client)
351 { 352 {
352// m_log.DebugFormat("[HGFRIENDS MODULE]: Entering GetFriendsFromService for {0}", client.Name); 353 // m_log.DebugFormat("[HGFRIENDS MODULE]: Entering GetFriendsFromService for {0}", client.Name);
353 Boolean agentIsLocal = true; 354 Boolean agentIsLocal = true;
354 if (UserManagementModule != null) 355 if (UserManagementModule != null)
355 agentIsLocal = UserManagementModule.IsLocalGridUser(client.AgentId); 356 agentIsLocal = UserManagementModule.IsLocalGridUser(client.AgentId);
@@ -362,13 +363,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
362 AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode); 363 AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
363 if (agentClientCircuit != null) 364 if (agentClientCircuit != null)
364 { 365 {
365 //[XXX] string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); 366 // Note that this is calling a different interface than base; this one calls with a string param!
366
367 finfos = FriendsService.GetFriends(client.AgentId.ToString()); 367 finfos = FriendsService.GetFriends(client.AgentId.ToString());
368 m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, client.AgentId.ToString()); 368 m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, client.AgentId.ToString());
369 } 369 }
370 370
371// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetFriendsFromService for {0}", client.Name); 371 // m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetFriendsFromService for {0}", client.Name);
372 372
373 return finfos; 373 return finfos;
374 } 374 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index fa8c3f3..adb838c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -26,27 +26,25 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
30using Nini.Config;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Scenes;
34using OpenSim.Region.Framework.Interfaces;
35using System;
36using System.Reflection;
37using System.Collections; 29using System.Collections;
30using System.Collections.Generic;
38using System.Collections.Specialized; 31using System.Collections.Specialized;
39using System.Reflection;
40using System.IO; 32using System.IO;
33using System.Reflection;
41using System.Web; 34using System.Web;
42using System.Xml; 35using System.Xml;
43using log4net; 36using log4net;
44using Mono.Addins; 37using Mono.Addins;
38using Nini.Config;
39using OpenMetaverse;
45using OpenMetaverse.Messages.Linden; 40using OpenMetaverse.Messages.Linden;
46using OpenMetaverse.StructuredData; 41using OpenMetaverse.StructuredData;
42using OpenSim.Framework;
47using OpenSim.Framework.Capabilities; 43using OpenSim.Framework.Capabilities;
48using OpenSim.Framework.Servers; 44using OpenSim.Framework.Servers;
49using OpenSim.Framework.Servers.HttpServer; 45using OpenSim.Framework.Servers.HttpServer;
46using OpenSim.Region.Framework.Scenes;
47using OpenSim.Region.Framework.Interfaces;
50using Caps = OpenSim.Framework.Capabilities.Caps; 48using Caps = OpenSim.Framework.Capabilities.Caps;
51using OSDArray = OpenMetaverse.StructuredData.OSDArray; 49using OSDArray = OpenMetaverse.StructuredData.OSDArray;
52using OSDMap = OpenMetaverse.StructuredData.OSDMap; 50using OSDMap = OpenMetaverse.StructuredData.OSDMap;
@@ -127,9 +125,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
127 { 125 {
128 string uri = "/CAPS/" + UUID.Random(); 126 string uri = "/CAPS/" + UUID.Random();
129 127
130 caps.RegisterHandler("UntrustedSimulatorMessage", 128 caps.RegisterHandler(
131 new RestStreamHandler("POST", uri, 129 "UntrustedSimulatorMessage",
132 HandleUntrustedSimulatorMessage)); 130 new RestStreamHandler("POST", uri, HandleUntrustedSimulatorMessage, "UntrustedSimulatorMessage", null));
133 } 131 }
134 132
135 private string HandleUntrustedSimulatorMessage(string request, 133 private string HandleUntrustedSimulatorMessage(string request,
@@ -278,7 +276,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
278 if (sp.IsChildAgent) 276 if (sp.IsChildAgent)
279 return; 277 return;
280 sp.ControllingClient.Kick(reason); 278 sp.ControllingClient.Kick(reason);
281 sp.Scene.IncomingCloseAgent(sp.UUID, true); 279 sp.Scene.CloseAgent(sp.UUID, true);
282 } 280 }
283 281
284 private void OnIncomingInstantMessage(GridInstantMessage msg) 282 private void OnIncomingInstantMessage(GridInstantMessage msg)
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 1627f6c..b321adb 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -392,7 +392,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
392 gim.fromAgentName = fromAgentName; 392 gim.fromAgentName = fromAgentName;
393 gim.fromGroup = fromGroup; 393 gim.fromGroup = fromGroup;
394 gim.imSessionID = imSessionID.Guid; 394 gim.imSessionID = imSessionID.Guid;
395 gim.RegionID = UUID.Zero.Guid; // RegionID.Guid; 395 gim.RegionID = RegionID.Guid;
396 gim.timestamp = timestamp; 396 gim.timestamp = timestamp;
397 gim.toAgentID = toAgentID.Guid; 397 gim.toAgentID = toAgentID.Guid;
398 gim.message = message; 398 gim.message = message;
@@ -728,7 +728,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
728 gim["position_x"] = msg.Position.X.ToString(); 728 gim["position_x"] = msg.Position.X.ToString();
729 gim["position_y"] = msg.Position.Y.ToString(); 729 gim["position_y"] = msg.Position.Y.ToString();
730 gim["position_z"] = msg.Position.Z.ToString(); 730 gim["position_z"] = msg.Position.Z.ToString();
731 gim["region_id"] = msg.RegionID.ToString(); 731 gim["region_id"] = new UUID(msg.RegionID).ToString();
732 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None); 732 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
733 if (m_MessageKey != String.Empty) 733 if (m_MessageKey != String.Empty)
734 gim["message_key"] = m_MessageKey; 734 gim["message_key"] = m_MessageKey;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
index 659b178..5a8544e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs
@@ -67,10 +67,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
67 /// </summary> 67 /// </summary>
68 protected bool m_merge; 68 protected bool m_merge;
69 69
70 /// <value> 70 protected IInventoryService m_InventoryService;
71 /// We only use this to request modules 71 protected IAssetService m_AssetService;
72 /// </value> 72 protected IUserAccountService m_UserAccountService;
73 protected Scene m_scene;
74 73
75 /// <value> 74 /// <value>
76 /// The stream from which the inventory archive will be loaded. 75 /// The stream from which the inventory archive will be loaded.
@@ -118,9 +117,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
118 protected Dictionary<UUID, UUID> m_creatorIdForAssetId = new Dictionary<UUID, UUID>(); 117 protected Dictionary<UUID, UUID> m_creatorIdForAssetId = new Dictionary<UUID, UUID>();
119 118
120 public InventoryArchiveReadRequest( 119 public InventoryArchiveReadRequest(
121 Scene scene, UserAccount userInfo, string invPath, string loadPath, bool merge) 120 IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, string loadPath, bool merge)
122 : this( 121 : this(
123 scene, 122 inv,
123 assets,
124 uacc,
124 userInfo, 125 userInfo,
125 invPath, 126 invPath,
126 new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress), 127 new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress),
@@ -129,9 +130,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
129 } 130 }
130 131
131 public InventoryArchiveReadRequest( 132 public InventoryArchiveReadRequest(
132 Scene scene, UserAccount userInfo, string invPath, Stream loadStream, bool merge) 133 IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, Stream loadStream, bool merge)
133 { 134 {
134 m_scene = scene; 135 m_InventoryService = inv;
136 m_AssetService = assets;
137 m_UserAccountService = uacc;
135 m_merge = merge; 138 m_merge = merge;
136 m_userInfo = userInfo; 139 m_userInfo = userInfo;
137 m_invPath = invPath; 140 m_invPath = invPath;
@@ -162,7 +165,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
162 165
163 List<InventoryFolderBase> folderCandidates 166 List<InventoryFolderBase> folderCandidates
164 = InventoryArchiveUtils.FindFoldersByPath( 167 = InventoryArchiveUtils.FindFoldersByPath(
165 m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); 168 m_InventoryService, m_userInfo.PrincipalID, m_invPath);
166 169
167 if (folderCandidates.Count == 0) 170 if (folderCandidates.Count == 0)
168 { 171 {
@@ -297,7 +300,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
297 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath); 300 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath);
298 List<InventoryFolderBase> folderCandidates 301 List<InventoryFolderBase> folderCandidates
299 = InventoryArchiveUtils.FindFoldersByPath( 302 = InventoryArchiveUtils.FindFoldersByPath(
300 m_scene.InventoryService, m_userInfo.PrincipalID, plainPath); 303 m_InventoryService, m_userInfo.PrincipalID, plainPath);
301 304
302 if (folderCandidates.Count != 0) 305 if (folderCandidates.Count != 0)
303 { 306 {
@@ -380,7 +383,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
380 = new InventoryFolderBase( 383 = new InventoryFolderBase(
381 newFolderId, newFolderName, m_userInfo.PrincipalID, 384 newFolderId, newFolderName, m_userInfo.PrincipalID,
382 (short)AssetType.Unknown, destFolder.ID, 1); 385 (short)AssetType.Unknown, destFolder.ID, 1);
383 m_scene.InventoryService.AddFolder(destFolder); 386 m_InventoryService.AddFolder(destFolder);
384 387
385 // Record that we have now created this folder 388 // Record that we have now created this folder
386 iarPathExisting += rawDirsToCreate[i] + "/"; 389 iarPathExisting += rawDirsToCreate[i] + "/";
@@ -406,7 +409,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
406 // Don't use the item ID that's in the file 409 // Don't use the item ID that's in the file
407 item.ID = UUID.Random(); 410 item.ID = UUID.Random();
408 411
409 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_scene.UserAccountService); 412 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_UserAccountService);
410 if (UUID.Zero != ospResolvedId) // The user exists in this grid 413 if (UUID.Zero != ospResolvedId) // The user exists in this grid
411 { 414 {
412// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId); 415// m_log.DebugFormat("[INVENTORY ARCHIVER]: Found creator {0} via OSPA resolution", ospResolvedId);
@@ -418,7 +421,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
418 item.CreatorId = ospResolvedId.ToString(); 421 item.CreatorId = ospResolvedId.ToString();
419 item.CreatorData = string.Empty; 422 item.CreatorData = string.Empty;
420 } 423 }
421 else if (item.CreatorData == null || item.CreatorData == String.Empty) 424 else if (string.IsNullOrEmpty(item.CreatorData))
422 { 425 {
423 item.CreatorId = m_userInfo.PrincipalID.ToString(); 426 item.CreatorId = m_userInfo.PrincipalID.ToString();
424// item.CreatorIdAsUuid = new UUID(item.CreatorId); 427// item.CreatorIdAsUuid = new UUID(item.CreatorId);
@@ -436,7 +439,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
436 // relying on native tar tools. 439 // relying on native tar tools.
437 m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid; 440 m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid;
438 441
439 m_scene.AddInventoryItem(item); 442 if (!m_InventoryService.AddItem(item))
443 m_log.WarnFormat("[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}", item.Name, item.Folder);
440 444
441 return item; 445 return item;
442 } 446 }
@@ -518,7 +522,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
518 522
519 foreach (SceneObjectGroup sog in sceneObjects) 523 foreach (SceneObjectGroup sog in sceneObjects)
520 foreach (SceneObjectPart sop in sog.Parts) 524 foreach (SceneObjectPart sop in sog.Parts)
521 if (sop.CreatorData == null || sop.CreatorData == "") 525 if (string.IsNullOrEmpty(sop.CreatorData))
522 sop.CreatorID = m_creatorIdForAssetId[assetId]; 526 sop.CreatorID = m_creatorIdForAssetId[assetId];
523 527
524 if (coa != null) 528 if (coa != null)
@@ -533,7 +537,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
533 AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString()); 537 AssetBase asset = new AssetBase(assetId, "From IAR", assetType, UUID.Zero.ToString());
534 asset.Data = data; 538 asset.Data = data;
535 539
536 m_scene.AssetService.Store(asset); 540 m_AssetService.Store(asset);
537 541
538 return true; 542 return true;
539 } 543 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index 4ec8ae7..4292719 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -78,7 +78,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
78 /// <value> 78 /// <value>
79 /// Used to collect the uuids of the assets that we need to save into the archive 79 /// Used to collect the uuids of the assets that we need to save into the archive
80 /// </value> 80 /// </value>
81 protected Dictionary<UUID, AssetType> m_assetUuids = new Dictionary<UUID, AssetType>(); 81 protected Dictionary<UUID, sbyte> m_assetUuids = new Dictionary<UUID, sbyte>();
82 82
83 /// <value> 83 /// <value>
84 /// Used to collect the uuids of the users that we need to save into the archive 84 /// Used to collect the uuids of the users that we need to save into the archive
@@ -187,7 +187,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
187 187
188 // Don't chase down link asset items as they actually point to their target item IDs rather than an asset 188 // Don't chase down link asset items as they actually point to their target item IDs rather than an asset
189 if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) 189 if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder)
190 m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (AssetType)inventoryItem.AssetType, m_assetUuids); 190 m_assetGatherer.GatherAssetUuids(inventoryItem.AssetID, (sbyte)inventoryItem.AssetType, m_assetUuids);
191 } 191 }
192 192
193 /// <summary> 193 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index f4f9e2d..ea660bd 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -294,7 +294,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
294 294
295 try 295 try
296 { 296 {
297 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadStream, merge); 297 request = new InventoryArchiveReadRequest(m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadStream, merge);
298 } 298 }
299 catch (EntryPointNotFoundException e) 299 catch (EntryPointNotFoundException e)
300 { 300 {
@@ -342,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
342 342
343 try 343 try
344 { 344 {
345 request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge); 345 request = new InventoryArchiveReadRequest(m_aScene.InventoryService, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadPath, merge);
346 } 346 }
347 catch (EntryPointNotFoundException e) 347 catch (EntryPointNotFoundException e)
348 { 348 {
@@ -538,7 +538,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
538 } 538 }
539 catch (Exception e) 539 catch (Exception e)
540 { 540 {
541 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e.Message); 541 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e);
542 return null; 542 return null;
543 } 543 }
544 */ 544 */
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
index 95f562e..08f199a 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveLoadPathTests.cs
@@ -229,7 +229,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
229 229
230 { 230 {
231 // Test replication of path1 231 // Test replication of path1
232 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) 232 new InventoryArchiveReadRequest(scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
233 .ReplicateArchivePathToUserInventory( 233 .ReplicateArchivePathToUserInventory(
234 iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 234 iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
235 foldersCreated, nodesLoaded); 235 foldersCreated, nodesLoaded);
@@ -246,7 +246,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
246 246
247 { 247 {
248 // Test replication of path2 248 // Test replication of path2
249 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) 249 new InventoryArchiveReadRequest(scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
250 .ReplicateArchivePathToUserInventory( 250 .ReplicateArchivePathToUserInventory(
251 iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 251 iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
252 foldersCreated, nodesLoaded); 252 foldersCreated, nodesLoaded);
@@ -291,8 +291,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
291 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); 291 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
292 292
293 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); 293 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
294 294
295 new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false) 295 new InventoryArchiveReadRequest(scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, null, (Stream)null, false)
296 .ReplicateArchivePathToUserInventory( 296 .ReplicateArchivePathToUserInventory(
297 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 297 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
298 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); 298 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
@@ -342,8 +342,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
342 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); 342 string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
343 343
344 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); 344 string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
345 345
346 new InventoryArchiveReadRequest(scene, ua1, folder1ExistingName, (Stream)null, true) 346 new InventoryArchiveReadRequest(scene.InventoryService, scene.AssetService, scene.UserAccountService, ua1, folder1ExistingName, (Stream)null, true)
347 .ReplicateArchivePathToUserInventory( 347 .ReplicateArchivePathToUserInventory(
348 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), 348 itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
349 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>()); 349 new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
index 5e7e24c..b85739e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveSaveTests.cs
@@ -86,7 +86,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
86 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 86 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
87 87
88 InventoryArchiveReadRequest iarr 88 InventoryArchiveReadRequest iarr
89 = new InventoryArchiveReadRequest(null, null, null, (Stream)null, false); 89 = new InventoryArchiveReadRequest(null, null, null, null, null, (Stream)null, false);
90 iarr.LoadControlFile(filePath, data); 90 iarr.LoadControlFile(filePath, data);
91 91
92 Assert.That(iarr.ControlFileLoaded, Is.True); 92 Assert.That(iarr.ControlFileLoaded, Is.True);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index f122d00..03aaaac 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -47,10 +47,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
47 47
48 /// <summary> 48 /// <summary>
49 private List<Scene> m_Scenelist = new List<Scene>(); 49 private List<Scene> m_Scenelist = new List<Scene>();
50// private Dictionary<UUID, Scene> m_AgentRegions =
51// new Dictionary<UUID, Scene>();
52 50
53 private IMessageTransferModule m_TransferModule = null; 51 private IMessageTransferModule m_TransferModule;
54 private bool m_Enabled = true; 52 private bool m_Enabled = true;
55 53
56 #region Region Module interface 54 #region Region Module interface
@@ -81,9 +79,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
81// scene.RegisterModuleInterface<IInventoryTransferModule>(this); 79// scene.RegisterModuleInterface<IInventoryTransferModule>(this);
82 80
83 scene.EventManager.OnNewClient += OnNewClient; 81 scene.EventManager.OnNewClient += OnNewClient;
84// scene.EventManager.OnClientClosed += ClientLoggedOut;
85 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; 82 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
86// scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
87 } 83 }
88 84
89 public void RegionLoaded(Scene scene) 85 public void RegionLoaded(Scene scene)
@@ -96,11 +92,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
96 m_log.Error("[INVENTORY TRANSFER]: No Message transfer module found, transfers will be local only"); 92 m_log.Error("[INVENTORY TRANSFER]: No Message transfer module found, transfers will be local only");
97 m_Enabled = false; 93 m_Enabled = false;
98 94
99 m_Scenelist.Clear(); 95// m_Scenelist.Clear();
100 scene.EventManager.OnNewClient -= OnNewClient; 96// scene.EventManager.OnNewClient -= OnNewClient;
101// scene.EventManager.OnClientClosed -= ClientLoggedOut;
102 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 97 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
103// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
104 } 98 }
105 } 99 }
106 } 100 }
@@ -108,9 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
108 public void RemoveRegion(Scene scene) 102 public void RemoveRegion(Scene scene)
109 { 103 {
110 scene.EventManager.OnNewClient -= OnNewClient; 104 scene.EventManager.OnNewClient -= OnNewClient;
111// scene.EventManager.OnClientClosed -= ClientLoggedOut;
112 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 105 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
113// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
114 m_Scenelist.Remove(scene); 106 m_Scenelist.Remove(scene);
115 } 107 }
116 108
@@ -139,11 +131,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
139 // Inventory giving is conducted via instant message 131 // Inventory giving is conducted via instant message
140 client.OnInstantMessage += OnInstantMessage; 132 client.OnInstantMessage += OnInstantMessage;
141 } 133 }
142
143// protected void OnSetRootAgentScene(UUID id, Scene scene)
144// {
145// m_AgentRegions[id] = scene;
146// }
147 134
148 private Scene FindClientScene(UUID agentId) 135 private Scene FindClientScene(UUID agentId)
149 { 136 {
@@ -162,8 +149,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
162 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 149 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
163 { 150 {
164// m_log.DebugFormat( 151// m_log.DebugFormat(
165// "[INVENTORY TRANSFER]: {0} IM type received from {1}", 152// "[INVENTORY TRANSFER]: {0} IM type received from client {1}. From={2} ({3}), To={4}",
166// (InstantMessageDialog)im.dialog, client.Name); 153// (InstantMessageDialog)im.dialog, client.Name,
154// im.fromAgentID, im.fromAgentName, im.toAgentID);
167 155
168 Scene scene = FindClientScene(client.AgentId); 156 Scene scene = FindClientScene(client.AgentId);
169 157
@@ -188,9 +176,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
188 { 176 {
189 UUID folderID = new UUID(im.binaryBucket, 1); 177 UUID folderID = new UUID(im.binaryBucket, 1);
190 178
191 m_log.DebugFormat("[INVENTORY TRANSFER]: Inserting original folder {0} "+ 179 m_log.DebugFormat(
192 "into agent {1}'s inventory", 180 "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory",
193 folderID, new UUID(im.toAgentID)); 181 folderID, new UUID(im.toAgentID));
194 182
195 InventoryFolderBase folderCopy 183 InventoryFolderBase folderCopy
196 = scene.GiveInventoryFolder(recipientID, client.AgentId, folderID, UUID.Zero); 184 = scene.GiveInventoryFolder(recipientID, client.AgentId, folderID, UUID.Zero);
@@ -213,7 +201,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
213 user.ControllingClient.SendBulkUpdateInventory(folderCopy); 201 user.ControllingClient.SendBulkUpdateInventory(folderCopy);
214 202
215 // HACK!! 203 // HACK!!
216 // Insert the ID of the copied item into the IM so that we know which item to move to trash if it 204 // Insert the ID of the copied folder into the IM so that we know which item to move to trash if it
217 // is rejected. 205 // is rejected.
218 // XXX: This is probably a misuse of the session ID slot. 206 // XXX: This is probably a misuse of the session ID slot.
219 im.imSessionID = copyID.Guid; 207 im.imSessionID = copyID.Guid;
@@ -425,7 +413,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
425 { 413 {
426 folder = new InventoryFolderBase(inventoryID, client.AgentId); 414 folder = new InventoryFolderBase(inventoryID, client.AgentId);
427 folder = invService.GetFolder(folder); 415 folder = invService.GetFolder(folder);
428 416
429 if (folder != null & trashFolder != null) 417 if (folder != null & trashFolder != null)
430 { 418 {
431 previousParentFolderID = folder.ParentID; 419 previousParentFolderID = folder.ParentID;
@@ -477,76 +465,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
477 } 465 }
478 } 466 }
479 467
480// public bool NeedSceneCacheClear(UUID agentID, Scene scene)
481// {
482// if (!m_AgentRegions.ContainsKey(agentID))
483// {
484// // Since we can get here two ways, we need to scan
485// // the scenes here. This is somewhat more expensive
486// // but helps avoid a nasty bug
487// //
488//
489// foreach (Scene s in m_Scenelist)
490// {
491// ScenePresence presence;
492//
493// if (s.TryGetScenePresence(agentID, out presence))
494// {
495// // If the agent is in this scene, then we
496// // are being called twice in a single
497// // teleport. This is wasteful of cycles
498// // but harmless due to this 2nd level check
499// //
500// // If the agent is found in another scene
501// // then the list wasn't current
502// //
503// // If the agent is totally unknown, then what
504// // are we even doing here??
505// //
506// if (s == scene)
507// {
508// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName);
509// return true;
510// }
511// else
512// {
513// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName);
514// return false;
515// }
516// }
517// }
518// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName);
519// return true;
520// }
521//
522// // The agent is left in current Scene, so we must be
523// // going to another instance
524// //
525// if (m_AgentRegions[agentID] == scene)
526// {
527// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName);
528// m_AgentRegions.Remove(agentID);
529// return true;
530// }
531//
532// // Another region has claimed the agent
533// //
534// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName);
535// return false;
536// }
537//
538// public void ClientLoggedOut(UUID agentID, Scene scene)
539// {
540// if (m_AgentRegions.ContainsKey(agentID))
541// m_AgentRegions.Remove(agentID);
542// }
543
544 /// <summary> 468 /// <summary>
545 /// 469 ///
546 /// </summary> 470 /// </summary>
547 /// <param name="msg"></param> 471 /// <param name="im"></param>
548 private void OnGridInstantMessage(GridInstantMessage im) 472 private void OnGridInstantMessage(GridInstantMessage im)
549 { 473 {
474 // Check if it's a type of message that we should handle
475 if (!((im.dialog == (byte) InstantMessageDialog.InventoryOffered)
476 || (im.dialog == (byte) InstantMessageDialog.InventoryAccepted)
477 || (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
478 || (im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined)))
479 return;
480
481 m_log.DebugFormat(
482 "[INVENTORY TRANSFER]: {0} IM type received from grid. From={1} ({2}), To={3}",
483 (InstantMessageDialog)im.dialog, im.fromAgentID, im.fromAgentName, im.toAgentID);
484
550 // Check if this is ours to handle 485 // Check if this is ours to handle
551 // 486 //
552 Scene scene = FindClientScene(new UUID(im.toAgentID)); 487 Scene scene = FindClientScene(new UUID(im.toAgentID));
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
new file mode 100644
index 0000000..162a0c3
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/Tests/InventoryTransferModuleTests.cs
@@ -0,0 +1,449 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net.Config;
32using Nini.Config;
33using NUnit.Framework;
34using OpenMetaverse;
35using OpenMetaverse.Assets;
36using OpenSim.Framework;
37using OpenSim.Region.CoreModules.Avatar.Inventory.Transfer;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Tests.Common;
42using OpenSim.Tests.Common.Mock;
43
44namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.Tests
45{
46 [TestFixture]
47 public class InventoryTransferModuleTests : OpenSimTestCase
48 {
49 protected TestScene m_scene;
50
51 [SetUp]
52 public override void SetUp()
53 {
54 base.SetUp();
55
56 IConfigSource config = new IniConfigSource();
57 config.AddConfig("Messaging");
58 config.Configs["Messaging"].Set("InventoryTransferModule", "InventoryTransferModule");
59
60 m_scene = new SceneHelpers().SetupScene();
61 SceneHelpers.SetupSceneModules(m_scene, config, new InventoryTransferModule());
62 }
63
64 [Test]
65 public void TestAcceptGivenItem()
66 {
67// TestHelpers.EnableLogging();
68
69 UUID initialSessionId = TestHelpers.ParseTail(0x10);
70 UUID itemId = TestHelpers.ParseTail(0x100);
71 UUID assetId = TestHelpers.ParseTail(0x200);
72
73 UserAccount ua1
74 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
75 UserAccount ua2
76 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
77
78 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
79 TestClient giverClient = (TestClient)giverSp.ControllingClient;
80
81 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
82 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
83
84 // Create the object to test give
85 InventoryItemBase originalItem
86 = UserInventoryHelpers.CreateInventoryItem(
87 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
88
89 byte[] giveImBinaryBucket = new byte[17];
90 byte[] itemIdBytes = itemId.GetBytes();
91 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
92
93 GridInstantMessage giveIm
94 = new GridInstantMessage(
95 m_scene,
96 giverSp.UUID,
97 giverSp.Name,
98 receiverSp.UUID,
99 (byte)InstantMessageDialog.InventoryOffered,
100 false,
101 "inventory offered msg",
102 initialSessionId,
103 false,
104 Vector3.Zero,
105 giveImBinaryBucket,
106 true);
107
108 giverClient.HandleImprovedInstantMessage(giveIm);
109
110 // These details might not all be correct.
111 GridInstantMessage acceptIm
112 = new GridInstantMessage(
113 m_scene,
114 receiverSp.UUID,
115 receiverSp.Name,
116 giverSp.UUID,
117 (byte)InstantMessageDialog.InventoryAccepted,
118 false,
119 "inventory accepted msg",
120 initialSessionId,
121 false,
122 Vector3.Zero,
123 null,
124 true);
125
126 receiverClient.HandleImprovedInstantMessage(acceptIm);
127
128 // Test for item remaining in the giver's inventory (here we assume a copy item)
129 // TODO: Test no-copy items.
130 InventoryItemBase originalItemAfterGive
131 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
132
133 Assert.That(originalItemAfterGive, Is.Not.Null);
134 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
135
136 // Test for item successfully making it into the receiver's inventory
137 InventoryItemBase receivedItem
138 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Objects/givenObj");
139
140 Assert.That(receivedItem, Is.Not.Null);
141 Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID));
142
143 // Test that on a delete, item still exists and is accessible for the giver.
144 m_scene.InventoryService.DeleteItems(receiverSp.UUID, new List<UUID>() { receivedItem.ID });
145
146 InventoryItemBase originalItemAfterDelete
147 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
148
149 Assert.That(originalItemAfterDelete, Is.Not.Null);
150
151 // TODO: Test scenario where giver deletes their item first.
152 }
153
154 /// <summary>
155 /// Test user rejection of a given item.
156 /// </summary>
157 /// <remarks>
158 /// A rejected item still ends up in the user's trash folder.
159 /// </remarks>
160 [Test]
161 public void TestRejectGivenItem()
162 {
163// TestHelpers.EnableLogging();
164
165 UUID initialSessionId = TestHelpers.ParseTail(0x10);
166 UUID itemId = TestHelpers.ParseTail(0x100);
167 UUID assetId = TestHelpers.ParseTail(0x200);
168
169 UserAccount ua1
170 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
171 UserAccount ua2
172 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
173
174 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
175 TestClient giverClient = (TestClient)giverSp.ControllingClient;
176
177 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
178 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
179
180 // Create the object to test give
181 InventoryItemBase originalItem
182 = UserInventoryHelpers.CreateInventoryItem(
183 m_scene, "givenObj", itemId, assetId, giverSp.UUID, InventoryType.Object);
184
185 GridInstantMessage receivedIm = null;
186 receiverClient.OnReceivedInstantMessage += im => receivedIm = im;
187
188 byte[] giveImBinaryBucket = new byte[17];
189 byte[] itemIdBytes = itemId.GetBytes();
190 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
191
192 GridInstantMessage giveIm
193 = new GridInstantMessage(
194 m_scene,
195 giverSp.UUID,
196 giverSp.Name,
197 receiverSp.UUID,
198 (byte)InstantMessageDialog.InventoryOffered,
199 false,
200 "inventory offered msg",
201 initialSessionId,
202 false,
203 Vector3.Zero,
204 giveImBinaryBucket,
205 true);
206
207 giverClient.HandleImprovedInstantMessage(giveIm);
208
209 // These details might not all be correct.
210 // Session ID is now the created item ID (!)
211 GridInstantMessage rejectIm
212 = new GridInstantMessage(
213 m_scene,
214 receiverSp.UUID,
215 receiverSp.Name,
216 giverSp.UUID,
217 (byte)InstantMessageDialog.InventoryDeclined,
218 false,
219 "inventory declined msg",
220 new UUID(receivedIm.imSessionID),
221 false,
222 Vector3.Zero,
223 null,
224 true);
225
226 receiverClient.HandleImprovedInstantMessage(rejectIm);
227
228 // Test for item remaining in the giver's inventory (here we assume a copy item)
229 // TODO: Test no-copy items.
230 InventoryItemBase originalItemAfterGive
231 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
232
233 Assert.That(originalItemAfterGive, Is.Not.Null);
234 Assert.That(originalItemAfterGive.ID, Is.EqualTo(originalItem.ID));
235
236 // Test for item successfully making it into the receiver's inventory
237 InventoryItemBase receivedItem
238 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, receiverSp.UUID, "Trash/givenObj");
239
240 InventoryFolderBase trashFolder
241 = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, AssetType.TrashFolder);
242
243 Assert.That(receivedItem, Is.Not.Null);
244 Assert.That(receivedItem.ID, Is.Not.EqualTo(originalItem.ID));
245 Assert.That(receivedItem.Folder, Is.EqualTo(trashFolder.ID));
246
247 // Test that on a delete, item still exists and is accessible for the giver.
248 m_scene.InventoryService.PurgeFolder(trashFolder);
249
250 InventoryItemBase originalItemAfterDelete
251 = UserInventoryHelpers.GetInventoryItem(m_scene.InventoryService, giverSp.UUID, "Objects/givenObj");
252
253 Assert.That(originalItemAfterDelete, Is.Not.Null);
254 }
255
256 [Test]
257 public void TestAcceptGivenFolder()
258 {
259 TestHelpers.InMethod();
260// TestHelpers.EnableLogging();
261
262 UUID initialSessionId = TestHelpers.ParseTail(0x10);
263 UUID folderId = TestHelpers.ParseTail(0x100);
264
265 UserAccount ua1
266 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
267 UserAccount ua2
268 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
269
270 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
271 TestClient giverClient = (TestClient)giverSp.ControllingClient;
272
273 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
274 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
275
276 InventoryFolderBase originalFolder
277 = UserInventoryHelpers.CreateInventoryFolder(
278 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
279
280 byte[] giveImBinaryBucket = new byte[17];
281 giveImBinaryBucket[0] = (byte)AssetType.Folder;
282 byte[] itemIdBytes = folderId.GetBytes();
283 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
284
285 GridInstantMessage giveIm
286 = new GridInstantMessage(
287 m_scene,
288 giverSp.UUID,
289 giverSp.Name,
290 receiverSp.UUID,
291 (byte)InstantMessageDialog.InventoryOffered,
292 false,
293 "inventory offered msg",
294 initialSessionId,
295 false,
296 Vector3.Zero,
297 giveImBinaryBucket,
298 true);
299
300 giverClient.HandleImprovedInstantMessage(giveIm);
301
302 // These details might not all be correct.
303 GridInstantMessage acceptIm
304 = new GridInstantMessage(
305 m_scene,
306 receiverSp.UUID,
307 receiverSp.Name,
308 giverSp.UUID,
309 (byte)InstantMessageDialog.InventoryAccepted,
310 false,
311 "inventory accepted msg",
312 initialSessionId,
313 false,
314 Vector3.Zero,
315 null,
316 true);
317
318 receiverClient.HandleImprovedInstantMessage(acceptIm);
319
320 // Test for item remaining in the giver's inventory (here we assume a copy item)
321 // TODO: Test no-copy items.
322 InventoryFolderBase originalFolderAfterGive
323 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
324
325 Assert.That(originalFolderAfterGive, Is.Not.Null);
326 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
327
328 // Test for item successfully making it into the receiver's inventory
329 InventoryFolderBase receivedFolder
330 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "f1");
331
332 Assert.That(receivedFolder, Is.Not.Null);
333 Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID));
334
335 // Test that on a delete, item still exists and is accessible for the giver.
336 m_scene.InventoryService.DeleteFolders(receiverSp.UUID, new List<UUID>() { receivedFolder.ID });
337
338 InventoryFolderBase originalFolderAfterDelete
339 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
340
341 Assert.That(originalFolderAfterDelete, Is.Not.Null);
342
343 // TODO: Test scenario where giver deletes their item first.
344 }
345
346 /// <summary>
347 /// Test user rejection of a given item.
348 /// </summary>
349 /// <remarks>
350 /// A rejected item still ends up in the user's trash folder.
351 /// </remarks>
352 [Test]
353 public void TestRejectGivenFolder()
354 {
355 TestHelpers.InMethod();
356// TestHelpers.EnableLogging();
357
358 UUID initialSessionId = TestHelpers.ParseTail(0x10);
359 UUID folderId = TestHelpers.ParseTail(0x100);
360
361 UserAccount ua1
362 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "One", TestHelpers.ParseTail(0x1), "pw");
363 UserAccount ua2
364 = UserAccountHelpers.CreateUserWithInventory(m_scene, "User", "Two", TestHelpers.ParseTail(0x2), "pw");
365
366 ScenePresence giverSp = SceneHelpers.AddScenePresence(m_scene, ua1);
367 TestClient giverClient = (TestClient)giverSp.ControllingClient;
368
369 ScenePresence receiverSp = SceneHelpers.AddScenePresence(m_scene, ua2);
370 TestClient receiverClient = (TestClient)receiverSp.ControllingClient;
371
372 // Create the folder to test give
373 InventoryFolderBase originalFolder
374 = UserInventoryHelpers.CreateInventoryFolder(
375 m_scene.InventoryService, giverSp.UUID, folderId, "f1", true);
376
377 GridInstantMessage receivedIm = null;
378 receiverClient.OnReceivedInstantMessage += im => receivedIm = im;
379
380 byte[] giveImBinaryBucket = new byte[17];
381 giveImBinaryBucket[0] = (byte)AssetType.Folder;
382 byte[] itemIdBytes = folderId.GetBytes();
383 Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length);
384
385 GridInstantMessage giveIm
386 = new GridInstantMessage(
387 m_scene,
388 giverSp.UUID,
389 giverSp.Name,
390 receiverSp.UUID,
391 (byte)InstantMessageDialog.InventoryOffered,
392 false,
393 "inventory offered msg",
394 initialSessionId,
395 false,
396 Vector3.Zero,
397 giveImBinaryBucket,
398 true);
399
400 giverClient.HandleImprovedInstantMessage(giveIm);
401
402 // These details might not all be correct.
403 // Session ID is now the created item ID (!)
404 GridInstantMessage rejectIm
405 = new GridInstantMessage(
406 m_scene,
407 receiverSp.UUID,
408 receiverSp.Name,
409 giverSp.UUID,
410 (byte)InstantMessageDialog.InventoryDeclined,
411 false,
412 "inventory declined msg",
413 new UUID(receivedIm.imSessionID),
414 false,
415 Vector3.Zero,
416 null,
417 true);
418
419 receiverClient.HandleImprovedInstantMessage(rejectIm);
420
421 // Test for item remaining in the giver's inventory (here we assume a copy item)
422 // TODO: Test no-copy items.
423 InventoryFolderBase originalFolderAfterGive
424 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
425
426 Assert.That(originalFolderAfterGive, Is.Not.Null);
427 Assert.That(originalFolderAfterGive.ID, Is.EqualTo(originalFolder.ID));
428
429 // Test for folder successfully making it into the receiver's inventory
430 InventoryFolderBase receivedFolder
431 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, receiverSp.UUID, "Trash/f1");
432
433 InventoryFolderBase trashFolder
434 = m_scene.InventoryService.GetFolderForType(receiverSp.UUID, AssetType.TrashFolder);
435
436 Assert.That(receivedFolder, Is.Not.Null);
437 Assert.That(receivedFolder.ID, Is.Not.EqualTo(originalFolder.ID));
438 Assert.That(receivedFolder.ParentID, Is.EqualTo(trashFolder.ID));
439
440 // Test that on a delete, item still exists and is accessible for the giver.
441 m_scene.InventoryService.PurgeFolder(trashFolder);
442
443 InventoryFolderBase originalFolderAfterDelete
444 = UserInventoryHelpers.GetInventoryFolder(m_scene.InventoryService, giverSp.UUID, "f1");
445
446 Assert.That(originalFolderAfterDelete, Is.Not.Null);
447 }
448 }
449} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index 0c64f19..c517a30 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -165,7 +165,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
165 (uint)presence.AbsolutePosition.Y, 165 (uint)presence.AbsolutePosition.Y,
166 (uint)presence.AbsolutePosition.Z + 2); 166 (uint)presence.AbsolutePosition.Z + 2);
167 167
168 m_log.DebugFormat("TP invite with message {0}, type {1}", message, lureType); 168 m_log.DebugFormat("[LURE MODULE]: TP invite with message {0}, type {1}", message, lureType);
169 169
170 GridInstantMessage m; 170 GridInstantMessage m;
171 171
diff --git a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
index bf24030..2bb24ae 100644
--- a/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Profile/BasicProfileModule.cs
@@ -57,6 +57,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Profile
57 57
58 public void Initialise(IConfigSource config) 58 public void Initialise(IConfigSource config)
59 { 59 {
60 if(config.Configs["UserProfiles"] != null)
61 return;
62
60 m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled"); 63 m_log.DebugFormat("[PROFILE MODULE]: Basic Profile Module enabled");
61 m_Enabled = true; 64 m_Enabled = true;
62 } 65 }
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
new file mode 100644
index 0000000..d359ebc
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs
@@ -0,0 +1,1343 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.IO;
30using System.Text;
31using System.Collections;
32using System.Collections.Generic;
33using System.Globalization;
34using System.Net;
35using System.Net.Sockets;
36using System.Reflection;
37using System.Xml;
38using OpenMetaverse;
39using OpenMetaverse.StructuredData;
40using log4net;
41using Nini.Config;
42using Nwc.XmlRpc;
43using OpenSim.Framework;
44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes;
46using OpenSim.Services.Interfaces;
47using Mono.Addins;
48using OpenSim.Services.Connectors.Hypergrid;
49
50namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles
51{
52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserProfilesModule")]
53 public class UserProfileModule : IProfileModule, INonSharedRegionModule
54 {
55 /// <summary>
56 /// Logging
57 /// </summary>
58 static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59
60 // The pair of Dictionaries are used to handle the switching of classified ads
61 // by maintaining a cache of classified id to creator id mappings and an interest
62 // count. The entries are removed when the interest count reaches 0.
63 Dictionary<UUID, UUID> m_classifiedCache = new Dictionary<UUID, UUID>();
64 Dictionary<UUID, int> m_classifiedInterest = new Dictionary<UUID, int>();
65
66 public Scene Scene
67 {
68 get; private set;
69 }
70
71 /// <summary>
72 /// Gets or sets the ConfigSource.
73 /// </summary>
74 /// <value>
75 /// The configuration
76 /// </value>
77 public IConfigSource Config {
78 get;
79 set;
80 }
81
82 /// <summary>
83 /// Gets or sets the URI to the profile server.
84 /// </summary>
85 /// <value>
86 /// The profile server URI.
87 /// </value>
88 public string ProfileServerUri {
89 get;
90 set;
91 }
92
93 IProfileModule ProfileModule
94 {
95 get; set;
96 }
97
98 IUserManagement UserManagementModule
99 {
100 get; set;
101 }
102
103 /// <summary>
104 /// Gets or sets a value indicating whether this
105 /// <see cref="OpenSim.Region.Coremodules.UserProfiles.UserProfileModule"/> is enabled.
106 /// </summary>
107 /// <value>
108 /// <c>true</c> if enabled; otherwise, <c>false</c>.
109 /// </value>
110 public bool Enabled {
111 get;
112 set;
113 }
114
115 #region IRegionModuleBase implementation
116 /// <summary>
117 /// This is called to initialize the region module. For shared modules, this is called exactly once, after
118 /// creating the single (shared) instance. For non-shared modules, this is called once on each instance, after
119 /// the instace for the region has been created.
120 /// </summary>
121 /// <param name='source'>
122 /// Source.
123 /// </param>
124 public void Initialise(IConfigSource source)
125 {
126 Config = source;
127 ReplaceableInterface = typeof(IProfileModule);
128
129 IConfig profileConfig = Config.Configs["UserProfiles"];
130
131 if (profileConfig == null)
132 {
133 m_log.Debug("[PROFILES]: UserProfiles disabled, no configuration");
134 Enabled = false;
135 return;
136 }
137
138 // If we find ProfileURL then we configure for FULL support
139 // else we setup for BASIC support
140 ProfileServerUri = profileConfig.GetString("ProfileServiceURL", "");
141 if (ProfileServerUri == "")
142 {
143 Enabled = false;
144 return;
145 }
146
147 m_log.Debug("[PROFILES]: Full Profiles Enabled");
148 ReplaceableInterface = null;
149 Enabled = true;
150 }
151
152 /// <summary>
153 /// Adds the region.
154 /// </summary>
155 /// <param name='scene'>
156 /// Scene.
157 /// </param>
158 public void AddRegion(Scene scene)
159 {
160 if(!Enabled)
161 return;
162
163 Scene = scene;
164 Scene.RegisterModuleInterface<IProfileModule>(this);
165 Scene.EventManager.OnNewClient += OnNewClient;
166 Scene.EventManager.OnMakeRootAgent += HandleOnMakeRootAgent;
167
168 UserManagementModule = Scene.RequestModuleInterface<IUserManagement>();
169 }
170
171 void HandleOnMakeRootAgent (ScenePresence obj)
172 {
173 if(obj.PresenceType == PresenceType.Npc)
174 return;
175
176 Util.FireAndForget(delegate
177 {
178 GetImageAssets(((IScenePresence)obj).UUID);
179 });
180 }
181
182 /// <summary>
183 /// Removes the region.
184 /// </summary>
185 /// <param name='scene'>
186 /// Scene.
187 /// </param>
188 public void RemoveRegion(Scene scene)
189 {
190 if(!Enabled)
191 return;
192 }
193
194 /// <summary>
195 /// This will be called once for every scene loaded. In a shared module this will be multiple times in one
196 /// instance, while a nonshared module instance will only be called once. This method is called after AddRegion
197 /// has been called in all modules for that scene, providing an opportunity to request another module's
198 /// interface, or hook an event from another module.
199 /// </summary>
200 /// <param name='scene'>
201 /// Scene.
202 /// </param>
203 public void RegionLoaded(Scene scene)
204 {
205 if(!Enabled)
206 return;
207 }
208
209 /// <summary>
210 /// If this returns non-null, it is the type of an interface that this module intends to register. This will
211 /// cause the loader to defer loading of this module until all other modules have been loaded. If no other
212 /// module has registered the interface by then, this module will be activated, else it will remain inactive,
213 /// letting the other module take over. This should return non-null ONLY in modules that are intended to be
214 /// easily replaceable, e.g. stub implementations that the developer expects to be replaced by third party
215 /// provided modules.
216 /// </summary>
217 /// <value>
218 /// The replaceable interface.
219 /// </value>
220 public Type ReplaceableInterface
221 {
222 get; private set;
223 }
224
225 /// <summary>
226 /// Called as the instance is closed.
227 /// </summary>
228 public void Close()
229 {
230 }
231
232 /// <value>
233 /// The name of the module
234 /// </value>
235 /// <summary>
236 /// Gets the module name.
237 /// </summary>
238 public string Name
239 {
240 get { return "UserProfileModule"; }
241 }
242 #endregion IRegionModuleBase implementation
243
244 #region Region Event Handlers
245 /// <summary>
246 /// Raises the new client event.
247 /// </summary>
248 /// <param name='client'>
249 /// Client.
250 /// </param>
251 void OnNewClient(IClientAPI client)
252 {
253 //Profile
254 client.OnRequestAvatarProperties += RequestAvatarProperties;
255 client.OnUpdateAvatarProperties += AvatarPropertiesUpdate;
256 client.OnAvatarInterestUpdate += AvatarInterestsUpdate;
257
258 // Classifieds
259 client.AddGenericPacketHandler("avatarclassifiedsrequest", ClassifiedsRequest);
260 client.OnClassifiedInfoUpdate += ClassifiedInfoUpdate;
261 client.OnClassifiedInfoRequest += ClassifiedInfoRequest;
262 client.OnClassifiedDelete += ClassifiedDelete;
263
264 // Picks
265 client.AddGenericPacketHandler("avatarpicksrequest", PicksRequest);
266 client.AddGenericPacketHandler("pickinforequest", PickInfoRequest);
267 client.OnPickInfoUpdate += PickInfoUpdate;
268 client.OnPickDelete += PickDelete;
269
270 // Notes
271 client.AddGenericPacketHandler("avatarnotesrequest", NotesRequest);
272 client.OnAvatarNotesUpdate += NotesUpdate;
273 }
274 #endregion Region Event Handlers
275
276 #region Classified
277 ///
278 /// <summary>
279 /// Handles the avatar classifieds request.
280 /// </summary>
281 /// <param name='sender'>
282 /// Sender.
283 /// </param>
284 /// <param name='method'>
285 /// Method.
286 /// </param>
287 /// <param name='args'>
288 /// Arguments.
289 /// </param>
290 public void ClassifiedsRequest(Object sender, string method, List<String> args)
291 {
292 if (!(sender is IClientAPI))
293 return;
294
295 IClientAPI remoteClient = (IClientAPI)sender;
296
297 UUID targetID;
298 UUID.TryParse(args[0], out targetID);
299
300 // Can't handle NPC yet...
301 ScenePresence p = FindPresence(targetID);
302
303 if (null != p)
304 {
305 if (p.PresenceType == PresenceType.Npc)
306 return;
307 }
308
309 string serverURI = string.Empty;
310 GetUserProfileServerURI(targetID, out serverURI);
311 UUID creatorId = UUID.Zero;
312 Dictionary<UUID, string> classifieds = new Dictionary<UUID, string>();
313
314 OSDMap parameters= new OSDMap();
315 UUID.TryParse(args[0], out creatorId);
316 parameters.Add("creatorId", OSD.FromUUID(creatorId));
317 OSD Params = (OSD)parameters;
318 if(!JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString()))
319 {
320 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds);
321 return;
322 }
323
324 parameters = (OSDMap)Params;
325
326 OSDArray list = (OSDArray)parameters["result"];
327
328
329 foreach(OSD map in list)
330 {
331 OSDMap m = (OSDMap)map;
332 UUID cid = m["classifieduuid"].AsUUID();
333 string name = m["name"].AsString();
334
335 classifieds[cid] = name;
336
337 lock (m_classifiedCache)
338 {
339 if (!m_classifiedCache.ContainsKey(cid))
340 {
341 m_classifiedCache.Add(cid,creatorId);
342 m_classifiedInterest.Add(cid, 0);
343 }
344
345 m_classifiedInterest[cid]++;
346 }
347 }
348
349 remoteClient.SendAvatarClassifiedReply(new UUID(args[0]), classifieds);
350 }
351
352 public void ClassifiedInfoRequest(UUID queryClassifiedID, IClientAPI remoteClient)
353 {
354 UUID target = remoteClient.AgentId;
355 UserClassifiedAdd ad = new UserClassifiedAdd();
356 ad.ClassifiedId = queryClassifiedID;
357
358 lock (m_classifiedCache)
359 {
360 if (m_classifiedCache.ContainsKey(queryClassifiedID))
361 {
362 target = m_classifiedCache[queryClassifiedID];
363
364 m_classifiedInterest[queryClassifiedID] --;
365
366 if (m_classifiedInterest[queryClassifiedID] == 0)
367 {
368 m_classifiedInterest.Remove(queryClassifiedID);
369 m_classifiedCache.Remove(queryClassifiedID);
370 }
371 }
372 }
373
374 string serverURI = string.Empty;
375 GetUserProfileServerURI(target, out serverURI);
376
377 object Ad = (object)ad;
378 if(!JsonRpcRequest(ref Ad, "classifieds_info_query", serverURI, UUID.Random().ToString()))
379 {
380 remoteClient.SendAgentAlertMessage(
381 "Error getting classified info", false);
382 return;
383 }
384 ad = (UserClassifiedAdd) Ad;
385
386 if(ad.CreatorId == UUID.Zero)
387 return;
388
389 Vector3 globalPos = new Vector3();
390 Vector3.TryParse(ad.GlobalPos, out globalPos);
391
392 remoteClient.SendClassifiedInfoReply(ad.ClassifiedId, ad.CreatorId, (uint)ad.CreationDate, (uint)ad.ExpirationDate,
393 (uint)ad.Category, ad.Name, ad.Description, ad.ParcelId, (uint)ad.ParentEstate,
394 ad.SnapshotId, ad.SimName, globalPos, ad.ParcelName, ad.Flags, ad.Price);
395
396 }
397
398 /// <summary>
399 /// Classifieds info update.
400 /// </summary>
401 /// <param name='queryclassifiedID'>
402 /// Queryclassified I.
403 /// </param>
404 /// <param name='queryCategory'>
405 /// Query category.
406 /// </param>
407 /// <param name='queryName'>
408 /// Query name.
409 /// </param>
410 /// <param name='queryDescription'>
411 /// Query description.
412 /// </param>
413 /// <param name='queryParcelID'>
414 /// Query parcel I.
415 /// </param>
416 /// <param name='queryParentEstate'>
417 /// Query parent estate.
418 /// </param>
419 /// <param name='querySnapshotID'>
420 /// Query snapshot I.
421 /// </param>
422 /// <param name='queryGlobalPos'>
423 /// Query global position.
424 /// </param>
425 /// <param name='queryclassifiedFlags'>
426 /// Queryclassified flags.
427 /// </param>
428 /// <param name='queryclassifiedPrice'>
429 /// Queryclassified price.
430 /// </param>
431 /// <param name='remoteClient'>
432 /// Remote client.
433 /// </param>
434 public void ClassifiedInfoUpdate(UUID queryclassifiedID, uint queryCategory, string queryName, string queryDescription, UUID queryParcelID,
435 uint queryParentEstate, UUID querySnapshotID, Vector3 queryGlobalPos, byte queryclassifiedFlags,
436 int queryclassifiedPrice, IClientAPI remoteClient)
437 {
438 UserClassifiedAdd ad = new UserClassifiedAdd();
439
440 Scene s = (Scene) remoteClient.Scene;
441 Vector3 pos = remoteClient.SceneAgent.AbsolutePosition;
442 ILandObject land = s.LandChannel.GetLandObject(pos.X, pos.Y);
443 ScenePresence p = FindPresence(remoteClient.AgentId);
444
445 string serverURI = string.Empty;
446 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
447
448 if (land == null)
449 {
450 ad.ParcelName = string.Empty;
451 }
452 else
453 {
454 ad.ParcelName = land.LandData.Name;
455 }
456
457 ad.CreatorId = remoteClient.AgentId;
458 ad.ClassifiedId = queryclassifiedID;
459 ad.Category = Convert.ToInt32(queryCategory);
460 ad.Name = queryName;
461 ad.Description = queryDescription;
462 ad.ParentEstate = Convert.ToInt32(queryParentEstate);
463 ad.SnapshotId = querySnapshotID;
464 ad.SimName = remoteClient.Scene.RegionInfo.RegionName;
465 ad.GlobalPos = queryGlobalPos.ToString ();
466 ad.Flags = queryclassifiedFlags;
467 ad.Price = queryclassifiedPrice;
468 ad.ParcelId = p.currentParcelUUID;
469
470 object Ad = ad;
471
472 OSD.SerializeMembers(Ad);
473
474 if(!JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString()))
475 {
476 remoteClient.SendAgentAlertMessage(
477 "Error updating classified", false);
478 }
479 }
480
481 /// <summary>
482 /// Classifieds delete.
483 /// </summary>
484 /// <param name='queryClassifiedID'>
485 /// Query classified I.
486 /// </param>
487 /// <param name='remoteClient'>
488 /// Remote client.
489 /// </param>
490 public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient)
491 {
492 string serverURI = string.Empty;
493 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
494
495 UUID classifiedId;
496 OSDMap parameters= new OSDMap();
497 UUID.TryParse(queryClassifiedID.ToString(), out classifiedId);
498 parameters.Add("classifiedId", OSD.FromUUID(classifiedId));
499 OSD Params = (OSD)parameters;
500 if(!JsonRpcRequest(ref Params, "classified_delete", serverURI, UUID.Random().ToString()))
501 {
502 remoteClient.SendAgentAlertMessage(
503 "Error classified delete", false);
504 }
505
506 parameters = (OSDMap)Params;
507 }
508 #endregion Classified
509
510 #region Picks
511 /// <summary>
512 /// Handles the avatar picks request.
513 /// </summary>
514 /// <param name='sender'>
515 /// Sender.
516 /// </param>
517 /// <param name='method'>
518 /// Method.
519 /// </param>
520 /// <param name='args'>
521 /// Arguments.
522 /// </param>
523 public void PicksRequest(Object sender, string method, List<String> args)
524 {
525 if (!(sender is IClientAPI))
526 return;
527
528 IClientAPI remoteClient = (IClientAPI)sender;
529
530 UUID targetId;
531 UUID.TryParse(args[0], out targetId);
532
533 // Can't handle NPC yet...
534 ScenePresence p = FindPresence(targetId);
535
536 if (null != p)
537 {
538 if (p.PresenceType == PresenceType.Npc)
539 return;
540 }
541
542 string serverURI = string.Empty;
543 GetUserProfileServerURI(targetId, out serverURI);
544
545 Dictionary<UUID, string> picks = new Dictionary<UUID, string>();
546
547 OSDMap parameters= new OSDMap();
548 parameters.Add("creatorId", OSD.FromUUID(targetId));
549 OSD Params = (OSD)parameters;
550 if(!JsonRpcRequest(ref Params, "avatarpicksrequest", serverURI, UUID.Random().ToString()))
551 {
552 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks);
553 return;
554 }
555
556 parameters = (OSDMap)Params;
557
558 OSDArray list = (OSDArray)parameters["result"];
559
560 foreach(OSD map in list)
561 {
562 OSDMap m = (OSDMap)map;
563 UUID cid = m["pickuuid"].AsUUID();
564 string name = m["name"].AsString();
565
566 m_log.DebugFormat("[PROFILES]: PicksRequest {0}", name);
567
568 picks[cid] = name;
569 }
570 remoteClient.SendAvatarPicksReply(new UUID(args[0]), picks);
571 }
572
573 /// <summary>
574 /// Handles the pick info request.
575 /// </summary>
576 /// <param name='sender'>
577 /// Sender.
578 /// </param>
579 /// <param name='method'>
580 /// Method.
581 /// </param>
582 /// <param name='args'>
583 /// Arguments.
584 /// </param>
585 public void PickInfoRequest(Object sender, string method, List<String> args)
586 {
587 if (!(sender is IClientAPI))
588 return;
589
590 UUID targetID;
591 UUID.TryParse(args[0], out targetID);
592 string serverURI = string.Empty;
593 GetUserProfileServerURI(targetID, out serverURI);
594 IClientAPI remoteClient = (IClientAPI)sender;
595
596 UserProfilePick pick = new UserProfilePick();
597 UUID.TryParse(args[0], out pick.CreatorId);
598 UUID.TryParse(args[1], out pick.PickId);
599
600
601 object Pick = (object)pick;
602 if(!JsonRpcRequest(ref Pick, "pickinforequest", serverURI, UUID.Random().ToString()))
603 {
604 remoteClient.SendAgentAlertMessage(
605 "Error selecting pick", false);
606 }
607 pick = (UserProfilePick) Pick;
608 if(pick.SnapshotId == UUID.Zero)
609 {
610 // In case of a new UserPick, the data may not be ready and we would send wrong data, skip it...
611 m_log.DebugFormat("[PROFILES]: PickInfoRequest: SnapshotID is {0}", UUID.Zero.ToString());
612 return;
613 }
614
615 Vector3 globalPos;
616 Vector3.TryParse(pick.GlobalPos,out globalPos);
617
618 m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString());
619
620 remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name,
621 pick.Desc,pick.SnapshotId,pick.User,pick.OriginalName,pick.SimName,
622 globalPos,pick.SortOrder,pick.Enabled);
623 }
624
625 /// <summary>
626 /// Updates the userpicks
627 /// </summary>
628 /// <param name='remoteClient'>
629 /// Remote client.
630 /// </param>
631 /// <param name='pickID'>
632 /// Pick I.
633 /// </param>
634 /// <param name='creatorID'>
635 /// the creator of the pick
636 /// </param>
637 /// <param name='topPick'>
638 /// Top pick.
639 /// </param>
640 /// <param name='name'>
641 /// Name.
642 /// </param>
643 /// <param name='desc'>
644 /// Desc.
645 /// </param>
646 /// <param name='snapshotID'>
647 /// Snapshot I.
648 /// </param>
649 /// <param name='sortOrder'>
650 /// Sort order.
651 /// </param>
652 /// <param name='enabled'>
653 /// Enabled.
654 /// </param>
655 public void PickInfoUpdate(IClientAPI remoteClient, UUID pickID, UUID creatorID, bool topPick, string name, string desc, UUID snapshotID, int sortOrder, bool enabled)
656 {
657
658 m_log.DebugFormat("[PROFILES]: Start PickInfoUpdate Name: {0} PickId: {1} SnapshotId: {2}", name, pickID.ToString(), snapshotID.ToString());
659 UserProfilePick pick = new UserProfilePick();
660 string serverURI = string.Empty;
661 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
662 ScenePresence p = FindPresence(remoteClient.AgentId);
663
664 Vector3 avaPos = p.AbsolutePosition;
665 // Getting the global position for the Avatar
666 Vector3 posGlobal = new Vector3(remoteClient.Scene.RegionInfo.RegionLocX*Constants.RegionSize + avaPos.X,
667 remoteClient.Scene.RegionInfo.RegionLocY*Constants.RegionSize + avaPos.Y,
668 avaPos.Z);
669
670 string landOwnerName = string.Empty;
671 ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y);
672 if(land.LandData.IsGroupOwned)
673 {
674 IGroupsModule groupMod = p.Scene.RequestModuleInterface<IGroupsModule>();
675 UUID groupId = land.LandData.GroupID;
676 GroupRecord groupRecord = groupMod.GetGroupRecord(groupId);
677 landOwnerName = groupRecord.GroupName;
678 }
679 else
680 {
681 IUserAccountService accounts = p.Scene.RequestModuleInterface<IUserAccountService>();
682 UserAccount user = accounts.GetUserAccount(p.Scene.RegionInfo.ScopeID, land.LandData.OwnerID);
683 landOwnerName = user.Name;
684 }
685
686 pick.PickId = pickID;
687 pick.CreatorId = creatorID;
688 pick.TopPick = topPick;
689 pick.Name = name;
690 pick.Desc = desc;
691 pick.ParcelId = p.currentParcelUUID;
692 pick.SnapshotId = snapshotID;
693 pick.User = landOwnerName;
694 pick.SimName = remoteClient.Scene.RegionInfo.RegionName;
695 pick.GlobalPos = posGlobal.ToString();
696 pick.SortOrder = sortOrder;
697 pick.Enabled = enabled;
698
699 object Pick = (object)pick;
700 if(!JsonRpcRequest(ref Pick, "picks_update", serverURI, UUID.Random().ToString()))
701 {
702 remoteClient.SendAgentAlertMessage(
703 "Error updating pick", false);
704 }
705
706 m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString());
707 }
708
709 /// <summary>
710 /// Delete a Pick
711 /// </summary>
712 /// <param name='remoteClient'>
713 /// Remote client.
714 /// </param>
715 /// <param name='queryPickID'>
716 /// Query pick I.
717 /// </param>
718 public void PickDelete(IClientAPI remoteClient, UUID queryPickID)
719 {
720 string serverURI = string.Empty;
721 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
722
723 OSDMap parameters= new OSDMap();
724 parameters.Add("pickId", OSD.FromUUID(queryPickID));
725 OSD Params = (OSD)parameters;
726 if(!JsonRpcRequest(ref Params, "picks_delete", serverURI, UUID.Random().ToString()))
727 {
728 remoteClient.SendAgentAlertMessage(
729 "Error picks delete", false);
730 }
731 }
732 #endregion Picks
733
734 #region Notes
735 /// <summary>
736 /// Handles the avatar notes request.
737 /// </summary>
738 /// <param name='sender'>
739 /// Sender.
740 /// </param>
741 /// <param name='method'>
742 /// Method.
743 /// </param>
744 /// <param name='args'>
745 /// Arguments.
746 /// </param>
747 public void NotesRequest(Object sender, string method, List<String> args)
748 {
749 UserProfileNotes note = new UserProfileNotes();
750
751 if (!(sender is IClientAPI))
752 return;
753
754 IClientAPI remoteClient = (IClientAPI)sender;
755 string serverURI = string.Empty;
756 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
757 note.UserId = remoteClient.AgentId;
758 UUID.TryParse(args[0], out note.TargetId);
759
760 object Note = (object)note;
761 if(!JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString()))
762 {
763 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
764 return;
765 }
766 note = (UserProfileNotes) Note;
767
768 remoteClient.SendAvatarNotesReply(note.TargetId, note.Notes);
769 }
770
771 /// <summary>
772 /// Avatars the notes update.
773 /// </summary>
774 /// <param name='remoteClient'>
775 /// Remote client.
776 /// </param>
777 /// <param name='queryTargetID'>
778 /// Query target I.
779 /// </param>
780 /// <param name='queryNotes'>
781 /// Query notes.
782 /// </param>
783 public void NotesUpdate(IClientAPI remoteClient, UUID queryTargetID, string queryNotes)
784 {
785 UserProfileNotes note = new UserProfileNotes();
786
787 note.UserId = remoteClient.AgentId;
788 note.TargetId = queryTargetID;
789 note.Notes = queryNotes;
790
791 string serverURI = string.Empty;
792 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
793
794 object Note = note;
795 if(!JsonRpcRequest(ref Note, "avatar_notes_update", serverURI, UUID.Random().ToString()))
796 {
797 return;
798 }
799 }
800 #endregion Notes
801
802 #region Avatar Properties
803 /// <summary>
804 /// Update the avatars interests .
805 /// </summary>
806 /// <param name='remoteClient'>
807 /// Remote client.
808 /// </param>
809 /// <param name='wantmask'>
810 /// Wantmask.
811 /// </param>
812 /// <param name='wanttext'>
813 /// Wanttext.
814 /// </param>
815 /// <param name='skillsmask'>
816 /// Skillsmask.
817 /// </param>
818 /// <param name='skillstext'>
819 /// Skillstext.
820 /// </param>
821 /// <param name='languages'>
822 /// Languages.
823 /// </param>
824 public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages)
825 {
826 UserProfileProperties prop = new UserProfileProperties();
827
828 prop.UserId = remoteClient.AgentId;
829 prop.WantToMask = (int)wantmask;
830 prop.WantToText = wanttext;
831 prop.SkillsMask = (int)skillsmask;
832 prop.SkillsText = skillstext;
833 prop.Language = languages;
834
835 string serverURI = string.Empty;
836 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
837
838 object Param = prop;
839 if(!JsonRpcRequest(ref Param, "avatar_interests_update", serverURI, UUID.Random().ToString()))
840 {
841 remoteClient.SendAgentAlertMessage(
842 "Error updating interests", false);
843 }
844 }
845
846 public void RequestAvatarProperties(IClientAPI remoteClient, UUID avatarID)
847 {
848 if ( String.IsNullOrEmpty(avatarID.ToString()) || String.IsNullOrEmpty(remoteClient.AgentId.ToString()))
849 {
850 // Looking for a reason that some viewers are sending null Id's
851 m_log.DebugFormat("[PROFILES]: This should not happen remoteClient.AgentId {0} - avatarID {1}", remoteClient.AgentId, avatarID);
852 return;
853 }
854
855 // Can't handle NPC yet...
856 ScenePresence p = FindPresence(avatarID);
857
858 if (null != p)
859 {
860 if (p.PresenceType == PresenceType.Npc)
861 return;
862 }
863
864 string serverURI = string.Empty;
865 bool foreign = GetUserProfileServerURI(avatarID, out serverURI);
866
867 UserAccount account = null;
868 Dictionary<string,object> userInfo;
869
870 if (!foreign)
871 {
872 account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, avatarID);
873 }
874 else
875 {
876 userInfo = new Dictionary<string, object>();
877 }
878
879 Byte[] charterMember = new Byte[1];
880 string born = String.Empty;
881 uint flags = 0x00;
882
883 if (null != account)
884 {
885 if (account.UserTitle == "")
886 {
887 charterMember[0] = (Byte)((account.UserFlags & 0xf00) >> 8);
888 }
889 else
890 {
891 charterMember = Utils.StringToBytes(account.UserTitle);
892 }
893
894 born = Util.ToDateTime(account.Created).ToString(
895 "M/d/yyyy", CultureInfo.InvariantCulture);
896 flags = (uint)(account.UserFlags & 0xff);
897 }
898 else
899 {
900 if (GetUserAccountData(avatarID, out userInfo) == true)
901 {
902 if ((string)userInfo["user_title"] == "")
903 {
904 charterMember[0] = (Byte)(((Byte)userInfo["user_flags"] & 0xf00) >> 8);
905 }
906 else
907 {
908 charterMember = Utils.StringToBytes((string)userInfo["user_title"]);
909 }
910
911 int val_born = (int)userInfo["user_created"];
912 born = Util.ToDateTime(val_born).ToString(
913 "M/d/yyyy", CultureInfo.InvariantCulture);
914
915 // picky, picky
916 int val_flags = (int)userInfo["user_flags"];
917 flags = (uint)(val_flags & 0xff);
918 }
919 }
920
921 UserProfileProperties props = new UserProfileProperties();
922 string result = string.Empty;
923
924 props.UserId = avatarID;
925 GetProfileData(ref props, out result);
926
927 remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, charterMember , props.FirstLifeText, flags,
928 props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
929
930
931 remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask,
932 props.SkillsText, props.Language);
933 }
934
935 /// <summary>
936 /// Updates the avatar properties.
937 /// </summary>
938 /// <param name='remoteClient'>
939 /// Remote client.
940 /// </param>
941 /// <param name='newProfile'>
942 /// New profile.
943 /// </param>
944 public void AvatarPropertiesUpdate(IClientAPI remoteClient, UserProfileData newProfile)
945 {
946 if (remoteClient.AgentId == newProfile.ID)
947 {
948 UserProfileProperties prop = new UserProfileProperties();
949
950 prop.UserId = remoteClient.AgentId;
951 prop.WebUrl = newProfile.ProfileUrl;
952 prop.ImageId = newProfile.Image;
953 prop.AboutText = newProfile.AboutText;
954 prop.FirstLifeImageId = newProfile.FirstLifeImage;
955 prop.FirstLifeText = newProfile.FirstLifeAboutText;
956
957 string serverURI = string.Empty;
958 GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
959
960 object Prop = prop;
961
962 if(!JsonRpcRequest(ref Prop, "avatar_properties_update", serverURI, UUID.Random().ToString()))
963 {
964 remoteClient.SendAgentAlertMessage(
965 "Error updating properties", false);
966 }
967
968 RequestAvatarProperties(remoteClient, newProfile.ID);
969 }
970 }
971
972 /// <summary>
973 /// Gets the profile data.
974 /// </summary>
975 /// <returns>
976 /// The profile data.
977 /// </returns>
978 /// <param name='userID'>
979 /// User I.
980 /// </param>
981 bool GetProfileData(ref UserProfileProperties properties, out string message)
982 {
983 // Can't handle NPC yet...
984 ScenePresence p = FindPresence(properties.UserId);
985
986 if (null != p)
987 {
988 if (p.PresenceType == PresenceType.Npc)
989 {
990 message = "Id points to NPC";
991 return false;
992 }
993 }
994
995 string serverURI = string.Empty;
996 GetUserProfileServerURI(properties.UserId, out serverURI);
997
998 // This is checking a friend on the home grid
999 // Not HG friend
1000 if ( String.IsNullOrEmpty(serverURI))
1001 {
1002 message = "No Presence - foreign friend";
1003 return false;
1004 }
1005
1006 object Prop = (object)properties;
1007 JsonRpcRequest(ref Prop, "avatar_properties_request", serverURI, UUID.Random().ToString());
1008 properties = (UserProfileProperties)Prop;
1009
1010 message = "Success";
1011 return true;
1012 }
1013 #endregion Avatar Properties
1014
1015 #region Utils
1016 bool GetImageAssets(UUID avatarId)
1017 {
1018 string profileServerURI = string.Empty;
1019 string assetServerURI = string.Empty;
1020
1021 bool foreign = GetUserProfileServerURI(avatarId, out profileServerURI);
1022
1023 if(!foreign)
1024 return true;
1025
1026 assetServerURI = UserManagementModule.GetUserServerURL(avatarId, "AssetServerURI");
1027
1028 OSDMap parameters= new OSDMap();
1029 parameters.Add("avatarId", OSD.FromUUID(avatarId));
1030 OSD Params = (OSD)parameters;
1031 if(!JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString()))
1032 {
1033 return false;
1034 }
1035
1036 parameters = (OSDMap)Params;
1037
1038 OSDArray list = (OSDArray)parameters["result"];
1039
1040 foreach(OSD asset in list)
1041 {
1042 OSDString assetId = (OSDString)asset;
1043
1044 Scene.AssetService.Get(string.Format("{0}/{1}",assetServerURI, assetId.AsString()));
1045 }
1046 return true;
1047 }
1048
1049 /// <summary>
1050 /// Gets the user account data.
1051 /// </summary>
1052 /// <returns>
1053 /// The user profile data.
1054 /// </returns>
1055 /// <param name='userID'>
1056 /// If set to <c>true</c> user I.
1057 /// </param>
1058 /// <param name='userInfo'>
1059 /// If set to <c>true</c> user info.
1060 /// </param>
1061 bool GetUserAccountData(UUID userID, out Dictionary<string, object> userInfo)
1062 {
1063 Dictionary<string,object> info = new Dictionary<string, object>();
1064
1065 if (UserManagementModule.IsLocalGridUser(userID))
1066 {
1067 // Is local
1068 IUserAccountService uas = Scene.UserAccountService;
1069 UserAccount account = uas.GetUserAccount(Scene.RegionInfo.ScopeID, userID);
1070
1071 info["user_flags"] = account.UserFlags;
1072 info["user_created"] = account.Created;
1073
1074 if (!String.IsNullOrEmpty(account.UserTitle))
1075 info["user_title"] = account.UserTitle;
1076 else
1077 info["user_title"] = "";
1078
1079 userInfo = info;
1080
1081 return false;
1082 }
1083 else
1084 {
1085 // Is Foreign
1086 string home_url = UserManagementModule.GetUserServerURL(userID, "HomeURI");
1087
1088 if (String.IsNullOrEmpty(home_url))
1089 {
1090 info["user_flags"] = 0;
1091 info["user_created"] = 0;
1092 info["user_title"] = "Unavailable";
1093
1094 userInfo = info;
1095 return true;
1096 }
1097
1098 UserAgentServiceConnector uConn = new UserAgentServiceConnector(home_url);
1099
1100 Dictionary<string, object> account = uConn.GetUserInfo(userID);
1101
1102 if (account.Count > 0)
1103 {
1104 if (account.ContainsKey("user_flags"))
1105 info["user_flags"] = account["user_flags"];
1106 else
1107 info["user_flags"] = "";
1108
1109 if (account.ContainsKey("user_created"))
1110 info["user_created"] = account["user_created"];
1111 else
1112 info["user_created"] = "";
1113
1114 info["user_title"] = "HG Visitor";
1115 }
1116 else
1117 {
1118 info["user_flags"] = 0;
1119 info["user_created"] = 0;
1120 info["user_title"] = "HG Visitor";
1121 }
1122 userInfo = info;
1123 return true;
1124 }
1125 }
1126
1127 /// <summary>
1128 /// Gets the user profile server UR.
1129 /// </summary>
1130 /// <returns>
1131 /// The user profile server UR.
1132 /// </returns>
1133 /// <param name='userID'>
1134 /// If set to <c>true</c> user I.
1135 /// </param>
1136 /// <param name='serverURI'>
1137 /// If set to <c>true</c> server UR.
1138 /// </param>
1139 bool GetUserProfileServerURI(UUID userID, out string serverURI)
1140 {
1141 bool local;
1142 local = UserManagementModule.IsLocalGridUser(userID);
1143
1144 if (!local)
1145 {
1146 serverURI = UserManagementModule.GetUserServerURL(userID, "ProfileServerURI");
1147 // Is Foreign
1148 return true;
1149 }
1150 else
1151 {
1152 serverURI = ProfileServerUri;
1153 // Is local
1154 return false;
1155 }
1156 }
1157
1158 /// <summary>
1159 /// Finds the presence.
1160 /// </summary>
1161 /// <returns>
1162 /// The presence.
1163 /// </returns>
1164 /// <param name='clientID'>
1165 /// Client I.
1166 /// </param>
1167 ScenePresence FindPresence(UUID clientID)
1168 {
1169 ScenePresence p;
1170
1171 p = Scene.GetScenePresence(clientID);
1172 if (p != null && !p.IsChildAgent)
1173 return p;
1174
1175 return null;
1176 }
1177 #endregion Util
1178
1179 #region Web Util
1180 /// <summary>
1181 /// Sends json-rpc request with a serializable type.
1182 /// </summary>
1183 /// <returns>
1184 /// OSD Map.
1185 /// </returns>
1186 /// <param name='parameters'>
1187 /// Serializable type .
1188 /// </param>
1189 /// <param name='method'>
1190 /// Json-rpc method to call.
1191 /// </param>
1192 /// <param name='uri'>
1193 /// URI of json-rpc service.
1194 /// </param>
1195 /// <param name='jsonId'>
1196 /// Id for our call.
1197 /// </param>
1198 bool JsonRpcRequest(ref object parameters, string method, string uri, string jsonId)
1199 {
1200 if (jsonId == null)
1201 throw new ArgumentNullException ("jsonId");
1202 if (uri == null)
1203 throw new ArgumentNullException ("uri");
1204 if (method == null)
1205 throw new ArgumentNullException ("method");
1206 if (parameters == null)
1207 throw new ArgumentNullException ("parameters");
1208
1209 // Prep our payload
1210 OSDMap json = new OSDMap();
1211
1212 json.Add("jsonrpc", OSD.FromString("2.0"));
1213 json.Add("id", OSD.FromString(jsonId));
1214 json.Add("method", OSD.FromString(method));
1215
1216 json.Add("params", OSD.SerializeMembers(parameters));
1217
1218 string jsonRequestData = OSDParser.SerializeJsonString(json);
1219 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1220
1221 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1222
1223 webRequest.ContentType = "application/json-rpc";
1224 webRequest.Method = "POST";
1225
1226 Stream dataStream = webRequest.GetRequestStream();
1227 dataStream.Write(content, 0, content.Length);
1228 dataStream.Close();
1229
1230 WebResponse webResponse = null;
1231 try
1232 {
1233 webResponse = webRequest.GetResponse();
1234 }
1235 catch (WebException e)
1236 {
1237 Console.WriteLine("Web Error" + e.Message);
1238 Console.WriteLine ("Please check input");
1239 return false;
1240 }
1241
1242 Stream rstream = webResponse.GetResponseStream();
1243
1244 OSDMap mret = new OSDMap();
1245 try
1246 {
1247 mret = (OSDMap)OSDParser.DeserializeJson(rstream);
1248 }
1249 catch (Exception e)
1250 {
1251 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1252 return false;
1253 }
1254
1255
1256 if (mret.ContainsKey("error"))
1257 return false;
1258
1259 // get params...
1260 OSD.DeserializeMembers(ref parameters, (OSDMap) mret["result"]);
1261 return true;
1262 }
1263
1264 /// <summary>
1265 /// Sends json-rpc request with OSD parameter.
1266 /// </summary>
1267 /// <returns>
1268 /// The rpc request.
1269 /// </returns>
1270 /// <param name='data'>
1271 /// data - incoming as parameters, outgong as result/error
1272 /// </param>
1273 /// <param name='method'>
1274 /// Json-rpc method to call.
1275 /// </param>
1276 /// <param name='uri'>
1277 /// URI of json-rpc service.
1278 /// </param>
1279 /// <param name='jsonId'>
1280 /// If set to <c>true</c> json identifier.
1281 /// </param>
1282 bool JsonRpcRequest(ref OSD data, string method, string uri, string jsonId)
1283 {
1284 OSDMap map = new OSDMap();
1285
1286 map["jsonrpc"] = "2.0";
1287 if(string.IsNullOrEmpty(jsonId))
1288 map["id"] = UUID.Random().ToString();
1289 else
1290 map["id"] = jsonId;
1291
1292 map["method"] = method;
1293 map["params"] = data;
1294
1295 string jsonRequestData = OSDParser.SerializeJsonString(map);
1296 byte[] content = Encoding.UTF8.GetBytes(jsonRequestData);
1297
1298 HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
1299 webRequest.ContentType = "application/json-rpc";
1300 webRequest.Method = "POST";
1301
1302 Stream dataStream = webRequest.GetRequestStream();
1303 dataStream.Write(content, 0, content.Length);
1304 dataStream.Close();
1305
1306 WebResponse webResponse = null;
1307 try
1308 {
1309 webResponse = webRequest.GetResponse();
1310 }
1311 catch (WebException e)
1312 {
1313 Console.WriteLine("Web Error" + e.Message);
1314 Console.WriteLine ("Please check input");
1315 return false;
1316 }
1317
1318 Stream rstream = webResponse.GetResponseStream();
1319
1320 OSDMap response = new OSDMap();
1321 try
1322 {
1323 response = (OSDMap)OSDParser.DeserializeJson(rstream);
1324 }
1325 catch (Exception e)
1326 {
1327 m_log.DebugFormat("[PROFILES]: JsonRpcRequest Error {0} - remote user with legacy profiles?", e.Message);
1328 return false;
1329 }
1330
1331 if(response.ContainsKey("error"))
1332 {
1333 data = response["error"];
1334 return false;
1335 }
1336
1337 data = response;
1338
1339 return true;
1340 }
1341 #endregion Web Util
1342 }
1343} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index fff86d5..de8925d 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Linq;
31using System.Reflection; 32using System.Reflection;
32using System.Text; 33using System.Text;
33using log4net; 34using log4net;
@@ -37,6 +38,7 @@ using OpenMetaverse;
37using OpenSim.Framework; 38using OpenSim.Framework;
38using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
39using OpenSim.Framework.Servers; 40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
42using Caps=OpenSim.Framework.Capabilities.Caps; 44using Caps=OpenSim.Framework.Capabilities.Caps;
@@ -57,8 +59,9 @@ namespace OpenSim.Region.CoreModules.Framework
57 /// </summary> 59 /// </summary>
58 protected Dictionary<uint, Caps> m_capsObjects = new Dictionary<uint, Caps>(); 60 protected Dictionary<uint, Caps> m_capsObjects = new Dictionary<uint, Caps>();
59 61
60 protected Dictionary<UUID, string> capsPaths = new Dictionary<UUID, string>(); 62 protected Dictionary<UUID, string> m_capsPaths = new Dictionary<UUID, string>();
61 protected Dictionary<UUID, Dictionary<ulong, string>> childrenSeeds 63
64 protected Dictionary<UUID, Dictionary<ulong, string>> m_childrenSeeds
62 = new Dictionary<UUID, Dictionary<ulong, string>>(); 65 = new Dictionary<UUID, Dictionary<ulong, string>>();
63 66
64 public void Initialise(IConfigSource source) 67 public void Initialise(IConfigSource source)
@@ -70,9 +73,24 @@ namespace OpenSim.Region.CoreModules.Framework
70 m_scene = scene; 73 m_scene = scene;
71 m_scene.RegisterModuleInterface<ICapabilitiesModule>(this); 74 m_scene.RegisterModuleInterface<ICapabilitiesModule>(this);
72 75
73 MainConsole.Instance.Commands.AddCommand("Comms", false, "show caps", 76 MainConsole.Instance.Commands.AddCommand(
74 "show caps", 77 "Comms", false, "show caps list",
75 "Shows all registered capabilities for users", HandleShowCapsCommand); 78 "show caps list",
79 "Shows list of registered capabilities for users.", HandleShowCapsListCommand);
80
81 MainConsole.Instance.Commands.AddCommand(
82 "Comms", false, "show caps stats by user",
83 "show caps stats by user [<first-name> <last-name>]",
84 "Shows statistics on capabilities use by user.",
85 "If a user name is given, then prints a detailed breakdown of caps use ordered by number of requests received.",
86 HandleShowCapsStatsByUserCommand);
87
88 MainConsole.Instance.Commands.AddCommand(
89 "Comms", false, "show caps stats by cap",
90 "show caps stats by cap [<cap-name>]",
91 "Shows statistics on capabilities use by capability.",
92 "If a capability name is given, then prints a detailed breakdown of use by each user.",
93 HandleShowCapsStatsByCapCommand);
76 } 94 }
77 95
78 public void RegionLoaded(Scene scene) 96 public void RegionLoaded(Scene scene)
@@ -106,35 +124,38 @@ namespace OpenSim.Region.CoreModules.Framework
106 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags)) 124 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags))
107 return; 125 return;
108 126
127 Caps caps;
109 String capsObjectPath = GetCapsPath(agentId); 128 String capsObjectPath = GetCapsPath(agentId);
110 129
111 if (m_capsObjects.ContainsKey(circuitCode)) 130 lock (m_capsObjects)
112 { 131 {
113 Caps oldCaps = m_capsObjects[circuitCode]; 132 if (m_capsObjects.ContainsKey(circuitCode))
114 133 {
115 m_log.DebugFormat( 134 Caps oldCaps = m_capsObjects[circuitCode];
116 "[CAPS]: Recreating caps for agent {0}. Old caps path {1}, new caps path {2}. ", 135
117 agentId, oldCaps.CapsObjectPath, capsObjectPath); 136 //m_log.WarnFormat(
118 // This should not happen. The caller code is confused. We need to fix that. 137 // "[CAPS]: Recreating caps for agent {0} in region {1}. Old caps path {2}, new caps path {3}. ",
119 // CAPs can never be reregistered, or the client will be confused. 138 // agentId, m_scene.RegionInfo.RegionName, oldCaps.CapsObjectPath, capsObjectPath);
120 // Hence this return here. 139 }
121 //return;
122 }
123
124 Caps caps = new Caps(MainServer.Instance, m_scene.RegionInfo.ExternalHostName,
125 (MainServer.Instance == null) ? 0: MainServer.Instance.Port,
126 capsObjectPath, agentId, m_scene.RegionInfo.RegionName);
127 140
128 m_capsObjects[circuitCode] = caps; 141 caps = new Caps(MainServer.Instance, m_scene.RegionInfo.ExternalHostName,
142 (MainServer.Instance == null) ? 0: MainServer.Instance.Port,
143 capsObjectPath, agentId, m_scene.RegionInfo.RegionName);
129 144
145 m_capsObjects[circuitCode] = caps;
146 }
130 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps); 147 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps);
131 } 148 }
132 149
133 public void RemoveCaps(UUID agentId, uint circuitCode) 150 public void RemoveCaps(UUID agentId, uint circuitCode)
134 { 151 {
135 if (childrenSeeds.ContainsKey(agentId)) 152 m_log.DebugFormat("[CAPS]: Remove caps for agent {0} in region {1}", agentId, m_scene.RegionInfo.RegionName);
153 lock (m_childrenSeeds)
136 { 154 {
137 childrenSeeds.Remove(agentId); 155 if (m_childrenSeeds.ContainsKey(agentId))
156 {
157 m_childrenSeeds.Remove(agentId);
158 }
138 } 159 }
139 160
140 lock (m_capsObjects) 161 lock (m_capsObjects)
@@ -180,16 +201,22 @@ namespace OpenSim.Region.CoreModules.Framework
180 201
181 public void SetAgentCapsSeeds(AgentCircuitData agent) 202 public void SetAgentCapsSeeds(AgentCircuitData agent)
182 { 203 {
183 capsPaths[agent.AgentID] = agent.CapsPath; 204 lock (m_capsPaths)
184 childrenSeeds[agent.AgentID] 205 m_capsPaths[agent.AgentID] = agent.CapsPath;
185 = ((agent.ChildrenCapSeeds == null) ? new Dictionary<ulong, string>() : agent.ChildrenCapSeeds); 206
207 lock (m_childrenSeeds)
208 m_childrenSeeds[agent.AgentID]
209 = ((agent.ChildrenCapSeeds == null) ? new Dictionary<ulong, string>() : agent.ChildrenCapSeeds);
186 } 210 }
187 211
188 public string GetCapsPath(UUID agentId) 212 public string GetCapsPath(UUID agentId)
189 { 213 {
190 if (capsPaths.ContainsKey(agentId)) 214 lock (m_capsPaths)
191 { 215 {
192 return capsPaths[agentId]; 216 if (m_capsPaths.ContainsKey(agentId))
217 {
218 return m_capsPaths[agentId];
219 }
193 } 220 }
194 221
195 return null; 222 return null;
@@ -198,17 +225,24 @@ namespace OpenSim.Region.CoreModules.Framework
198 public Dictionary<ulong, string> GetChildrenSeeds(UUID agentID) 225 public Dictionary<ulong, string> GetChildrenSeeds(UUID agentID)
199 { 226 {
200 Dictionary<ulong, string> seeds = null; 227 Dictionary<ulong, string> seeds = null;
201 if (childrenSeeds.TryGetValue(agentID, out seeds)) 228
202 return seeds; 229 lock (m_childrenSeeds)
230 if (m_childrenSeeds.TryGetValue(agentID, out seeds))
231 return seeds;
232
203 return new Dictionary<ulong, string>(); 233 return new Dictionary<ulong, string>();
204 } 234 }
205 235
206 public void DropChildSeed(UUID agentID, ulong handle) 236 public void DropChildSeed(UUID agentID, ulong handle)
207 { 237 {
208 Dictionary<ulong, string> seeds; 238 Dictionary<ulong, string> seeds;
209 if (childrenSeeds.TryGetValue(agentID, out seeds)) 239
240 lock (m_childrenSeeds)
210 { 241 {
211 seeds.Remove(handle); 242 if (m_childrenSeeds.TryGetValue(agentID, out seeds))
243 {
244 seeds.Remove(handle);
245 }
212 } 246 }
213 } 247 }
214 248
@@ -216,53 +250,339 @@ namespace OpenSim.Region.CoreModules.Framework
216 { 250 {
217 Dictionary<ulong, string> seeds; 251 Dictionary<ulong, string> seeds;
218 string returnval; 252 string returnval;
219 if (childrenSeeds.TryGetValue(agentID, out seeds)) 253
254 lock (m_childrenSeeds)
220 { 255 {
221 if (seeds.TryGetValue(handle, out returnval)) 256 if (m_childrenSeeds.TryGetValue(agentID, out seeds))
222 return returnval; 257 {
258 if (seeds.TryGetValue(handle, out returnval))
259 return returnval;
260 }
223 } 261 }
262
224 return null; 263 return null;
225 } 264 }
226 265
227 public void SetChildrenSeed(UUID agentID, Dictionary<ulong, string> seeds) 266 public void SetChildrenSeed(UUID agentID, Dictionary<ulong, string> seeds)
228 { 267 {
229 //m_log.DebugFormat(" !!! Setting child seeds in {0} to {1}", m_scene.RegionInfo.RegionName, seeds.Count); 268 //m_log.DebugFormat(" !!! Setting child seeds in {0} to {1}", m_scene.RegionInfo.RegionName, seeds.Count);
230 childrenSeeds[agentID] = seeds; 269
270 lock (m_childrenSeeds)
271 m_childrenSeeds[agentID] = seeds;
231 } 272 }
232 273
233 public void DumpChildrenSeeds(UUID agentID) 274 public void DumpChildrenSeeds(UUID agentID)
234 { 275 {
235 m_log.Info("================ ChildrenSeed "+m_scene.RegionInfo.RegionName+" ================"); 276 m_log.Info("================ ChildrenSeed "+m_scene.RegionInfo.RegionName+" ================");
236 foreach (KeyValuePair<ulong, string> kvp in childrenSeeds[agentID]) 277
278 lock (m_childrenSeeds)
279 {
280 foreach (KeyValuePair<ulong, string> kvp in m_childrenSeeds[agentID])
281 {
282 uint x, y;
283 Utils.LongToUInts(kvp.Key, out x, out y);
284 x = x / Constants.RegionSize;
285 y = y / Constants.RegionSize;
286 m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
287 }
288 }
289 }
290
291 private void HandleShowCapsListCommand(string module, string[] cmdParams)
292 {
293 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
294 return;
295
296 StringBuilder capsReport = new StringBuilder();
297 capsReport.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName);
298
299 lock (m_capsObjects)
237 { 300 {
238 uint x, y; 301 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects)
239 Utils.LongToUInts(kvp.Key, out x, out y); 302 {
240 x = x / Constants.RegionSize; 303 capsReport.AppendFormat("** Circuit {0}:\n", kvp.Key);
241 y = y / Constants.RegionSize; 304 Caps caps = kvp.Value;
242 m_log.Info(" >> "+x+", "+y+": "+kvp.Value); 305
306 for (IDictionaryEnumerator kvp2 = caps.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); )
307 {
308 Uri uri = new Uri(kvp2.Value.ToString());
309 capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery);
310 }
311
312 foreach (KeyValuePair<string, PollServiceEventArgs> kvp2 in caps.GetPollHandlers())
313 capsReport.AppendFormat(m_showCapsCommandFormat, kvp2.Key, kvp2.Value.Url);
314
315 foreach (KeyValuePair<string, string> kvp3 in caps.ExternalCapsHandlers)
316 capsReport.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value);
317 }
243 } 318 }
319
320 MainConsole.Instance.Output(capsReport.ToString());
244 } 321 }
245 322
246 private void HandleShowCapsCommand(string module, string[] cmdparams) 323 private void HandleShowCapsStatsByCapCommand(string module, string[] cmdParams)
247 { 324 {
248 StringBuilder caps = new StringBuilder(); 325 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
249 caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); 326 return;
327
328 if (cmdParams.Length != 5 && cmdParams.Length != 6)
329 {
330 MainConsole.Instance.Output("Usage: show caps stats by cap [<cap-name>]");
331 return;
332 }
333
334 StringBuilder sb = new StringBuilder();
335 sb.AppendFormat("Region {0}:\n", m_scene.Name);
336
337 if (cmdParams.Length == 5)
338 {
339 BuildSummaryStatsByCapReport(sb);
340 }
341 else if (cmdParams.Length == 6)
342 {
343 BuildDetailedStatsByCapReport(sb, cmdParams[5]);
344 }
345
346 MainConsole.Instance.Output(sb.ToString());
347 }
348
349 private void BuildDetailedStatsByCapReport(StringBuilder sb, string capName)
350 {
351 /*
352 sb.AppendFormat("Capability name {0}\n", capName);
353
354 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
355 cdt.AddColumn("User Name", 34);
356 cdt.AddColumn("Req Received", 12);
357 cdt.AddColumn("Req Handled", 12);
358 cdt.Indent = 2;
359
360 Dictionary<string, int> receivedStats = new Dictionary<string, int>();
361 Dictionary<string, int> handledStats = new Dictionary<string, int>();
362
363 m_scene.ForEachScenePresence(
364 sp =>
365 {
366 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
250 367
251 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects) 368 if (caps == null)
369 return;
370
371 Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers();
372
373 IRequestHandler reqHandler;
374 if (capsHandlers.TryGetValue(capName, out reqHandler))
375 {
376 receivedStats[sp.Name] = reqHandler.RequestsReceived;
377 handledStats[sp.Name] = reqHandler.RequestsHandled;
378 }
379 else
380 {
381 PollServiceEventArgs pollHandler = null;
382 if (caps.TryGetPollHandler(capName, out pollHandler))
383 {
384 receivedStats[sp.Name] = pollHandler.RequestsReceived;
385 handledStats[sp.Name] = pollHandler.RequestsHandled;
386 }
387 }
388 }
389 );
390
391 foreach (KeyValuePair<string, int> kvp in receivedStats.OrderByDescending(kp => kp.Value))
252 { 392 {
253 caps.AppendFormat("** Circuit {0}:\n", kvp.Key); 393 cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]);
394 }
395
396 sb.Append(cdt.ToString());
397 */
398 }
399
400 private void BuildSummaryStatsByCapReport(StringBuilder sb)
401 {
402 /*
403 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
404 cdt.AddColumn("Name", 34);
405 cdt.AddColumn("Req Received", 12);
406 cdt.AddColumn("Req Handled", 12);
407 cdt.Indent = 2;
408
409 Dictionary<string, int> receivedStats = new Dictionary<string, int>();
410 Dictionary<string, int> handledStats = new Dictionary<string, int>();
254 411
255 for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false, null).GetEnumerator(); kvp2.MoveNext(); ) 412 m_scene.ForEachScenePresence(
413 sp =>
256 { 414 {
257 Uri uri = new Uri(kvp2.Value.ToString()); 415 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
258 caps.AppendFormat(m_showCapsCommandFormat, kvp2.Key, uri.PathAndQuery); 416
417 if (caps == null)
418 return;
419
420 foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values)
421 {
422 string reqName = reqHandler.Name ?? "";
423
424 if (!receivedStats.ContainsKey(reqName))
425 {
426 receivedStats[reqName] = reqHandler.RequestsReceived;
427 handledStats[reqName] = reqHandler.RequestsHandled;
428 }
429 else
430 {
431 receivedStats[reqName] += reqHandler.RequestsReceived;
432 handledStats[reqName] += reqHandler.RequestsHandled;
433 }
434 }
435
436 foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers())
437 {
438 string name = kvp.Key;
439 PollServiceEventArgs pollHandler = kvp.Value;
440
441 if (!receivedStats.ContainsKey(name))
442 {
443 receivedStats[name] = pollHandler.RequestsReceived;
444 handledStats[name] = pollHandler.RequestsHandled;
445 }
446 else
447 {
448 receivedStats[name] += pollHandler.RequestsReceived;
449 handledStats[name] += pollHandler.RequestsHandled;
450 }
451 }
259 } 452 }
453 );
454
455 foreach (KeyValuePair<string, int> kvp in receivedStats.OrderByDescending(kp => kp.Value))
456 cdt.AddRow(kvp.Key, kvp.Value, handledStats[kvp.Key]);
457
458 sb.Append(cdt.ToString());
459 */
460 }
461
462 private void HandleShowCapsStatsByUserCommand(string module, string[] cmdParams)
463 {
464 /*
465 if (SceneManager.Instance.CurrentScene != null && SceneManager.Instance.CurrentScene != m_scene)
466 return;
467
468 if (cmdParams.Length != 5 && cmdParams.Length != 7)
469 {
470 MainConsole.Instance.Output("Usage: show caps stats by user [<first-name> <last-name>]");
471 return;
472 }
473
474 StringBuilder sb = new StringBuilder();
475 sb.AppendFormat("Region {0}:\n", m_scene.Name);
476
477 if (cmdParams.Length == 5)
478 {
479 BuildSummaryStatsByUserReport(sb);
480 }
481 else if (cmdParams.Length == 7)
482 {
483 string firstName = cmdParams[5];
484 string lastName = cmdParams[6];
485
486 ScenePresence sp = m_scene.GetScenePresence(firstName, lastName);
487
488 if (sp == null)
489 return;
260 490
261 foreach (KeyValuePair<string, string> kvp3 in kvp.Value.ExternalCapsHandlers) 491 BuildDetailedStatsByUserReport(sb, sp);
262 caps.AppendFormat(m_showCapsCommandFormat, kvp3.Key, kvp3.Value);
263 } 492 }
264 493
265 MainConsole.Instance.Output(caps.ToString()); 494 MainConsole.Instance.Output(sb.ToString());
495 */
496 }
497
498 private void BuildDetailedStatsByUserReport(StringBuilder sb, ScenePresence sp)
499 {
500 /*
501 sb.AppendFormat("Avatar name {0}, type {1}\n", sp.Name, sp.IsChildAgent ? "child" : "root");
502
503 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
504 cdt.AddColumn("Cap Name", 34);
505 cdt.AddColumn("Req Received", 12);
506 cdt.AddColumn("Req Handled", 12);
507 cdt.Indent = 2;
508
509 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
510
511 if (caps == null)
512 return;
513
514 List<CapTableRow> capRows = new List<CapTableRow>();
515
516 foreach (IRequestHandler reqHandler in caps.CapsHandlers.GetCapsHandlers().Values)
517 capRows.Add(new CapTableRow(reqHandler.Name, reqHandler.RequestsReceived, reqHandler.RequestsHandled));
518
519 foreach (KeyValuePair<string, PollServiceEventArgs> kvp in caps.GetPollHandlers())
520 capRows.Add(new CapTableRow(kvp.Key, kvp.Value.RequestsReceived, kvp.Value.RequestsHandled));
521
522 foreach (CapTableRow ctr in capRows.OrderByDescending(ctr => ctr.RequestsReceived))
523 cdt.AddRow(ctr.Name, ctr.RequestsReceived, ctr.RequestsHandled);
524
525 sb.Append(cdt.ToString());
526 */
527 }
528
529 private void BuildSummaryStatsByUserReport(StringBuilder sb)
530 {
531 /*
532 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
533 cdt.AddColumn("Name", 32);
534 cdt.AddColumn("Type", 5);
535 cdt.AddColumn("Req Received", 12);
536 cdt.AddColumn("Req Handled", 12);
537 cdt.Indent = 2;
538
539 m_scene.ForEachScenePresence(
540 sp =>
541 {
542 Caps caps = m_scene.CapsModule.GetCapsForUser(sp.UUID);
543
544 if (caps == null)
545 return;
546
547 Dictionary<string, IRequestHandler> capsHandlers = caps.CapsHandlers.GetCapsHandlers();
548
549 int totalRequestsReceived = 0;
550 int totalRequestsHandled = 0;
551
552 foreach (IRequestHandler reqHandler in capsHandlers.Values)
553 {
554 totalRequestsReceived += reqHandler.RequestsReceived;
555 totalRequestsHandled += reqHandler.RequestsHandled;
556 }
557
558 Dictionary<string, PollServiceEventArgs> capsPollHandlers = caps.GetPollHandlers();
559
560 foreach (PollServiceEventArgs handler in capsPollHandlers.Values)
561 {
562 totalRequestsReceived += handler.RequestsReceived;
563 totalRequestsHandled += handler.RequestsHandled;
564 }
565
566 cdt.AddRow(sp.Name, sp.IsChildAgent ? "child" : "root", totalRequestsReceived, totalRequestsHandled);
567 }
568 );
569
570 sb.Append(cdt.ToString());
571 */
572 }
573
574 private class CapTableRow
575 {
576 public string Name { get; set; }
577 public int RequestsReceived { get; set; }
578 public int RequestsHandled { get; set; }
579
580 public CapTableRow(string name, int requestsReceived, int requestsHandled)
581 {
582 Name = name;
583 RequestsReceived = requestsReceived;
584 RequestsHandled = requestsHandled;
585 }
266 } 586 }
267 } 587 }
268} 588}
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
index 1f1568f..0c632b1 100644
--- a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
@@ -44,11 +44,12 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")] 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")]
45 public class DAExampleModule : INonSharedRegionModule 45 public class DAExampleModule : INonSharedRegionModule
46 { 46 {
47// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private static readonly bool ENABLED = false; // enable for testing 49 private readonly bool ENABLED = false; // enable for testing
50 50
51 public const string DANamespace = "DAExample Module"; 51 public const string Namespace = "Example";
52 public const string StoreName = "DA";
52 53
53 protected Scene m_scene; 54 protected Scene m_scene;
54 protected IDialogModule m_dialogMod; 55 protected IDialogModule m_dialogMod;
@@ -65,6 +66,8 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
65 m_scene = scene; 66 m_scene = scene;
66 m_scene.EventManager.OnSceneGroupMove += OnSceneGroupMove; 67 m_scene.EventManager.OnSceneGroupMove += OnSceneGroupMove;
67 m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>(); 68 m_dialogMod = m_scene.RequestModuleInterface<IDialogModule>();
69
70 m_log.DebugFormat("[DA EXAMPLE MODULE]: Added region {0}", m_scene.Name);
68 } 71 }
69 } 72 }
70 73
@@ -91,7 +94,7 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
91 if (sop == null) 94 if (sop == null)
92 return true; 95 return true;
93 96
94 if (!sop.DynAttrs.TryGetValue(DANamespace, out attrs)) 97 if (!sop.DynAttrs.TryGetStore(Namespace, StoreName, out attrs))
95 attrs = new OSDMap(); 98 attrs = new OSDMap();
96 99
97 OSDInteger newValue; 100 OSDInteger newValue;
@@ -106,12 +109,14 @@ namespace OpenSim.Region.CoreModules.Framework.DynamicAttributes.DAExampleModule
106 109
107 attrs["moves"] = newValue; 110 attrs["moves"] = newValue;
108 111
109 sop.DynAttrs[DANamespace] = attrs; 112 sop.DynAttrs.SetStore(Namespace, StoreName, attrs);
110 } 113 }
111 114
112 sop.ParentGroup.HasGroupChanged = true; 115 sop.ParentGroup.HasGroupChanged = true;
113 116
114 m_dialogMod.SendGeneralAlert(string.Format("{0} {1} moved {2} times", sop.Name, sop.UUID, newValue)); 117 string msg = string.Format("{0} {1} moved {2} times", sop.Name, sop.UUID, newValue);
118 m_log.DebugFormat("[DA EXAMPLE MODULE]: {0}", msg);
119 m_dialogMod.SendGeneralAlert(msg);
115 120
116 return true; 121 return true;
117 } 122 }
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs
index 650aa35..166a994 100644
--- a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DOExampleModule.cs
@@ -64,8 +64,8 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule
64 64
65 private Scene m_scene; 65 private Scene m_scene;
66 private IDialogModule m_dialogMod; 66 private IDialogModule m_dialogMod;
67 67
68 public string Name { get { return "DOExample Module"; } } 68 public string Name { get { return "DO"; } }
69 public Type ReplaceableInterface { get { return null; } } 69 public Type ReplaceableInterface { get { return null; } }
70 70
71 public void Initialise(IConfigSource source) {} 71 public void Initialise(IConfigSource source) {}
@@ -106,7 +106,7 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule
106 106
107// Console.WriteLine("Here for {0}", so.Name); 107// Console.WriteLine("Here for {0}", so.Name);
108 108
109 if (rootPart.DynAttrs.TryGetValue(DAExampleModule.DANamespace, out attrs)) 109 if (rootPart.DynAttrs.TryGetStore(DAExampleModule.Namespace, DAExampleModule.StoreName, out attrs))
110 { 110 {
111 movesSoFar = attrs["moves"].AsInteger(); 111 movesSoFar = attrs["moves"].AsInteger();
112 112
@@ -114,7 +114,7 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DOExampleModule
114 "[DO EXAMPLE MODULE]: Found saved moves {0} for {1} in {2}", movesSoFar, so.Name, m_scene.Name); 114 "[DO EXAMPLE MODULE]: Found saved moves {0} for {1} in {2}", movesSoFar, so.Name, m_scene.Name);
115 } 115 }
116 116
117 rootPart.DynObjs.Add(Name, new MyObject(movesSoFar)); 117 rootPart.DynObjs.Add(DAExampleModule.Namespace, Name, new MyObject(movesSoFar));
118 } 118 }
119 119
120 private bool OnSceneGroupMove(UUID groupId, Vector3 delta) 120 private bool OnSceneGroupMove(UUID groupId, Vector3 delta)
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index ed867b8..5fea0cf 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -51,11 +51,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EntityTransferModule")] 51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EntityTransferModule")]
52 public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule 52 public class EntityTransferModule : INonSharedRegionModule, IEntityTransferModule
53 { 53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private static readonly string LogHeader = "[ENTITY TRANSFER MODULE]";
55 56
56 public const int DefaultMaxTransferDistance = 4095; 57 public const int DefaultMaxTransferDistance = 4095;
57 public const bool WaitForAgentArrivedAtDestinationDefault = true; 58 public const bool WaitForAgentArrivedAtDestinationDefault = true;
58 59
60 public string OutgoingTransferVersionName { get; set; }
61
62 /// <summary>
63 /// Determine the maximum entity transfer version we will use for teleports.
64 /// </summary>
65 public float MaxOutgoingTransferVersion { get; set; }
66
59 /// <summary> 67 /// <summary>
60 /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer. 68 /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer.
61 /// </summary> 69 /// </summary>
@@ -151,9 +159,39 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
151 /// <param name="source"></param> 159 /// <param name="source"></param>
152 protected virtual void InitialiseCommon(IConfigSource source) 160 protected virtual void InitialiseCommon(IConfigSource source)
153 { 161 {
162 string transferVersionName = "SIMULATION";
163 float maxTransferVersion = 0.2f;
164
154 IConfig transferConfig = source.Configs["EntityTransfer"]; 165 IConfig transferConfig = source.Configs["EntityTransfer"];
155 if (transferConfig != null) 166 if (transferConfig != null)
156 { 167 {
168 string rawVersion
169 = transferConfig.GetString(
170 "MaxOutgoingTransferVersion",
171 string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
172
173 string[] rawVersionComponents = rawVersion.Split(new char[] { '/' });
174
175 bool versionValid = false;
176
177 if (rawVersionComponents.Length >= 2)
178 versionValid = float.TryParse(rawVersionComponents[1], out maxTransferVersion);
179
180 if (!versionValid)
181 {
182 m_log.ErrorFormat(
183 "[ENTITY TRANSFER MODULE]: MaxOutgoingTransferVersion {0} is invalid, using {1}",
184 rawVersion, string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
185 }
186 else
187 {
188 transferVersionName = rawVersionComponents[0];
189
190 m_log.InfoFormat(
191 "[ENTITY TRANSFER MODULE]: MaxOutgoingTransferVersion set to {0}",
192 string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
193 }
194
157 DisableInterRegionTeleportCancellation 195 DisableInterRegionTeleportCancellation
158 = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false); 196 = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false);
159 197
@@ -167,6 +205,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
167 MaxTransferDistance = DefaultMaxTransferDistance; 205 MaxTransferDistance = DefaultMaxTransferDistance;
168 } 206 }
169 207
208 OutgoingTransferVersionName = transferVersionName;
209 MaxOutgoingTransferVersion = maxTransferVersion;
210
170 m_entityTransferStateMachine = new EntityTransferStateMachine(this); 211 m_entityTransferStateMachine = new EntityTransferStateMachine(this);
171 212
172 m_Enabled = true; 213 m_Enabled = true;
@@ -280,10 +321,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
280 321
281 private void OnConnectionClosed(IClientAPI client) 322 private void OnConnectionClosed(IClientAPI client)
282 { 323 {
283 if (client.IsLoggingOut) 324 if (client.IsLoggingOut && m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting))
284 { 325 {
285 m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting);
286
287 m_log.DebugFormat( 326 m_log.DebugFormat(
288 "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout", 327 "[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout",
289 client.Name, Scene.Name); 328 client.Name, Scene.Name);
@@ -318,7 +357,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
318 m_log.DebugFormat( 357 m_log.DebugFormat(
319 "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2}@{3} - agent is already in transit.", 358 "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2}@{3} - agent is already in transit.",
320 sp.Name, sp.UUID, position, regionHandle); 359 sp.Name, sp.UUID, position, regionHandle);
321 360
361 sp.ControllingClient.SendTeleportFailed("Previous teleport process incomplete. Please retry shortly.");
362
322 return; 363 return;
323 } 364 }
324 365
@@ -522,6 +563,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
522 /// </returns> 563 /// </returns>
523 private bool IsWithinMaxTeleportDistance(RegionInfo sourceRegion, GridRegion destRegion) 564 private bool IsWithinMaxTeleportDistance(RegionInfo sourceRegion, GridRegion destRegion)
524 { 565 {
566 if(MaxTransferDistance == 0)
567 return true;
568
525// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY); 569// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY);
526// 570//
527// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}", 571// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}",
@@ -623,7 +667,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
623 if (!sp.ValidateAttachments()) 667 if (!sp.ValidateAttachments())
624 m_log.DebugFormat( 668 m_log.DebugFormat(
625 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", 669 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
626 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); 670 sp.Name, sp.Scene.Name, finalDestination.RegionName);
627 671
628 string reason; 672 string reason;
629 string version; 673 string version;
@@ -634,7 +678,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
634 678
635 m_log.DebugFormat( 679 m_log.DebugFormat(
636 "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}", 680 "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}",
637 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason); 681 sp.Name, sp.Scene.Name, finalDestination.RegionName, reason);
638 682
639 return; 683 return;
640 } 684 }
@@ -644,7 +688,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
644 // as server attempts. 688 // as server attempts.
645 m_interRegionTeleportAttempts.Value++; 689 m_interRegionTeleportAttempts.Value++;
646 690
647 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); 691 m_log.DebugFormat(
692 "[ENTITY TRANSFER MODULE]: {0} max transfer version is {1}/{2}, {3} max version is {4}",
693 sp.Scene.Name, OutgoingTransferVersionName, MaxOutgoingTransferVersion, finalDestination.RegionName, version);
648 694
649 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from 695 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
650 // both regions 696 // both regions
@@ -691,6 +737,29 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
691 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 737 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
692 } 738 }
693 739
740 // We're going to fallback to V1 if the destination gives us anything smaller than 0.2 or we're forcing
741 // use of the earlier protocol
742 float versionNumber = 0.1f;
743 string[] versionComponents = version.Split(new char[] { '/' });
744 if (versionComponents.Length >= 2)
745 float.TryParse(versionComponents[1], out versionNumber);
746
747 if (versionNumber == 0.2f && MaxOutgoingTransferVersion >= versionNumber)
748 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
749 else
750 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
751 }
752
753 private void TransferAgent_V1(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
754 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, string version, out string reason)
755 {
756 ulong destinationHandle = finalDestination.RegionHandle;
757 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
758
759 m_log.DebugFormat(
760 "[ENTITY TRANSFER MODULE]: Using TP V1 for {0} going from {1} to {2}",
761 sp.Name, Scene.Name, finalDestination.RegionName);
762
694 // Let's create an agent there if one doesn't exist yet. 763 // Let's create an agent there if one doesn't exist yet.
695 // NOTE: logout will always be false for a non-HG teleport. 764 // NOTE: logout will always be false for a non-HG teleport.
696 bool logout = false; 765 bool logout = false;
@@ -712,7 +781,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
712 m_interRegionTeleportCancels.Value++; 781 m_interRegionTeleportCancels.Value++;
713 782
714 m_log.DebugFormat( 783 m_log.DebugFormat(
715 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request", 784 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
716 sp.Name, finalDestination.RegionName, sp.Scene.Name); 785 sp.Name, finalDestination.RegionName, sp.Scene.Name);
717 786
718 return; 787 return;
@@ -734,11 +803,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
734 // OK, it got this agent. Let's close some child agents 803 // OK, it got this agent. Let's close some child agents
735 sp.CloseChildAgents(newRegionX, newRegionY); 804 sp.CloseChildAgents(newRegionX, newRegionY);
736 805
737 IClientIPEndpoint ipepClient; 806 IClientIPEndpoint ipepClient;
807 string capsPath = String.Empty;
738 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 808 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
739 { 809 {
740 m_log.DebugFormat( 810 m_log.DebugFormat(
741 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}", 811 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for incoming agent {3} from {4}",
742 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name); 812 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
743 813
744 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); 814 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
@@ -756,7 +826,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
756 // The EnableSimulator message makes the client establish a connection with the destination 826 // The EnableSimulator message makes the client establish a connection with the destination
757 // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the 827 // simulator by sending the initial UseCircuitCode UDP packet to the destination containing the
758 // correct circuit code. 828 // correct circuit code.
759 m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID); 829 m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID,
830 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
831 m_log.DebugFormat("{0} Sent EnableSimulator. regName={1}, size=<{2},{3}>", LogHeader,
832 finalDestination.RegionName, finalDestination.RegionSizeX, finalDestination.RegionSizeY);
760 833
761 // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination 834 // XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination
762 // simulator to confirm that it has established communication with the viewer. 835 // simulator to confirm that it has established communication with the viewer.
@@ -766,7 +839,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
766 // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly 839 // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly
767 // only on TeleportFinish). This is untested for region teleport between different simulators 840 // only on TeleportFinish). This is untested for region teleport between different simulators
768 // though this probably also works. 841 // though this probably also works.
769 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); 842 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, finalDestination.RegionHandle,
843 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
770 } 844 }
771 else 845 else
772 { 846 {
@@ -785,10 +859,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
785 // Let's send a full update of the agent. This is a synchronous call. 859 // Let's send a full update of the agent. This is a synchronous call.
786 AgentData agent = new AgentData(); 860 AgentData agent = new AgentData();
787 sp.CopyTo(agent); 861 sp.CopyTo(agent);
788 agent.Position = position; 862 agent.Position = agentCircuit.startpos;
789 SetCallbackURL(agent, sp.Scene.RegionInfo); 863 SetCallbackURL(agent, sp.Scene.RegionInfo);
790 864
791 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
792 865
793 // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to 866 // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to
794 // establish th econnection to the destination which makes it return true. 867 // establish th econnection to the destination which makes it return true.
@@ -821,10 +894,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
821 } 894 }
822 895
823 m_log.WarnFormat( 896 m_log.WarnFormat(
824 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.", 897 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
825 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 898 sp.Name, finalDestination.RegionName, sp.Scene.Name);
826 899
827 Fail(sp, finalDestination, logout, "Connection between viewer and destination region could not be established."); 900 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
828 return; 901 return;
829 } 902 }
830 903
@@ -833,10 +906,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
833 m_interRegionTeleportCancels.Value++; 906 m_interRegionTeleportCancels.Value++;
834 907
835 m_log.DebugFormat( 908 m_log.DebugFormat(
836 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request", 909 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
837 sp.Name, finalDestination.RegionName, sp.Scene.Name); 910 sp.Name, finalDestination.RegionName, sp.Scene.Name);
838 911
839 CleanupFailedInterRegionTeleport(sp, finalDestination); 912 CleanupFailedInterRegionTeleport(sp, currentAgentCircuit.SessionID.ToString(), finalDestination);
840 913
841 return; 914 return;
842 } 915 }
@@ -850,9 +923,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
850 // closes our existing agent which is still signalled as root. 923 // closes our existing agent which is still signalled as root.
851 sp.IsChildAgent = true; 924 sp.IsChildAgent = true;
852 925
926 // OK, send TPFinish to the client, so that it starts the process of contacting the destination region
853 if (m_eqModule != null) 927 if (m_eqModule != null)
854 { 928 {
855 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID); 929 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID,
930 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
856 } 931 }
857 else 932 else
858 { 933 {
@@ -879,8 +954,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
879 m_log.WarnFormat( 954 m_log.WarnFormat(
880 "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.", 955 "[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.",
881 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName); 956 sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
882 957
883 Fail(sp, finalDestination, logout, "Destination region did not signal teleport completion."); 958 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Destination region did not signal teleport completion.");
884 959
885 return; 960 return;
886 } 961 }
@@ -908,15 +983,190 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
908 983
909 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 984 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
910 { 985 {
986 if (!sp.Scene.IncomingPreCloseClient(sp))
987 return;
988
911 // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before 989 // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before
912 // they regard the new region as the current region after receiving the AgentMovementComplete 990 // they regard the new region as the current region after receiving the AgentMovementComplete
913 // response. If close is sent before then, it will cause the viewer to quit instead. 991 // response. If close is sent before then, it will cause the viewer to quit instead.
914 // 992 //
915 // This sleep can be increased if necessary. However, whilst it's active, 993 // This sleep can be increased if necessary. However, whilst it's active,
916 // an agent cannot teleport back to this region if it has teleported away. 994 // an agent cannot teleport back to this region if it has teleported away.
917 Thread.Sleep(3000); 995 Thread.Sleep(2000);
918 996
919 sp.Scene.IncomingCloseAgent(sp.UUID, false); 997 sp.Scene.CloseAgent(sp.UUID, false);
998 }
999 else
1000 {
1001 // now we have a child agent in this region.
1002 sp.Reset();
1003 }
1004 }
1005
1006 private void TransferAgent_V2(ScenePresence sp, AgentCircuitData agentCircuit, GridRegion reg, GridRegion finalDestination,
1007 IPEndPoint endPoint, uint teleportFlags, uint oldRegionX, uint newRegionX, uint oldRegionY, uint newRegionY, string version, out string reason)
1008 {
1009 ulong destinationHandle = finalDestination.RegionHandle;
1010 AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
1011
1012 // Let's create an agent there if one doesn't exist yet.
1013 // NOTE: logout will always be false for a non-HG teleport.
1014 bool logout = false;
1015 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
1016 {
1017 m_interRegionTeleportFailures.Value++;
1018
1019 sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", reason));
1020
1021 m_log.DebugFormat(
1022 "[ENTITY TRANSFER MODULE]: Teleport of {0} from {1} to {2} was refused because {3}",
1023 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason);
1024
1025 return;
1026 }
1027
1028 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Cancelling)
1029 {
1030 m_interRegionTeleportCancels.Value++;
1031
1032 m_log.DebugFormat(
1033 "[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after CreateAgent on client request",
1034 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1035
1036 return;
1037 }
1038 else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
1039 {
1040 m_interRegionTeleportAborts.Value++;
1041
1042 m_log.DebugFormat(
1043 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
1044 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1045
1046 return;
1047 }
1048
1049 // Past this point we have to attempt clean up if the teleport fails, so update transfer state.
1050 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
1051
1052 IClientIPEndpoint ipepClient;
1053 string capsPath = String.Empty;
1054 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
1055 {
1056 m_log.DebugFormat(
1057 "[ENTITY TRANSFER MODULE]: Determined that region {0} at {1},{2} needs new child agent for agent {3} from {4}",
1058 finalDestination.RegionName, newRegionX, newRegionY, sp.Name, Scene.Name);
1059
1060 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent...");
1061 #region IP Translation for NAT
1062 // Uses ipepClient above
1063 if (sp.ClientView.TryGet(out ipepClient))
1064 {
1065 endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
1066 }
1067 #endregion
1068 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1069 }
1070 else
1071 {
1072 agentCircuit.CapsPath = sp.Scene.CapsModule.GetChildSeed(sp.UUID, reg.RegionHandle);
1073 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
1074 }
1075
1076 // We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
1077 // where that neighbour simulator could otherwise request a child agent create on the source which then
1078 // closes our existing agent which is still signalled as root.
1079 //sp.IsChildAgent = true;
1080
1081 // New protocol: send TP Finish directly, without prior ES or EAC. That's what happens in the Linden grid
1082 if (m_eqModule != null)
1083 m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID,
1084 finalDestination.RegionSizeX, finalDestination.RegionSizeY);
1085 else
1086 sp.ControllingClient.SendRegionTeleport(destinationHandle, 13, endPoint, 4,
1087 teleportFlags, capsPath);
1088
1089 m_log.DebugFormat(
1090 "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
1091 capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
1092
1093 // Let's send a full update of the agent.
1094 AgentData agent = new AgentData();
1095 sp.CopyTo(agent);
1096 agent.Position = agentCircuit.startpos;
1097 agent.SenderWantsToWaitForRoot = true;
1098 //SetCallbackURL(agent, sp.Scene.RegionInfo);
1099
1100 // Reset the do not close flag. This must be done before the destination opens child connections (here
1101 // triggered by UpdateAgent) to avoid race conditions. However, we also want to reset it as late as possible
1102 // to avoid a situation where an unexpectedly early call to Scene.NewUserConnection() wrongly results
1103 // in no close.
1104 sp.DoNotCloseAfterTeleport = false;
1105
1106 // Send the Update. If this returns true, we know the client has contacted the destination
1107 // via CompleteMovementIntoRegion, so we can let go.
1108 // If it returns false, something went wrong, and we need to abort.
1109 if (!UpdateAgent(reg, finalDestination, agent, sp))
1110 {
1111 if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
1112 {
1113 m_interRegionTeleportAborts.Value++;
1114
1115 m_log.DebugFormat(
1116 "[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
1117 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1118
1119 return;
1120 }
1121
1122 m_log.WarnFormat(
1123 "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}",
1124 sp.Name, finalDestination.RegionName, sp.Scene.Name);
1125
1126 Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established.");
1127 return;
1128 }
1129
1130 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
1131
1132 // Need to signal neighbours whether child agents may need closing irrespective of whether this
1133 // one needed closing. We also need to close child agents as quickly as possible to avoid complicated
1134 // race conditions with rapid agent releporting (e.g. from A1 to a non-neighbour B, back
1135 // to a neighbour A2 then off to a non-neighbour C). Closing child agents any later requires complex
1136 // distributed checks to avoid problems in rapid reteleporting scenarios and where child agents are
1137 // abandoned without proper close by viewer but then re-used by an incoming connection.
1138 sp.CloseChildAgents(newRegionX, newRegionY);
1139
1140 // May need to logout or other cleanup
1141 AgentHasMovedAway(sp, logout);
1142
1143 // Well, this is it. The agent is over there.
1144 KillEntity(sp.Scene, sp.LocalId);
1145
1146 // Now let's make it officially a child agent
1147 sp.MakeChildAgent();
1148
1149 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1150 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
1151 {
1152 if (!sp.Scene.IncomingPreCloseClient(sp))
1153 return;
1154
1155 // RED ALERT!!!!
1156 // PLEASE DO NOT DECREASE THIS WAIT TIME UNDER ANY CIRCUMSTANCES.
1157 // THE VIEWERS SEEM TO NEED SOME TIME AFTER RECEIVING MoveAgentIntoRegion
1158 // BEFORE THEY SETTLE IN THE NEW REGION.
1159 // DECREASING THE WAIT TIME HERE WILL EITHER RESULT IN A VIEWER CRASH OR
1160 // IN THE AVIE BEING PLACED IN INFINITY FOR A COUPLE OF SECONDS.
1161 Thread.Sleep(15000);
1162
1163 // OK, it got this agent. Let's close everything
1164 // If we shouldn't close the agent due to some other region renewing the connection
1165 // then this will be handled in IncomingCloseAgent under lock conditions
1166 m_log.DebugFormat(
1167 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name);
1168
1169 sp.Scene.CloseAgent(sp.UUID, false);
920 } 1170 }
921 else 1171 else
922 { 1172 {
@@ -934,17 +1184,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
934 /// <remarks> 1184 /// <remarks>
935 /// <param name='sp'> </param> 1185 /// <param name='sp'> </param>
936 /// <param name='finalDestination'></param> 1186 /// <param name='finalDestination'></param>
937 protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination) 1187 protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, string auth_token, GridRegion finalDestination)
938 { 1188 {
939 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); 1189 m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
940 1190
941 sp.IsChildAgent = false; 1191 if (sp.IsChildAgent) // We had set it to child before attempted TP (V1)
942 ReInstantiateScripts(sp); 1192 {
943 1193 sp.IsChildAgent = false;
944 EnableChildAgents(sp); 1194 ReInstantiateScripts(sp);
945 1195
1196 EnableChildAgents(sp);
1197 }
946 // Finally, kill the agent we just created at the destination. 1198 // Finally, kill the agent we just created at the destination.
947 Scene.SimulationService.CloseAgent(finalDestination, sp.UUID); 1199 // XXX: Possibly this should be done asynchronously.
1200 Scene.SimulationService.CloseAgent(finalDestination, sp.UUID, auth_token);
948 } 1201 }
949 1202
950 /// <summary> 1203 /// <summary>
@@ -954,9 +1207,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
954 /// <param name='finalDestination'></param> 1207 /// <param name='finalDestination'></param>
955 /// <param name='logout'></param> 1208 /// <param name='logout'></param>
956 /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param> 1209 /// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param>
957 protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason) 1210 protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string auth_code, string reason)
958 { 1211 {
959 CleanupFailedInterRegionTeleport(sp, finalDestination); 1212 CleanupFailedInterRegionTeleport(sp, auth_code, finalDestination);
960 1213
961 m_interRegionTeleportFailures.Value++; 1214 m_interRegionTeleportFailures.Value++;
962 1215
@@ -1132,7 +1385,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1132 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos) 1385 public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos)
1133 { 1386 {
1134 version = String.Empty; 1387 version = String.Empty;
1135 newpos = new Vector3(pos.X, pos.Y, pos.Z); 1388 newpos = pos;
1136 1389
1137// m_log.DebugFormat( 1390// m_log.DebugFormat(
1138// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); 1391// "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name);
@@ -1471,11 +1724,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1471 if (m_eqModule != null) 1724 if (m_eqModule != null)
1472 { 1725 {
1473 m_eqModule.CrossRegion( 1726 m_eqModule.CrossRegion(
1474 neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint, 1727 neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */,
1475 capsPath, agent.UUID, agent.ControllingClient.SessionId); 1728 neighbourRegion.ExternalEndPoint,
1729 capsPath, agent.UUID, agent.ControllingClient.SessionId,
1730 neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY);
1476 } 1731 }
1477 else 1732 else
1478 { 1733 {
1734 m_log.ErrorFormat("{0} Using old CrossRegion packet. Varregion will not work!!", LogHeader);
1479 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint, 1735 agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint,
1480 capsPath); 1736 capsPath);
1481 } 1737 }
@@ -1654,10 +1910,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1654 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles); 1910 List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles);
1655 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles); 1911 List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
1656 1912
1657 //Dump("Current Neighbors", neighbourHandles); 1913// Dump("Current Neighbors", neighbourHandles);
1658 //Dump("Previous Neighbours", previousRegionNeighbourHandles); 1914// Dump("Previous Neighbours", previousRegionNeighbourHandles);
1659 //Dump("New Neighbours", newRegions); 1915// Dump("New Neighbours", newRegions);
1660 //Dump("Old Neighbours", oldRegions); 1916// Dump("Old Neighbours", oldRegions);
1661 1917
1662 /// Update the scene presence's known regions here on this region 1918 /// Update the scene presence's known regions here on this region
1663 sp.DropOldNeighbours(oldRegions); 1919 sp.DropOldNeighbours(oldRegions);
@@ -1665,8 +1921,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1665 /// Collect as many seeds as possible 1921 /// Collect as many seeds as possible
1666 Dictionary<ulong, string> seeds; 1922 Dictionary<ulong, string> seeds;
1667 if (sp.Scene.CapsModule != null) 1923 if (sp.Scene.CapsModule != null)
1668 seeds 1924 seeds = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1669 = new Dictionary<ulong, string>(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID));
1670 else 1925 else
1671 seeds = new Dictionary<ulong, string>(); 1926 seeds = new Dictionary<ulong, string>();
1672 1927
@@ -1736,6 +1991,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1736 newAgent = true; 1991 newAgent = true;
1737 else 1992 else
1738 newAgent = false; 1993 newAgent = false;
1994// continue;
1739 1995
1740 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle) 1996 if (neighbour.RegionHandle != sp.Scene.RegionInfo.RegionHandle)
1741 { 1997 {
@@ -1841,12 +2097,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1841 } 2097 }
1842 #endregion 2098 #endregion
1843 2099
1844 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: {0} is sending {1} EnableSimulator for neighbour region {2} @ {3} " + 2100 m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " +
1845 "and EstablishAgentCommunication with seed cap {4}", 2101 "and EstablishAgentCommunication with seed cap {8}", LogHeader,
1846 scene.RegionInfo.RegionName, sp.Name, reg.RegionName, reg.RegionHandle, capsPath); 2102 scene.RegionInfo.RegionName, sp.Name,
2103 reg.RegionName, reg.RegionLocX, reg.RegionLocY, reg.RegionSizeX, reg.RegionSizeY , capsPath);
1847 2104
1848 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID); 2105 m_eqModule.EnableSimulator(reg.RegionHandle, endPoint, sp.UUID, reg.RegionSizeX, reg.RegionSizeY);
1849 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); 2106 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath, reg.RegionHandle, reg.RegionSizeX, reg.RegionSizeY);
1850 } 2107 }
1851 else 2108 else
1852 { 2109 {
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index d372c0e..7abdc21 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -53,8 +53,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 54
55 private int m_levelHGTeleport = 0; 55 private int m_levelHGTeleport = 0;
56 private string m_ThisHomeURI;
56 57
57 private GatekeeperServiceConnector m_GatekeeperConnector; 58 private GatekeeperServiceConnector m_GatekeeperConnector;
59 private IUserAgentService m_UAS;
58 60
59 protected bool m_RestrictAppearanceAbroad; 61 protected bool m_RestrictAppearanceAbroad;
60 protected string m_AccountName; 62 protected string m_AccountName;
@@ -143,6 +145,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
143 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); 145 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
144 } 146 }
145 } 147 }
148
149 moduleConfig = source.Configs["Hypergrid"];
150 if (moduleConfig != null)
151 {
152 m_ThisHomeURI = moduleConfig.GetString("HomeURI", string.Empty);
153 if (m_ThisHomeURI != string.Empty && !m_ThisHomeURI.EndsWith("/"))
154 m_ThisHomeURI += '/';
155 }
146 } 156 }
147 157
148 public override void AddRegion(Scene scene) 158 public override void AddRegion(Scene scene)
@@ -161,22 +171,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
161 if (!so.IsAttachment) 171 if (!so.IsAttachment)
162 return; 172 return;
163 173
164 if (so.Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar)) 174 if (so.AttachedAvatar == UUID.Zero || Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar))
165 return; 175 return;
166 176
167 // foreign user 177 // foreign user
168 AgentCircuitData aCircuit = so.Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar); 178 AgentCircuitData aCircuit = Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar);
169 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) 179 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
170 { 180 {
171 if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) 181 if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
172 { 182 {
173 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); 183 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString();
174 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachement {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url); 184 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url);
175 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 185 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
176 HGUuidGatherer uuidGatherer = new HGUuidGatherer(so.Scene.AssetService, url); 186 HGUuidGatherer uuidGatherer = new HGUuidGatherer(Scene.AssetService, url);
177 uuidGatherer.GatherAssetUuids(so, ids); 187 uuidGatherer.GatherAssetUuids(so, ids);
178 188
179 foreach (KeyValuePair<UUID, AssetType> kvp in ids) 189 foreach (KeyValuePair<UUID, sbyte> kvp in ids)
180 uuidGatherer.FetchAsset(kvp.Key); 190 uuidGatherer.FetchAsset(kvp.Key);
181 } 191 }
182 } 192 }
@@ -194,7 +204,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
194 base.RegionLoaded(scene); 204 base.RegionLoaded(scene);
195 205
196 if (m_Enabled) 206 if (m_Enabled)
207 {
197 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService); 208 m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService);
209 m_UAS = scene.RequestModuleInterface<IUserAgentService>();
210 if (m_UAS == null)
211 m_UAS = new UserAgentServiceConnector(m_ThisHomeURI);
212
213 }
198 } 214 }
199 215
200 public override void RemoveRegion(Scene scene) 216 public override void RemoveRegion(Scene scene)
@@ -272,8 +288,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
272 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI")) 288 if (agentCircuit.ServiceURLs.ContainsKey("HomeURI"))
273 { 289 {
274 string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString(); 290 string userAgentDriver = agentCircuit.ServiceURLs["HomeURI"].ToString();
275 IUserAgentService connector = new UserAgentServiceConnector(userAgentDriver); 291 IUserAgentService connector;
276 bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason); 292
293 if (userAgentDriver.Equals(m_ThisHomeURI) && m_UAS != null)
294 connector = m_UAS;
295 else
296 connector = new UserAgentServiceConnector(userAgentDriver);
297
298 bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, false, out reason);
277 logout = success; // flag for later logout from this grid; this is an HG TP 299 logout = success; // flag for later logout from this grid; this is an HG TP
278 300
279 if (success) 301 if (success)
@@ -552,12 +574,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
552 if (uMan != null && uMan.IsLocalGridUser(obj.AgentId)) 574 if (uMan != null && uMan.IsLocalGridUser(obj.AgentId))
553 { 575 {
554 // local grid user 576 // local grid user
577 m_UAS.LogoutAgent(obj.AgentId, obj.SessionId);
555 return; 578 return;
556 } 579 }
557 580
558 AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode); 581 AgentCircuitData aCircuit = ((Scene)(obj.Scene)).AuthenticateHandler.GetAgentCircuitData(obj.CircuitCode);
559 582 if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("HomeURI"))
560 if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
561 { 583 {
562 string url = aCircuit.ServiceURLs["HomeURI"].ToString(); 584 string url = aCircuit.ServiceURLs["HomeURI"].ToString();
563 IUserAgentService security = new UserAgentServiceConnector(url); 585 IUserAgentService security = new UserAgentServiceConnector(url);
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
index 7871eda..d4fb1ba 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -73,6 +73,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
73 73
74 private AssetMetadata FetchMetadata(string url, UUID assetID) 74 private AssetMetadata FetchMetadata(string url, UUID assetID)
75 { 75 {
76 if (string.IsNullOrEmpty(url))
77 return null;
78
76 if (!url.EndsWith("/") && !url.EndsWith("=")) 79 if (!url.EndsWith("/") && !url.EndsWith("="))
77 url = url + "/"; 80 url = url + "/";
78 81
@@ -92,6 +95,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
92 AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); 95 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
93 if (asset == null) 96 if (asset == null)
94 { 97 {
98 if (string.IsNullOrEmpty(url))
99 return null;
100
95 if (!url.EndsWith("/") && !url.EndsWith("=")) 101 if (!url.EndsWith("/") && !url.EndsWith("="))
96 url = url + "/"; 102 url = url + "/";
97 103
@@ -109,6 +115,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
109 115
110 public bool PostAsset(string url, AssetBase asset) 116 public bool PostAsset(string url, AssetBase asset)
111 { 117 {
118 if (string.IsNullOrEmpty(url))
119 return false;
120
112 if (asset != null) 121 if (asset != null)
113 { 122 {
114 if (!url.EndsWith("/") && !url.EndsWith("=")) 123 if (!url.EndsWith("/") && !url.EndsWith("="))
@@ -165,7 +174,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
165 174
166 private void AdjustIdentifiers(AssetMetadata meta) 175 private void AdjustIdentifiers(AssetMetadata meta)
167 { 176 {
168 if (meta.CreatorID != null && meta.CreatorID != string.Empty) 177 if (!string.IsNullOrEmpty(meta.CreatorID))
169 { 178 {
170 UUID uuid = UUID.Zero; 179 UUID uuid = UUID.Zero;
171 UUID.TryParse(meta.CreatorID, out uuid); 180 UUID.TryParse(meta.CreatorID, out uuid);
@@ -251,9 +260,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
251 260
252 // The act of gathering UUIDs downloads some assets from the remote server 261 // The act of gathering UUIDs downloads some assets from the remote server
253 // but not all... 262 // but not all...
254 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 263 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
255 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); 264 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
256 uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); 265 uuidGatherer.GatherAssetUuids(assetID, meta.Type, ids);
257 m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count); 266 m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count);
258 bool success = true; 267 bool success = true;
259 foreach (UUID uuid in ids.Keys) 268 foreach (UUID uuid in ids.Keys)
@@ -277,9 +286,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
277 AssetBase asset = m_scene.AssetService.Get(assetID.ToString()); 286 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
278 if (asset != null) 287 if (asset != null)
279 { 288 {
280 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 289 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
281 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); 290 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty);
282 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); 291 uuidGatherer.GatherAssetUuids(asset.FullID, asset.Type, ids);
283 bool success = false; 292 bool success = false;
284 foreach (UUID uuid in ids.Keys) 293 foreach (UUID uuid in ids.Keys)
285 { 294 {
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index b2b628d..ce7ed26 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -62,6 +62,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
62 private string m_ThisGatekeeper; 62 private string m_ThisGatekeeper;
63 private bool m_RestrictInventoryAccessAbroad; 63 private bool m_RestrictInventoryAccessAbroad;
64 64
65 private bool m_bypassPermissions = true;
66
65// private bool m_Initialized = false; 67// private bool m_Initialized = false;
66 68
67 #region INonSharedRegionModule 69 #region INonSharedRegionModule
@@ -100,6 +102,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
100 } 102 }
101 else 103 else
102 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); 104 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!");
105
106 m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(source, "serverside_object_permissions",
107 new string[] { "Startup", "Permissions" }, true);
108
103 } 109 }
104 } 110 }
105 } 111 }
@@ -114,6 +120,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
114 scene.EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem; 120 scene.EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem;
115 scene.EventManager.OnTeleportStart += TeleportStart; 121 scene.EventManager.OnTeleportStart += TeleportStart;
116 scene.EventManager.OnTeleportFail += TeleportFail; 122 scene.EventManager.OnTeleportFail += TeleportFail;
123
124 // We're fgoing to enforce some stricter permissions if Outbound is false
125 scene.Permissions.OnTakeObject += CanTakeObject;
126 scene.Permissions.OnTakeCopyObject += CanTakeObject;
127 scene.Permissions.OnTransferUserInventory += OnTransferUserInventory;
117 } 128 }
118 129
119 #endregion 130 #endregion
@@ -135,7 +146,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
135 if (sp is ScenePresence) 146 if (sp is ScenePresence)
136 { 147 {
137 AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId); 148 AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId);
138 if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) 149 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
139 { 150 {
140 if (m_RestrictInventoryAccessAbroad) 151 if (m_RestrictInventoryAccessAbroad)
141 { 152 {
@@ -185,8 +196,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
185 } 196 }
186 } 197 }
187 198
188 public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel) 199 public void UploadInventoryItem(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel)
189 { 200 {
201 if (type == AssetType.Link)
202 return;
203
190 string userAssetServer = string.Empty; 204 string userAssetServer = string.Empty;
191 if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission) 205 if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission)
192 { 206 {
@@ -221,7 +235,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
221 { 235 {
222 UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data); 236 UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data);
223 237
224 UploadInventoryItem(remoteClient.AgentId, newAssetID, "", 0); 238 UploadInventoryItem(remoteClient.AgentId, AssetType.Unknown, newAssetID, "", 0);
225 239
226 return newAssetID; 240 return newAssetID;
227 } 241 }
@@ -232,7 +246,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
232 protected override void ExportAsset(UUID agentID, UUID assetID) 246 protected override void ExportAsset(UUID agentID, UUID assetID)
233 { 247 {
234 if (!assetID.Equals(UUID.Zero)) 248 if (!assetID.Equals(UUID.Zero))
235 UploadInventoryItem(agentID, assetID, "", 0); 249 UploadInventoryItem(agentID, AssetType.Unknown, assetID, "", 0);
236 else 250 else
237 m_log.Debug("[HGScene]: Scene.Inventory did not create asset"); 251 m_log.Debug("[HGScene]: Scene.Inventory did not create asset");
238 } 252 }
@@ -244,7 +258,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
244 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 258 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
245 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment) 259 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
246 { 260 {
247 m_log.DebugFormat("[HGScene] RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID); 261 m_log.DebugFormat("[HGScene]: RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID);
248 262
249 //if (fromTaskID.Equals(UUID.Zero)) 263 //if (fromTaskID.Equals(UUID.Zero))
250 //{ 264 //{
@@ -297,7 +311,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
297 if (m_Scene.TryGetScenePresence(userID, out sp)) 311 if (m_Scene.TryGetScenePresence(userID, out sp))
298 { 312 {
299 AgentCircuitData aCircuit = m_Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 313 AgentCircuitData aCircuit = m_Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
300 if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) 314 if (aCircuit != null && aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
301 { 315 {
302 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString(); 316 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString();
303 assetServerURL = assetServerURL.Trim(new char[] { '/' }); 317 assetServerURL = assetServerURL.Trim(new char[] { '/' });
@@ -348,7 +362,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
348 InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId); 362 InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId);
349 InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID); 363 InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID);
350 364
351 inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); 365 List<InventoryFolderBase> keep = new List<InventoryFolderBase>();
366
367 foreach (InventoryFolderBase f in content.Folders)
368 {
369 if (f.Name != "My Suitcase" && f.Name != "Current Outfit")
370 keep.Add(f);
371 }
372
373 inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray());
352 } 374 }
353 } 375 }
354 } 376 }
@@ -381,7 +403,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
381 403
382 foreach (InventoryFolderBase f in content.Folders) 404 foreach (InventoryFolderBase f in content.Folders)
383 { 405 {
384 if (f.Name != "My Suitcase") 406 if (f.Name != "My Suitcase" && f.Name != "Current Outfit")
385 { 407 {
386 f.Name = f.Name + " (Unavailable)"; 408 f.Name = f.Name + " (Unavailable)";
387 keep.Add(f); 409 keep.Add(f);
@@ -406,5 +428,36 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
406 } 428 }
407 429
408 #endregion 430 #endregion
431
432 #region Permissions
433
434 private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene)
435 {
436 if (m_bypassPermissions) return true;
437
438 if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(stealer))
439 {
440 SceneObjectGroup sog = null;
441 if (m_Scene.TryGetSceneObjectGroup(objectID, out sog) && sog.OwnerID == stealer)
442 return true;
443
444 return false;
445 }
446
447 return true;
448 }
449
450 private bool OnTransferUserInventory(UUID itemID, UUID userID, UUID recipientID)
451 {
452 if (m_bypassPermissions) return true;
453
454 if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(recipientID))
455 return false;
456
457 return true;
458 }
459
460
461 #endregion
409 } 462 }
410} \ No newline at end of file 463} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index d09ea3e..fadcd5e 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -358,7 +358,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
358 bool asAttachment) 358 bool asAttachment)
359 { 359 {
360 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero); 360 CoalescedSceneObjects coa = new CoalescedSceneObjects(UUID.Zero);
361 Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>(); 361// Dictionary<UUID, Vector3> originalPositions = new Dictionary<UUID, Vector3>();
362 362
363 foreach (SceneObjectGroup objectGroup in objlist) 363 foreach (SceneObjectGroup objectGroup in objlist)
364 { 364 {
@@ -379,7 +379,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
379 objectGroup.AbsolutePosition.Z); 379 objectGroup.AbsolutePosition.Z);
380 380
381 Quaternion inventoryStoredRotation = objectGroup.GroupRotation; 381 Quaternion inventoryStoredRotation = objectGroup.GroupRotation;
382 originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition; 382 //originalPositions[objectGroup.UUID] = objectGroup.AbsolutePosition;
383 383
384 // Restore attachment data after trip through the sim 384 // Restore attachment data after trip through the sim
385 if (objectGroup.RootPart.AttachPoint > 0) 385 if (objectGroup.RootPart.AttachPoint > 0)
@@ -390,9 +390,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
390 390
391 // Trees could be attached and it's been done, but it makes 391 // Trees could be attached and it's been done, but it makes
392 // no sense. State must be preserved because it's the tree type 392 // no sense. State must be preserved because it's the tree type
393 if (objectGroup.RootPart.Shape.PCode != (byte)PCode.Tree && 393 if (objectGroup.RootPart.Shape.PCode != (byte) PCode.Tree &&
394 objectGroup.RootPart.Shape.PCode != (byte)PCode.NewTree) 394 objectGroup.RootPart.Shape.PCode != (byte) PCode.NewTree)
395 {
395 objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint; 396 objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint;
397 if (objectGroup.RootPart.AttachPoint > 0)
398 objectGroup.RootPart.Shape.LastAttachPoint = objectGroup.RootPart.AttachPoint;
399 }
396 400
397 objectGroup.AbsolutePosition = inventoryStoredPosition; 401 objectGroup.AbsolutePosition = inventoryStoredPosition;
398 objectGroup.RootPart.RotationOffset = inventoryStoredRotation; 402 objectGroup.RootPart.RotationOffset = inventoryStoredRotation;
@@ -423,9 +427,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
423 else 427 else
424 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment); 428 itemXml = SceneObjectSerializer.ToOriginalXmlFormat(objlist[0], !asAttachment);
425 429
426 // Restore the position of each group now that it has been stored to inventory. 430// // Restore the position of each group now that it has been stored to inventory.
427 foreach (SceneObjectGroup objectGroup in objlist) 431// foreach (SceneObjectGroup objectGroup in objlist)
428 objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; 432// objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID];
429 433
430 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID); 434 InventoryItemBase item = CreateItemForObject(action, remoteClient, objlist[0], folderID);
431 435
@@ -435,17 +439,28 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
435 439
436 if (item == null) 440 if (item == null)
437 return null; 441 return null;
442
443 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
444 item.CreatorData = objlist[0].RootPart.CreatorData;
438 445
439 // Can't know creator is the same, so null it in inventory
440 if (objlist.Count > 1) 446 if (objlist.Count > 1)
441 { 447 {
442 item.CreatorId = UUID.Zero.ToString();
443 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; 448 item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems;
449
450 // If the objects have different creators then don't specify a creator at all
451 foreach (SceneObjectGroup objectGroup in objlist)
452 {
453 if ((objectGroup.RootPart.CreatorID.ToString() != item.CreatorId)
454 || (objectGroup.RootPart.CreatorData.ToString() != item.CreatorData))
455 {
456 item.CreatorId = UUID.Zero.ToString();
457 item.CreatorData = string.Empty;
458 break;
459 }
460 }
444 } 461 }
445 else 462 else
446 { 463 {
447 item.CreatorId = objlist[0].RootPart.CreatorID.ToString();
448 item.CreatorData = objlist[0].RootPart.CreatorData;
449 item.SaleType = objlist[0].RootPart.ObjectSaleType; 464 item.SaleType = objlist[0].RootPart.ObjectSaleType;
450 item.SalePrice = objlist[0].RootPart.SalePrice; 465 item.SalePrice = objlist[0].RootPart.SalePrice;
451 } 466 }
@@ -466,13 +481,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
466 } 481 }
467 else 482 else
468 { 483 {
469 AddPermissions(item, objlist[0], objlist, remoteClient);
470
471 item.CreationDate = Util.UnixTimeSinceEpoch(); 484 item.CreationDate = Util.UnixTimeSinceEpoch();
472 item.Description = asset.Description; 485 item.Description = asset.Description;
473 item.Name = asset.Name; 486 item.Name = asset.Name;
474 item.AssetType = asset.Type; 487 item.AssetType = asset.Type;
475 488
489 AddPermissions(item, objlist[0], objlist, remoteClient);
490
476 m_Scene.AddInventoryItem(item); 491 m_Scene.AddInventoryItem(item);
477 492
478 if (remoteClient != null && item.Owner == remoteClient.AgentId) 493 if (remoteClient != null && item.Owner == remoteClient.AgentId)
@@ -527,16 +542,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
527 } 542 }
528 effectivePerms |= (uint)PermissionMask.Move; 543 effectivePerms |= (uint)PermissionMask.Move;
529 544
545 //PermissionsUtil.LogPermissions(item.Name, "Before AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions);
546
530 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) 547 if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions())
531 { 548 {
532 uint perms = effectivePerms; 549 uint perms = effectivePerms;
533 uint nextPerms = (perms & 7) << 13; 550 PermissionsUtil.ApplyFoldedPermissions(effectivePerms, ref perms);
534 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
535 perms &= ~(uint)PermissionMask.Copy;
536 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
537 perms &= ~(uint)PermissionMask.Transfer;
538 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
539 perms &= ~(uint)PermissionMask.Modify;
540 551
541 item.BasePermissions = perms & so.RootPart.NextOwnerMask; 552 item.BasePermissions = perms & so.RootPart.NextOwnerMask;
542 item.CurrentPermissions = item.BasePermissions; 553 item.CurrentPermissions = item.BasePermissions;
@@ -544,10 +555,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
544 item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask; 555 item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask;
545 item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask; 556 item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask;
546 557
547 // Magic number badness. Maybe this deserves an enum. 558 // apply next owner perms on rez
548 // bit 4 (16) is the "Slam" bit, it means treat as passed 559 item.CurrentPermissions |= SceneObjectGroup.SLAM;
549 // and apply next owner perms on rez
550 item.CurrentPermissions |= 16; // Slam!
551 } 560 }
552 else 561 else
553 { 562 {
@@ -564,8 +573,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
564 (uint)PermissionMask.Move | 573 (uint)PermissionMask.Move |
565 (uint)PermissionMask.Export | 574 (uint)PermissionMask.Export |
566 7); // Preserve folded permissions 575 7); // Preserve folded permissions
567 } 576 }
568 577
578 //PermissionsUtil.LogPermissions(item.Name, "After AddPermissions", item.BasePermissions, item.CurrentPermissions, item.NextPermissions);
579
569 return item; 580 return item;
570 } 581 }
571 582
@@ -707,6 +718,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
707 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); 718 InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID);
708 if (f != null) 719 if (f != null)
709 folder = m_Scene.InventoryService.GetFolder(f); 720 folder = m_Scene.InventoryService.GetFolder(f);
721
722 if(folder.Type == 14 || folder.Type == 16)
723 {
724 // folder.Type = 6;
725 folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object);
726 }
710 } 727 }
711 } 728 }
712 729
@@ -779,83 +796,29 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
779 796
780 SceneObjectGroup group = null; 797 SceneObjectGroup group = null;
781 798
782 string xmlData = Utils.BytesToString(rezAsset.Data); 799 List<SceneObjectGroup> objlist;
783 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(); 800 List<Vector3> veclist;
784 List<Vector3> veclist = new List<Vector3>(); 801 Vector3 bbox;
802 float offsetHeight;
785 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); 803 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
786 Vector3 pos; 804 Vector3 pos;
787 805
788 XmlDocument doc = new XmlDocument(); 806 bool single = m_Scene.GetObjectsToRez(rezAsset.Data, attachment, out objlist, out veclist, out bbox, out offsetHeight);
789 doc.LoadXml(xmlData);
790 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
791 Vector3 rez_pos;
792 if (e == null || attachment) // Single
793 {
794 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
795 if (!attachment)
796 {
797 g.RootPart.AttachPoint = g.RootPart.Shape.State;
798 g.RootPart.AttachOffset = g.AbsolutePosition;
799 g.RootPart.AttachRotation = g.GroupRotation;
800 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
801 g.RootPart.Shape.PCode != (byte)PCode.Tree)
802 g.RootPart.Shape.State = 0;
803 }
804 807
805 objlist.Add(g); 808 if (single)
806 veclist.Add(new Vector3(0, 0, 0)); 809 {
807
808 float offsetHeight = 0;
809 pos = m_Scene.GetNewRezLocation( 810 pos = m_Scene.GetNewRezLocation(
810 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 811 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
811 BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false); 812 BypassRayCast, bRayEndIsIntersection, true, bbox, false);
812 pos.Z += offsetHeight; 813 pos.Z += offsetHeight;
813 rez_pos = pos;
814 } 814 }
815 else 815 else
816 { 816 {
817 XmlElement coll = (XmlElement)e;
818 float bx = Convert.ToSingle(coll.GetAttribute("x"));
819 float by = Convert.ToSingle(coll.GetAttribute("y"));
820 float bz = Convert.ToSingle(coll.GetAttribute("z"));
821 Vector3 bbox = new Vector3(bx, by, bz);
822
823 pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, 817 pos = m_Scene.GetNewRezLocation(RayStart, RayEnd,
824 RayTargetID, Quaternion.Identity, 818 RayTargetID, Quaternion.Identity,
825 BypassRayCast, bRayEndIsIntersection, true, 819 BypassRayCast, bRayEndIsIntersection, true,
826 bbox, false); 820 bbox, false);
827
828 rez_pos = pos;
829
830 pos -= bbox / 2; 821 pos -= bbox / 2;
831
832 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
833 foreach (XmlNode n in groups)
834 {
835 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
836 g.RootPart.AttachPoint = g.RootPart.Shape.State;
837 g.RootPart.AttachOffset = g.AbsolutePosition;
838 g.RootPart.AttachRotation = g.GroupRotation;
839 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
840 g.RootPart.Shape.PCode != (byte)PCode.Tree)
841 g.RootPart.Shape.State = 0;
842
843 objlist.Add(g);
844 XmlElement el = (XmlElement)n;
845
846 string rawX = el.GetAttribute("offsetx");
847 string rawY = el.GetAttribute("offsety");
848 string rawZ = el.GetAttribute("offsetz");
849//
850// m_log.DebugFormat(
851// "[INVENTORY ACCESS MODULE]: Converting coalesced object {0} offset <{1}, {2}, {3}>",
852// g.Name, rawX, rawY, rawZ);
853
854 float x = Convert.ToSingle(rawX);
855 float y = Convert.ToSingle(rawY);
856 float z = Convert.ToSingle(rawZ);
857 veclist.Add(new Vector3(x, y, z));
858 }
859 } 822 }
860 823
861 int primcount = 0; 824 int primcount = 0;
@@ -863,7 +826,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
863 primcount += g.PrimCount; 826 primcount += g.PrimCount;
864 827
865 if (!m_Scene.Permissions.CanRezObject( 828 if (!m_Scene.Permissions.CanRezObject(
866 primcount, remoteClient.AgentId, rez_pos) 829 primcount, remoteClient.AgentId, pos)
867 && !attachment) 830 && !attachment)
868 { 831 {
869 // The client operates in no fail mode. It will 832 // The client operates in no fail mode. It will
@@ -880,7 +843,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
880 return null; 843 return null;
881 } 844 }
882 845
883 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, rez_pos, attachment)) 846 if (item != null && !DoPreRezWhenFromItem(remoteClient, item, objlist, pos, veclist, attachment))
884 return null; 847 return null;
885 848
886 for (int i = 0; i < objlist.Count; i++) 849 for (int i = 0; i < objlist.Count; i++)
@@ -900,11 +863,23 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
900 m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3"); 863 m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3");
901 } 864 }
902 865
903 foreach (SceneObjectPart part in group.Parts) 866 // if this was previously an attachment and is now being rezzed,
867 // save the old attachment info.
868 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
904 { 869 {
905 // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset. 870 group.RootPart.AttachedPos = group.AbsolutePosition;
906 part.LastOwnerID = part.OwnerID; 871 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
907 part.OwnerID = remoteClient.AgentId; 872 }
873
874 if (item == null)
875 {
876 // Change ownership. Normally this is done in DoPreRezWhenFromItem(), but in this case we must do it here.
877 foreach (SceneObjectPart part in group.Parts)
878 {
879 // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset.
880 part.LastOwnerID = part.OwnerID;
881 part.OwnerID = remoteClient.AgentId;
882 }
908 } 883 }
909 884
910 if (!attachment) 885 if (!attachment)
@@ -979,10 +954,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
979 /// <param name="item"></param> 954 /// <param name="item"></param>
980 /// <param name="objlist"></param> 955 /// <param name="objlist"></param>
981 /// <param name="pos"></param> 956 /// <param name="pos"></param>
957 /// <param name="veclist">
958 /// List of vector position adjustments for a coalesced objects. For ordinary objects
959 /// this list will contain just Vector3.Zero. The order of adjustments must match the order of objlist
960 /// </param>
982 /// <param name="isAttachment"></param> 961 /// <param name="isAttachment"></param>
983 /// <returns>true if we can processed with rezzing, false if we need to abort</returns> 962 /// <returns>true if we can processed with rezzing, false if we need to abort</returns>
984 private bool DoPreRezWhenFromItem( 963 private bool DoPreRezWhenFromItem(
985 IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist, Vector3 pos, bool isAttachment) 964 IClientAPI remoteClient, InventoryItemBase item, List<SceneObjectGroup> objlist,
965 Vector3 pos, List<Vector3> veclist, bool isAttachment)
986 { 966 {
987 UUID fromUserInventoryItemId = UUID.Zero; 967 UUID fromUserInventoryItemId = UUID.Zero;
988 968
@@ -1005,28 +985,29 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1005 } 985 }
1006 } 986 }
1007 987
1008 int primcount = 0; 988 for (int i = 0; i < objlist.Count; i++)
1009 foreach (SceneObjectGroup g in objlist)
1010 primcount += g.PrimCount;
1011
1012 if (!m_Scene.Permissions.CanRezObject(
1013 primcount, remoteClient.AgentId, pos)
1014 && !isAttachment)
1015 { 989 {
1016 // The client operates in no fail mode. It will 990 SceneObjectGroup g = objlist[i];
1017 // have already removed the item from the folder
1018 // if it's no copy.
1019 // Put it back if it's not an attachment
1020 //
1021 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment))
1022 remoteClient.SendBulkUpdateInventory(item);
1023 991
1024 ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); 992 if (!m_Scene.Permissions.CanRezObject(
1025 remoteClient.SendAlertMessage(string.Format( 993 g.PrimCount, remoteClient.AgentId, pos + veclist[i])
1026 "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.", 994 && !isAttachment)
1027 item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.RegionInfo.RegionName)); 995 {
996 // The client operates in no fail mode. It will
997 // have already removed the item from the folder
998 // if it's no copy.
999 // Put it back if it's not an attachment
1000 //
1001 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment))
1002 remoteClient.SendBulkUpdateInventory(item);
1028 1003
1029 return false; 1004 ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y);
1005 remoteClient.SendAlertMessage(string.Format(
1006 "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.",
1007 item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.Name));
1008
1009 return false;
1010 }
1030 } 1011 }
1031 1012
1032 for (int i = 0; i < objlist.Count; i++) 1013 for (int i = 0; i < objlist.Count; i++)
@@ -1107,7 +1088,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1107 part.GroupMask = item.GroupPermissions; 1088 part.GroupMask = item.GroupPermissions;
1108 } 1089 }
1109 } 1090 }
1110 1091
1111 rootPart.TrimPermissions(); 1092 rootPart.TrimPermissions();
1112 1093
1113 if (isAttachment) 1094 if (isAttachment)
diff --git a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
index d07cff4..69d7e16 100644
--- a/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Library/LibraryModule.cs
@@ -176,7 +176,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library
176 m_log.InfoFormat("[LIBRARY MODULE]: Loading library archive {0} ({1})...", iarFileName, simpleName); 176 m_log.InfoFormat("[LIBRARY MODULE]: Loading library archive {0} ({1})...", iarFileName, simpleName);
177 simpleName = GetInventoryPathFromName(simpleName); 177 simpleName = GetInventoryPathFromName(simpleName);
178 178
179 InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, simpleName, iarFileName, false); 179 InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene.InventoryService, m_MockScene.AssetService, m_MockScene.UserAccountService, uinfo, simpleName, iarFileName, false);
180 try 180 try
181 { 181 {
182 HashSet<InventoryNodeBase> nodes = archread.Execute(); 182 HashSet<InventoryNodeBase> nodes = archread.Execute();
@@ -185,7 +185,7 @@ namespace OpenSim.Region.CoreModules.Framework.Library
185 // didn't find the subfolder with the given name; place it on the top 185 // didn't find the subfolder with the given name; place it on the top
186 m_log.InfoFormat("[LIBRARY MODULE]: Didn't find {0} in library. Placing archive on the top level", simpleName); 186 m_log.InfoFormat("[LIBRARY MODULE]: Didn't find {0} in library. Placing archive on the top level", simpleName);
187 archread.Close(); 187 archread.Close();
188 archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, "/", iarFileName, false); 188 archread = new InventoryArchiveReadRequest(m_MockScene.InventoryService, m_MockScene.AssetService, m_MockScene.UserAccountService, uinfo, "/", iarFileName, false);
189 archread.Execute(); 189 archread.Execute();
190 } 190 }
191 191
diff --git a/OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs b/OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs
new file mode 100644
index 0000000..8838612
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/Search/BasicSearchModule.cs
@@ -0,0 +1,197 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.IO;
30using System.Reflection;
31using System.Threading;
32
33using OpenSim.Framework;
34using OpenSim.Framework.Console;
35using OpenSim.Framework.Monitoring;
36using OpenSim.Region.ClientStack.LindenUDP;
37using OpenSim.Region.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Services.Connectors.Hypergrid;
42
43using OpenMetaverse;
44using OpenMetaverse.Packets;
45using log4net;
46using Nini.Config;
47using Mono.Addins;
48
49using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
50
51namespace OpenSim.Region.CoreModules.Framework.Search
52{
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BasicSearchModule")]
54 public class BasicSearchModule : ISharedRegionModule
55 {
56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
57
58 protected bool m_Enabled;
59 protected List<Scene> m_Scenes = new List<Scene>();
60
61 private IGroupsModule m_GroupsService = null;
62
63 #region ISharedRegionModule
64
65 public void Initialise(IConfigSource config)
66 {
67 string umanmod = config.Configs["Modules"].GetString("SearchModule", Name);
68 if (umanmod == Name)
69 {
70 m_Enabled = true;
71 m_log.DebugFormat("[BASIC SEARCH MODULE]: {0} is enabled", Name);
72 }
73 }
74
75 public bool IsSharedModule
76 {
77 get { return true; }
78 }
79
80 public virtual string Name
81 {
82 get { return "BasicSearchModule"; }
83 }
84
85 public Type ReplaceableInterface
86 {
87 get { return null; }
88 }
89
90 public void AddRegion(Scene scene)
91 {
92 if (m_Enabled)
93 {
94 m_Scenes.Add(scene);
95
96 scene.EventManager.OnMakeRootAgent += new Action<ScenePresence>(EventManager_OnMakeRootAgent);
97 scene.EventManager.OnMakeChildAgent += new EventManager.OnMakeChildAgentDelegate(EventManager_OnMakeChildAgent);
98 }
99 }
100
101 public void RemoveRegion(Scene scene)
102 {
103 if (m_Enabled)
104 {
105 m_Scenes.Remove(scene);
106
107 scene.EventManager.OnMakeRootAgent -= new Action<ScenePresence>(EventManager_OnMakeRootAgent);
108 scene.EventManager.OnMakeChildAgent -= new EventManager.OnMakeChildAgentDelegate(EventManager_OnMakeChildAgent);
109 }
110 }
111
112 public void RegionLoaded(Scene s)
113 {
114 if (!m_Enabled)
115 return;
116
117 if (m_GroupsService == null)
118 {
119 m_GroupsService = s.RequestModuleInterface<IGroupsModule>();
120
121 // No Groups Service Connector, then group search won't work...
122 if (m_GroupsService == null)
123 m_log.Warn("[BASIC SEARCH MODULE]: Could not get IGroupsModule");
124 }
125 }
126
127 public void PostInitialise()
128 {
129 }
130
131 public void Close()
132 {
133 m_Scenes.Clear();
134 }
135
136 #endregion ISharedRegionModule
137
138
139 #region Event Handlers
140
141 void EventManager_OnMakeRootAgent(ScenePresence sp)
142 {
143 sp.ControllingClient.OnDirFindQuery += OnDirFindQuery;
144 }
145
146 void EventManager_OnMakeChildAgent(ScenePresence sp)
147 {
148 sp.ControllingClient.OnDirFindQuery -= OnDirFindQuery;
149 }
150
151 void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart)
152 {
153 if (((DirFindFlags)queryFlags & DirFindFlags.People) == DirFindFlags.People)
154 {
155 if (string.IsNullOrEmpty(queryText))
156 remoteClient.SendDirPeopleReply(queryID, new DirPeopleReplyData[0]);
157
158 List<UserAccount> accounts = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, queryText);
159 DirPeopleReplyData[] hits = new DirPeopleReplyData[accounts.Count];
160 int i = 0;
161 foreach (UserAccount acc in accounts)
162 {
163 DirPeopleReplyData d = new DirPeopleReplyData();
164 d.agentID = acc.PrincipalID;
165 d.firstName = acc.FirstName;
166 d.lastName = acc.LastName;
167 d.online = false;
168
169 hits[i++] = d;
170 }
171
172 // TODO: This currently ignores pretty much all the query flags including Mature and sort order
173 remoteClient.SendDirPeopleReply(queryID, hits);
174 }
175 else if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups)
176 {
177 if (m_GroupsService == null)
178 {
179 m_log.Warn("[BASIC SEARCH MODULE]: Groups service is not available. Unable to search groups.");
180 remoteClient.SendAlertMessage("Groups search is not enabled");
181 return;
182 }
183
184 if (string.IsNullOrEmpty(queryText))
185 remoteClient.SendDirGroupsReply(queryID, new DirGroupsReplyData[0]);
186
187 // TODO: This currently ignores pretty much all the query flags including Mature and sort order
188 remoteClient.SendDirGroupsReply(queryID, m_GroupsService.FindGroups(remoteClient, queryText).ToArray());
189 }
190
191 }
192
193 #endregion Event Handlers
194
195 }
196
197} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
new file mode 100644
index 0000000..a70261e
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs
@@ -0,0 +1,256 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32using log4net;
33using Mono.Addins;
34using Nini.Config;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Framework.Monitoring;
39using OpenSim.Region.Framework.Scenes;
40using GridRegion = OpenSim.Services.Interfaces.GridRegion;
41
42namespace OpenSim.Region.CoreModules.Framework
43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "GridServiceThrottleModule")]
45 public class ServiceThrottleModule : ISharedRegionModule, IServiceThrottleModule
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 private readonly List<Scene> m_scenes = new List<Scene>();
51 private System.Timers.Timer m_timer = new System.Timers.Timer();
52
53 private Queue<Action> m_RequestQueue = new Queue<Action>();
54 private Dictionary<string, List<string>> m_Pending = new Dictionary<string, List<string>>();
55 private int m_Interval;
56
57 #region ISharedRegionModule
58
59 public void Initialise(IConfigSource config)
60 {
61 m_Interval = Util.GetConfigVarFromSections<int>(config, "Interval", new string[] { "ServiceThrottle" }, 5000);
62
63 m_timer = new System.Timers.Timer();
64 m_timer.AutoReset = false;
65 m_timer.Enabled = true;
66 m_timer.Interval = 15000; // 15 secs at first
67 m_timer.Elapsed += ProcessQueue;
68 m_timer.Start();
69
70 //Watchdog.StartThread(
71 // ProcessQueue,
72 // "GridServiceRequestThread",
73 // ThreadPriority.BelowNormal,
74 // true,
75 // false);
76 }
77
78 public void AddRegion(Scene scene)
79 {
80 lock (m_scenes)
81 {
82 m_scenes.Add(scene);
83 scene.RegisterModuleInterface<IServiceThrottleModule>(this);
84 scene.EventManager.OnNewClient += OnNewClient;
85 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
86 }
87 }
88
89 public void RegionLoaded(Scene scene)
90 {
91 }
92
93 public void RemoveRegion(Scene scene)
94 {
95 lock (m_scenes)
96 {
97 m_scenes.Remove(scene);
98 scene.EventManager.OnNewClient -= OnNewClient;
99 }
100 }
101
102 public void PostInitialise()
103 {
104 }
105
106 public void Close()
107 {
108 }
109
110 public string Name
111 {
112 get { return "ServiceThrottleModule"; }
113 }
114
115 public Type ReplaceableInterface
116 {
117 get { return null; }
118 }
119
120 #endregion ISharedRegionMOdule
121
122 #region Events
123
124 void OnNewClient(IClientAPI client)
125 {
126 client.OnRegionHandleRequest += OnRegionHandleRequest;
127 }
128
129 void OnMakeRootAgent(ScenePresence obj)
130 {
131 lock (m_timer)
132 {
133 if (!m_timer.Enabled)
134 {
135 m_timer.Interval = m_Interval;
136 m_timer.Enabled = true;
137 m_timer.Start();
138 }
139 }
140 }
141
142 public void OnRegionHandleRequest(IClientAPI client, UUID regionID)
143 {
144 //m_log.DebugFormat("[SERVICE THROTTLE]: RegionHandleRequest {0}", regionID);
145 ulong handle = 0;
146 if (IsLocalRegionHandle(regionID, out handle))
147 {
148 client.SendRegionHandle(regionID, handle);
149 return;
150 }
151
152 Action action = delegate
153 {
154 GridRegion r = m_scenes[0].GridService.GetRegionByUUID(UUID.Zero, regionID);
155
156 if (r != null && r.RegionHandle != 0)
157 client.SendRegionHandle(regionID, r.RegionHandle);
158 };
159
160 Enqueue("region", regionID.ToString(), action);
161 }
162
163 #endregion Events
164
165 #region IServiceThrottleModule
166
167 public void Enqueue(string category, string itemid, Action continuation)
168 {
169 lock (m_RequestQueue)
170 {
171 if (m_Pending.ContainsKey(category))
172 {
173 if (m_Pending[category].Contains(itemid))
174 // Don't enqueue, it's already pending
175 return;
176 }
177 else
178 m_Pending.Add(category, new List<string>());
179
180 m_Pending[category].Add(itemid);
181
182 m_RequestQueue.Enqueue(delegate
183 {
184 lock (m_RequestQueue)
185 m_Pending[category].Remove(itemid);
186
187 continuation();
188 });
189 }
190 }
191
192 #endregion IServiceThrottleModule
193
194 #region Process Continuation Queue
195
196 private void ProcessQueue(object sender, System.Timers.ElapsedEventArgs e)
197 {
198 //m_log.DebugFormat("[YYY]: Process queue with {0} continuations", m_RequestQueue.Count);
199
200 while (m_RequestQueue.Count > 0)
201 {
202 Action continuation = null;
203 lock (m_RequestQueue)
204 continuation = m_RequestQueue.Dequeue();
205
206 if (continuation != null)
207 continuation();
208 }
209
210 if (AreThereRootAgents())
211 {
212 lock (m_timer)
213 {
214 m_timer.Interval = 1000; // 1 sec
215 m_timer.Enabled = true;
216 m_timer.Start();
217 }
218 }
219 else
220 lock (m_timer)
221 m_timer.Enabled = false;
222
223 }
224
225 #endregion Process Continuation Queue
226
227 #region Misc
228
229 private bool IsLocalRegionHandle(UUID regionID, out ulong regionHandle)
230 {
231 regionHandle = 0;
232 foreach (Scene s in m_scenes)
233 if (s.RegionInfo.RegionID == regionID)
234 {
235 regionHandle = s.RegionInfo.RegionHandle;
236 return true;
237 }
238 return false;
239 }
240
241 private bool AreThereRootAgents()
242 {
243 foreach (Scene s in m_scenes)
244 {
245 foreach (ScenePresence sp in s.GetScenePresences())
246 if (!sp.IsChildAgent)
247 return true;
248 }
249
250 return false;
251 }
252
253 #endregion Misc
254 }
255
256}
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
index 8ce20e9..245c808 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
@@ -54,11 +54,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
54 54
55 public new void Initialise(IConfigSource config) 55 public new void Initialise(IConfigSource config)
56 { 56 {
57 string umanmod = config.Configs["Modules"].GetString("UserManagementModule", Name); 57 string umanmod = config.Configs["Modules"].GetString("UserManagementModule", null);
58 if (umanmod == Name) 58 if (umanmod == Name)
59 { 59 {
60 m_Enabled = true; 60 m_Enabled = true;
61 RegisterConsoleCmds(); 61 Init();
62 m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name); 62 m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name);
63 } 63 }
64 } 64 }
@@ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
70 70
71 #endregion ISharedRegionModule 71 #endregion ISharedRegionModule
72 72
73 protected override void AddAdditionalUsers(UUID avatarID, string query, List<UserData> users) 73 protected override void AddAdditionalUsers(string query, List<UserData> users)
74 { 74 {
75 if (query.Contains("@")) // First.Last@foo.com, maybe? 75 if (query.Contains("@")) // First.Last@foo.com, maybe?
76 { 76 {
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs
new file mode 100644
index 0000000..9d36aa5
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/Tests/HGUserManagementModuleTests.cs
@@ -0,0 +1,76 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using Nini.Config;
30using NUnit.Framework;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.CoreModules.Framework.UserManagement;
34using OpenSim.Tests.Common;
35using OpenSim.Tests.Common.Mock;
36
37namespace OpenSim.Region.CoreModules.Framework.UserManagement.Tests
38{
39 [TestFixture]
40 public class HGUserManagementModuleTests : OpenSimTestCase
41 {
42 /// <summary>
43 /// Test that a new HG agent (i.e. one without a user account) has their name cached in the UMM upon creation.
44 /// </summary>
45 [Test]
46 public void TestCachedUserNameForNewAgent()
47 {
48 TestHelpers.InMethod();
49// TestHelpers.EnableLogging();
50
51 HGUserManagementModule hgumm = new HGUserManagementModule();
52 UUID userId = TestHelpers.ParseStem("11");
53 string firstName = "Fred";
54 string lastName = "Astaire";
55 string homeUri = "example.com";
56
57 IConfigSource config = new IniConfigSource();
58 config.AddConfig("Modules");
59 config.Configs["Modules"].Set("UserManagementModule", hgumm.Name);
60
61 SceneHelpers sceneHelpers = new SceneHelpers();
62 TestScene scene = sceneHelpers.SetupScene();
63 SceneHelpers.SetupSceneModules(scene, config, hgumm);
64
65 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
66 acd.firstname = firstName;
67 acd.lastname = lastName;
68 acd.ServiceURLs["HomeURI"] = "http://" + homeUri;
69
70 SceneHelpers.AddScenePresence(scene, acd);
71
72 string name = hgumm.GetUserName(userId);
73 Assert.That(name, Is.EqualTo(string.Format("{0}.{1} @{2}", firstName, lastName, homeUri)));
74 }
75 }
76} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 77e8b00..3fb5195 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -28,9 +28,11 @@ using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.IO; 29using System.IO;
30using System.Reflection; 30using System.Reflection;
31using System.Threading;
31 32
32using OpenSim.Framework; 33using OpenSim.Framework;
33using OpenSim.Framework.Console; 34using OpenSim.Framework.Console;
35using OpenSim.Framework.Monitoring;
34using OpenSim.Region.ClientStack.LindenUDP; 36using OpenSim.Region.ClientStack.LindenUDP;
35using OpenSim.Region.Framework; 37using OpenSim.Region.Framework;
36using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
@@ -44,25 +46,19 @@ using log4net;
44using Nini.Config; 46using Nini.Config;
45using Mono.Addins; 47using Mono.Addins;
46 48
49using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
50
47namespace OpenSim.Region.CoreModules.Framework.UserManagement 51namespace OpenSim.Region.CoreModules.Framework.UserManagement
48{ 52{
49 public class UserData
50 {
51 public UUID Id { get; set; }
52 public string FirstName { get; set; }
53 public string LastName { get; set; }
54 public string HomeURL { get; set; }
55 public Dictionary<string, object> ServerURLs { get; set; }
56 }
57
58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")] 53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")]
59 public class UserManagementModule : ISharedRegionModule, IUserManagement 54 public class UserManagementModule : ISharedRegionModule, IUserManagement, IPeople
60 { 55 {
61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62 57
63 protected bool m_Enabled; 58 protected bool m_Enabled;
64 protected List<Scene> m_Scenes = new List<Scene>(); 59 protected List<Scene> m_Scenes = new List<Scene>();
65 60
61 protected IServiceThrottleModule m_ServiceThrottle;
66 // The cache 62 // The cache
67 protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>(); 63 protected Dictionary<UUID, UserData> m_UserCache = new Dictionary<UUID, UserData>();
68 64
@@ -74,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
74 if (umanmod == Name) 70 if (umanmod == Name)
75 { 71 {
76 m_Enabled = true; 72 m_Enabled = true;
77 RegisterConsoleCmds(); 73 Init();
78 m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name); 74 m_log.DebugFormat("[USER MANAGEMENT MODULE]: {0} is enabled", Name);
79 } 75 }
80 } 76 }
@@ -101,6 +97,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
101 m_Scenes.Add(scene); 97 m_Scenes.Add(scene);
102 98
103 scene.RegisterModuleInterface<IUserManagement>(this); 99 scene.RegisterModuleInterface<IUserManagement>(this);
100 scene.RegisterModuleInterface<IPeople>(this);
104 scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); 101 scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient);
105 scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); 102 scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded);
106 } 103 }
@@ -117,6 +114,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
117 114
118 public void RegionLoaded(Scene s) 115 public void RegionLoaded(Scene s)
119 { 116 {
117 if (m_Enabled && m_ServiceThrottle == null)
118 m_ServiceThrottle = s.RequestModuleInterface<IServiceThrottleModule>();
120 } 119 }
121 120
122 public void PostInitialise() 121 public void PostInitialise()
@@ -143,7 +142,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
143 s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); }); 142 s.ForEachSOG(delegate(SceneObjectGroup sog) { CacheCreators(sog); });
144 } 143 }
145 144
146
147 void EventManager_OnNewClient(IClientAPI client) 145 void EventManager_OnNewClient(IClientAPI client)
148 { 146 {
149 client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed); 147 client.OnConnectionClosed += new Action<IClientAPI>(HandleConnectionClosed);
@@ -157,21 +155,43 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
157 client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest); 155 client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest);
158 } 156 }
159 157
160 void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client) 158 void HandleUUIDNameRequest(UUID uuid, IClientAPI client)
161 { 159 {
160// m_log.DebugFormat(
161// "[USER MANAGEMENT MODULE]: Handling request for name binding of UUID {0} from {1}",
162// uuid, remote_client.Name);
163
162 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) 164 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
163 { 165 {
164 remote_client.SendNameReply(uuid, "Mr", "OpenSim"); 166 client.SendNameReply(uuid, "Mr", "OpenSim");
165 } 167 }
166 else 168 else
167 { 169 {
168 string[] names = GetUserNames(uuid); 170 string[] names = new string[2];
169 if (names.Length == 2) 171 if (TryGetUserNamesFromCache(uuid, names))
170 { 172 {
171 //m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0} is {1} {2}", uuid, names[0], names[1]); 173 client.SendNameReply(uuid, names[0], names[1]);
172 remote_client.SendNameReply(uuid, names[0], names[1]); 174 return;
173 } 175 }
174 176
177 // Not found in cache, queue continuation
178 m_ServiceThrottle.Enqueue("name", uuid.ToString(), delegate
179 {
180 //m_log.DebugFormat("[YYY]: Name request {0}", uuid);
181
182 // As least upto September 2013, clients permanently cache UUID -> Name bindings. Some clients
183 // appear to clear this when the user asks it to clear the cache, but others may not.
184 //
185 // So to avoid clients
186 // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will
187 // instead drop the request entirely.
188 if (TryGetUserNames(uuid, names))
189 client.SendNameReply(uuid, names[0], names[1]);
190// else
191// m_log.DebugFormat(
192// "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}",
193// uuid, client.Name);
194 });
175 } 195 }
176 } 196 }
177 197
@@ -181,29 +201,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
181 201
182 m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); 202 m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query);
183 203
184 // searhc the user accounts service 204 List<UserData> users = GetUserData(query, 500, 1);
185 List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query);
186
187 List<UserData> users = new List<UserData>();
188 if (accs != null)
189 {
190 foreach (UserAccount acc in accs)
191 {
192 UserData ud = new UserData();
193 ud.FirstName = acc.FirstName;
194 ud.LastName = acc.LastName;
195 ud.Id = acc.PrincipalID;
196 users.Add(ud);
197 }
198 }
199
200 // search the local cache
201 foreach (UserData data in m_UserCache.Values)
202 if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null &&
203 (data.FirstName.StartsWith(query) || data.LastName.StartsWith(query)))
204 users.Add(data);
205
206 AddAdditionalUsers(avatarID, query, users);
207 205
208 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); 206 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
209 // TODO: don't create new blocks if recycling an old packet 207 // TODO: don't create new blocks if recycling an old packet
@@ -249,12 +247,51 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
249 client.SendAvatarPickerReply(agent_data, data_args); 247 client.SendAvatarPickerReply(agent_data, data_args);
250 } 248 }
251 249
252 protected virtual void AddAdditionalUsers(UUID avatarID, string query, List<UserData> users) 250 protected virtual void AddAdditionalUsers(string query, List<UserData> users)
253 { 251 {
254 } 252 }
255 253
256 #endregion Event Handlers 254 #endregion Event Handlers
257 255
256 #region IPeople
257
258 public List<UserData> GetUserData(string query, int page_size, int page_number)
259 {
260 // search the user accounts service
261 List<UserAccount> accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query);
262
263 List<UserData> users = new List<UserData>();
264 if (accs != null)
265 {
266 foreach (UserAccount acc in accs)
267 {
268 UserData ud = new UserData();
269 ud.FirstName = acc.FirstName;
270 ud.LastName = acc.LastName;
271 ud.Id = acc.PrincipalID;
272 users.Add(ud);
273 }
274 }
275
276 // search the local cache
277 lock (m_UserCache)
278 {
279 foreach (UserData data in m_UserCache.Values)
280 {
281 if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null &&
282 (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower())))
283 users.Add(data);
284 }
285 }
286
287 AddAdditionalUsers(query, users);
288
289 return users;
290
291 }
292
293 #endregion IPeople
294
258 private void CacheCreators(SceneObjectGroup sog) 295 private void CacheCreators(SceneObjectGroup sog)
259 { 296 {
260 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification); 297 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification);
@@ -268,26 +305,56 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
268 } 305 }
269 } 306 }
270 307
271 private string[] GetUserNames(UUID uuid) 308 /// <summary>
309 ///
310 /// </summary>
311 /// <param name="uuid"></param>
312 /// <param name="names">Caller please provide a properly instantiated array for names, string[2]</param>
313 /// <returns></returns>
314 private bool TryGetUserNames(UUID uuid, string[] names)
272 { 315 {
273 string[] returnstring = new string[2]; 316 if (names == null)
317 names = new string[2];
318
319 if (TryGetUserNamesFromCache(uuid, names))
320 return true;
321
322 if (TryGetUserNamesFromServices(uuid, names))
323 return true;
324
325 return false;
326 }
274 327
328 private bool TryGetUserNamesFromCache(UUID uuid, string[] names)
329 {
275 lock (m_UserCache) 330 lock (m_UserCache)
276 { 331 {
277 if (m_UserCache.ContainsKey(uuid)) 332 if (m_UserCache.ContainsKey(uuid))
278 { 333 {
279 returnstring[0] = m_UserCache[uuid].FirstName; 334 names[0] = m_UserCache[uuid].FirstName;
280 returnstring[1] = m_UserCache[uuid].LastName; 335 names[1] = m_UserCache[uuid].LastName;
281 return returnstring; 336
337 return true;
282 } 338 }
283 } 339 }
284 340
341 return false;
342 }
343
344 /// <summary>
345 /// Try to get the names bound to the given uuid, from the services.
346 /// </summary>
347 /// <returns>True if the name was found, false if not.</returns>
348 /// <param name='uuid'></param>
349 /// <param name='names'>The array of names if found. If not found, then names[0] = "Unknown" and names[1] = "User"</param>
350 private bool TryGetUserNamesFromServices(UUID uuid, string[] names)
351 {
285 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid); 352 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(UUID.Zero, uuid);
286 353
287 if (account != null) 354 if (account != null)
288 { 355 {
289 returnstring[0] = account.FirstName; 356 names[0] = account.FirstName;
290 returnstring[1] = account.LastName; 357 names[1] = account.LastName;
291 358
292 UserData user = new UserData(); 359 UserData user = new UserData();
293 user.FirstName = account.FirstName; 360 user.FirstName = account.FirstName;
@@ -295,14 +362,42 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
295 362
296 lock (m_UserCache) 363 lock (m_UserCache)
297 m_UserCache[uuid] = user; 364 m_UserCache[uuid] = user;
365
366 return true;
298 } 367 }
299 else 368 else
300 { 369 {
301 returnstring[0] = "Unknown"; 370 // Let's try the GridUser service
302 returnstring[1] = "User"; 371 GridUserInfo uInfo = m_Scenes[0].GridUserService.GetGridUserInfo(uuid.ToString());
303 } 372 if (uInfo != null)
373 {
374 string url, first, last, tmp;
375 UUID u;
376 if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out u, out url, out first, out last, out tmp))
377 {
378 AddUser(uuid, first, last, url);
379
380 if (m_UserCache.ContainsKey(uuid))
381 {
382 names[0] = m_UserCache[uuid].FirstName;
383 names[1] = m_UserCache[uuid].LastName;
384
385 return true;
386 }
387 }
388 else
389 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Unable to parse UUI {0}", uInfo.UserID);
390 }
391 else
392 {
393 m_log.DebugFormat("[USER MANAGEMENT MODULE]: No grid user found for {0}", uuid);
394 }
304 395
305 return returnstring; 396 names[0] = "Unknown";
397 names[1] = "UserUMMTGUN9";
398
399 return false;
400 }
306 } 401 }
307 402
308 #region IUserManagement 403 #region IUserManagement
@@ -338,16 +433,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
338 433
339 public string GetUserName(UUID uuid) 434 public string GetUserName(UUID uuid)
340 { 435 {
341 string[] names = GetUserNames(uuid); 436 string[] names = new string[2];
342 if (names.Length == 2) 437 TryGetUserNames(uuid, names);
343 {
344 string firstname = names[0];
345 string lastname = names[1];
346 438
347 return firstname + " " + lastname; 439 return names[0] + " " + names[1];
348 440
349 }
350 return "(hippos)";
351 } 441 }
352 442
353 public string GetUserHomeURL(UUID userID) 443 public string GetUserHomeURL(UUID userID)
@@ -376,7 +466,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
376 return userdata.ServerURLs[serverType].ToString(); 466 return userdata.ServerURLs[serverType].ToString();
377 } 467 }
378 468
379 if (userdata.HomeURL != null && userdata.HomeURL != string.Empty) 469 if (!string.IsNullOrEmpty(userdata.HomeURL))
380 { 470 {
381 //m_log.DebugFormat( 471 //m_log.DebugFormat(
382 // "[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}", 472 // "[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}",
@@ -394,14 +484,20 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
394 484
395 public string GetUserUUI(UUID userID) 485 public string GetUserUUI(UUID userID)
396 { 486 {
397 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID);
398 if (account != null)
399 return userID.ToString();
400
401 UserData ud; 487 UserData ud;
402 lock (m_UserCache) 488 lock (m_UserCache)
403 m_UserCache.TryGetValue(userID, out ud); 489 m_UserCache.TryGetValue(userID, out ud);
404 490
491 if (ud == null) // It's not in the cache
492 {
493 string[] names = new string[2];
494 // This will pull the data from either UserAccounts or GridUser
495 // and stick it into the cache
496 TryGetUserNamesFromServices(userID, names);
497 lock (m_UserCache)
498 m_UserCache.TryGetValue(userID, out ud);
499 }
500
405 if (ud != null) 501 if (ud != null)
406 { 502 {
407 string homeURL = ud.HomeURL; 503 string homeURL = ud.HomeURL;
@@ -446,77 +542,81 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
446 AddUser(uuid, homeURL + ";" + first + " " + last); 542 AddUser(uuid, homeURL + ";" + first + " " + last);
447 } 543 }
448 544
449 public void AddUser (UUID id, string creatorData) 545 public void AddUser(UUID id, string creatorData)
450 { 546 {
451 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData); 547 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);
452 548
453 UserData oldUser; 549 UserData oldUser;
454 //lock the whole block - prevent concurrent update
455 lock (m_UserCache) 550 lock (m_UserCache)
551 m_UserCache.TryGetValue(id, out oldUser);
552
553 if (oldUser != null)
456 { 554 {
457 m_UserCache.TryGetValue (id, out oldUser); 555 if (string.IsNullOrEmpty(creatorData))
458 if (oldUser != null)
459 { 556 {
460 if (creatorData == null || creatorData == String.Empty) 557 //ignore updates without creator data
461 { 558 return;
462 //ignore updates without creator data
463 return;
464 }
465 //try update unknown users
466 //and creator's home URL's
467 if ((oldUser.FirstName == "Unknown" && !creatorData.Contains ("Unknown")) || (oldUser.HomeURL != null && !creatorData.StartsWith (oldUser.HomeURL)))
468 {
469 m_UserCache.Remove (id);
470// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData,oldUser.HomeURL);
471 }
472 else
473 {
474 //we have already a valid user within the cache
475 return;
476 }
477 } 559 }
478 560
479 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount (m_Scenes [0].RegionInfo.ScopeID, id); 561 //try update unknown users, but don't update anyone else
480 562 if (oldUser.FirstName == "Unknown" && !creatorData.Contains("Unknown"))
481 if (account != null)
482 { 563 {
483 AddUser (id, account.FirstName, account.LastName); 564 lock (m_UserCache)
565 m_UserCache.Remove(id);
566 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData, oldUser.HomeURL);
484 } 567 }
485 else 568 else
486 { 569 {
487 UserData user = new UserData (); 570 //we have already a valid user within the cache
488 user.Id = id; 571 return;
572 }
573 }
489 574
490 if (creatorData != null && creatorData != string.Empty) 575 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, id);
491 {
492 //creatorData = <endpoint>;<name>
493 576
494 string[] parts = creatorData.Split (';'); 577 if (account != null)
495 if (parts.Length >= 1) 578 {
579 AddUser(id, account.FirstName, account.LastName);
580 }
581 else
582 {
583 UserData user = new UserData();
584 user.Id = id;
585
586 if (!string.IsNullOrEmpty(creatorData))
587 {
588 //creatorData = <endpoint>;<name>
589
590 string[] parts = creatorData.Split(';');
591 if (parts.Length >= 1)
592 {
593 user.HomeURL = parts[0];
594 try
496 { 595 {
497 user.HomeURL = parts [0]; 596 Uri uri = new Uri(parts[0]);
498 try 597 user.LastName = "@" + uri.Authority;
499 { 598 }
500 Uri uri = new Uri (parts [0]); 599 catch (UriFormatException)
501 user.LastName = "@" + uri.Authority; 600 {
502 } 601 m_log.DebugFormat("[SCENE]: Unable to parse Uri {0}", parts[0]);
503 catch (UriFormatException) 602 user.LastName = "@unknown";
504 {
505 m_log.DebugFormat ("[SCENE]: Unable to parse Uri {0}", parts [0]);
506 user.LastName = "@unknown";
507 }
508 } 603 }
509 if (parts.Length >= 2)
510 user.FirstName = parts [1].Replace (' ', '.');
511 }
512 else
513 {
514 user.FirstName = "Unknown";
515 user.LastName = "User";
516 } 604 }
517 605
518 AddUserInternal (user); 606 if (parts.Length >= 2)
607 user.FirstName = parts[1].Replace(' ', '.');
608 }
609 else
610 {
611 // Temporarily add unknown user entries of this type into the cache so that we can distinguish
612 // this source from other recent (hopefully resolved) bugs that fail to retrieve a user name binding
613 // TODO: Can be removed when GUN* unknown users have definitely dropped significantly or
614 // disappeared.
615 user.FirstName = "Unknown";
616 user.LastName = "UserUMMAU4";
519 } 617 }
618
619 AddUserInternal(user);
520 } 620 }
521 } 621 }
522 622
@@ -541,9 +641,22 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
541 641
542 #endregion IUserManagement 642 #endregion IUserManagement
543 643
644 protected void Init()
645 {
646 AddUser(UUID.Zero, "Unknown", "User");
647 RegisterConsoleCmds();
648 }
649
544 protected void RegisterConsoleCmds() 650 protected void RegisterConsoleCmds()
545 { 651 {
546 MainConsole.Instance.Commands.AddCommand("Users", true, 652 MainConsole.Instance.Commands.AddCommand("Users", true,
653 "show name",
654 "show name <uuid>",
655 "Show the bindings between a single user UUID and a user name",
656 String.Empty,
657 HandleShowUser);
658
659 MainConsole.Instance.Commands.AddCommand("Users", true,
547 "show names", 660 "show names",
548 "show names", 661 "show names",
549 "Show the bindings between user UUIDs and user names", 662 "Show the bindings between user UUIDs and user names",
@@ -551,26 +664,56 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
551 HandleShowUsers); 664 HandleShowUsers);
552 } 665 }
553 666
554 private void HandleShowUsers(string module, string[] cmd) 667 private void HandleShowUser(string module, string[] cmd)
555 { 668 {
669 if (cmd.Length < 3)
670 {
671 MainConsole.Instance.OutputFormat("Usage: show name <uuid>");
672 return;
673 }
674
675 UUID userId;
676 if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, cmd[2], out userId))
677 return;
678
679 string[] names;
680
681 UserData ud;
682
556 lock (m_UserCache) 683 lock (m_UserCache)
557 { 684 {
558 if (m_UserCache.Count == 0) 685 if (!m_UserCache.TryGetValue(userId, out ud))
559 { 686 {
560 MainConsole.Instance.Output("No users found"); 687 MainConsole.Instance.OutputFormat("No name known for user with id {0}", userId);
561 return; 688 return;
562 } 689 }
563 690 }
564 MainConsole.Instance.Output("UUID User Name"); 691
565 MainConsole.Instance.Output("-----------------------------------------------------------------------------"); 692 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
693 cdt.AddColumn("UUID", 36);
694 cdt.AddColumn("Name", 30);
695 cdt.AddColumn("HomeURL", 40);
696 cdt.AddRow(userId, string.Format("{0} {1}", ud.FirstName, ud.LastName), ud.HomeURL);
697
698 MainConsole.Instance.Output(cdt.ToString());
699 }
700
701 private void HandleShowUsers(string module, string[] cmd)
702 {
703 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
704 cdt.AddColumn("UUID", 36);
705 cdt.AddColumn("Name", 30);
706 cdt.AddColumn("HomeURL", 40);
707
708 lock (m_UserCache)
709 {
566 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache) 710 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache)
567 { 711 cdt.AddRow(kvp.Key, string.Format("{0} {1}", kvp.Value.FirstName, kvp.Value.LastName), kvp.Value.HomeURL);
568 MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})",
569 kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL));
570 }
571
572 return;
573 } 712 }
713
714 MainConsole.Instance.Output(cdt.ToString());
574 } 715 }
716
575 } 717 }
718
576} \ No newline at end of file 719} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
index 7b11658..8946b5c 100644
--- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
@@ -31,6 +31,7 @@ using System.Reflection;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
34using Mono.Addins; 35using Mono.Addins;
35using OpenSim.Framework; 36using OpenSim.Framework;
36using OpenSim.Region.CoreModules.World.WorldMap; 37using OpenSim.Region.CoreModules.World.WorldMap;
@@ -48,20 +49,63 @@ namespace OpenSim.Region.CoreModules.Hypergrid
48 // Remember the map area that each client has been exposed to in this region 49 // Remember the map area that each client has been exposed to in this region
49 private Dictionary<UUID, List<MapBlockData>> m_SeenMapBlocks = new Dictionary<UUID, List<MapBlockData>>(); 50 private Dictionary<UUID, List<MapBlockData>> m_SeenMapBlocks = new Dictionary<UUID, List<MapBlockData>>();
50 51
52 private string m_MapImageServerURL = string.Empty;
53
54 private IUserManagement m_UserManagement;
55
51 #region INonSharedRegionModule Members 56 #region INonSharedRegionModule Members
52 57
53 public override void Initialise(IConfigSource config) 58 public override void Initialise(IConfigSource source)
54 { 59 {
55 if (Util.GetConfigVarFromSections<string>( 60 if (Util.GetConfigVarFromSections<string>(
56 config, "WorldMapModule", new string[] { "Map", "Startup" }, "WorldMap") == "HGWorldMap") 61 source, "WorldMapModule", new string[] { "Map", "Startup" }, "WorldMap") == "HGWorldMap")
62 {
57 m_Enabled = true; 63 m_Enabled = true;
64
65 m_MapImageServerURL = Util.GetConfigVarFromSections<string>(source, "MapTileURL", new string[] {"LoginService", "HGWorldMap", "SimulatorFeatures"});
66
67 if (!string.IsNullOrEmpty(m_MapImageServerURL))
68 {
69 m_MapImageServerURL = m_MapImageServerURL.Trim();
70 if (!m_MapImageServerURL.EndsWith("/"))
71 m_MapImageServerURL = m_MapImageServerURL + "/";
72 }
73
74
75 }
58 } 76 }
59 77
60 public override void AddRegion(Scene scene) 78 public override void AddRegion(Scene scene)
61 { 79 {
80 if (!m_Enabled)
81 return;
82
62 base.AddRegion(scene); 83 base.AddRegion(scene);
63 84
64 scene.EventManager.OnClientClosed += new EventManager.ClientClosed(EventManager_OnClientClosed); 85 scene.EventManager.OnClientClosed += EventManager_OnClientClosed;
86 }
87
88 public override void RegionLoaded(Scene scene)
89 {
90 if (!m_Enabled)
91 return;
92
93 base.RegionLoaded(scene);
94 ISimulatorFeaturesModule featuresModule = m_scene.RequestModuleInterface<ISimulatorFeaturesModule>();
95
96 if (featuresModule != null)
97 featuresModule.OnSimulatorFeaturesRequest += OnSimulatorFeaturesRequest;
98
99 m_UserManagement = m_scene.RequestModuleInterface<IUserManagement>();
100
101 }
102
103 public override void RemoveRegion(Scene scene)
104 {
105 if (!m_Enabled)
106 return;
107
108 scene.EventManager.OnClientClosed -= EventManager_OnClientClosed;
65 } 109 }
66 110
67 public override string Name 111 public override string Name
@@ -85,7 +129,7 @@ namespace OpenSim.Region.CoreModules.Hypergrid
85 b.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's 129 b.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's
86 } 130 }
87 131
88 m_log.DebugFormat("[HG MAP]: Reseting {0} blocks", mapBlocks.Count); 132 m_log.DebugFormat("[HG MAP]: Resetting {0} blocks", mapBlocks.Count);
89 sp.ControllingClient.SendMapBlock(mapBlocks, 0); 133 sp.ControllingClient.SendMapBlock(mapBlocks, 0);
90 m_SeenMapBlocks.Remove(clientID); 134 m_SeenMapBlocks.Remove(clientID);
91 } 135 }
@@ -115,6 +159,20 @@ namespace OpenSim.Region.CoreModules.Hypergrid
115 return mapBlocks; 159 return mapBlocks;
116 } 160 }
117 161
162 private void OnSimulatorFeaturesRequest(UUID agentID, ref OSDMap features)
163 {
164 if (m_UserManagement != null && !string.IsNullOrEmpty(m_MapImageServerURL) && !m_UserManagement.IsLocalGridUser(agentID))
165 {
166 OSD extras = new OSDMap();
167 if (features.ContainsKey("OpenSimExtras"))
168 extras = features["OpenSimExtras"];
169 else
170 features["OpenSimExtras"] = extras;
171
172 ((OSDMap)extras)["map-server-url"] = m_MapImageServerURL;
173
174 }
175 }
118 } 176 }
119 177
120 class MapArea 178 class MapArea
diff --git a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
index bfe0383..9809c86 100644
--- a/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/CoreModules/Properties/AssemblyInfo.cs
@@ -30,7 +30,7 @@ using Mono.Addins;
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.7.6.*")] 33[assembly: AssemblyVersion("0.8.0.*")]
34 34
35 35
36[assembly: Addin("OpenSim.Region.CoreModules", "0.1")] 36[assembly: Addin("OpenSim.Region.CoreModules", "0.1")]
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
index 2b13a8b..5541063 100644
--- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs
@@ -412,7 +412,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
412 //public bool HttpVerboseThrottle = true; // not implemented 412 //public bool HttpVerboseThrottle = true; // not implemented
413 public List<string> HttpCustomHeaders = null; 413 public List<string> HttpCustomHeaders = null;
414 public bool HttpPragmaNoCache = true; 414 public bool HttpPragmaNoCache = true;
415 private Thread httpThread;
416 415
417 // Request info 416 // Request info
418 private UUID _itemID; 417 private UUID _itemID;
@@ -501,9 +500,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
501 Request.Headers.Add(HttpCustomHeaders[i], 500 Request.Headers.Add(HttpCustomHeaders[i],
502 HttpCustomHeaders[i+1]); 501 HttpCustomHeaders[i+1]);
503 } 502 }
504 if (proxyurl != null && proxyurl.Length > 0) 503 if (!string.IsNullOrEmpty(proxyurl))
505 { 504 {
506 if (proxyexcepts != null && proxyexcepts.Length > 0) 505 if (!string.IsNullOrEmpty(proxyexcepts))
507 { 506 {
508 string[] elist = proxyexcepts.Split(';'); 507 string[] elist = proxyexcepts.Split(';');
509 Request.Proxy = new WebProxy(proxyurl, true, elist); 508 Request.Proxy = new WebProxy(proxyurl, true, elist);
@@ -521,7 +520,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
521 Request.Headers[entry.Key] = entry.Value; 520 Request.Headers[entry.Key] = entry.Value;
522 521
523 // Encode outbound data 522 // Encode outbound data
524 if (OutboundBody.Length > 0) 523 if (!string.IsNullOrEmpty(OutboundBody))
525 { 524 {
526 byte[] data = Util.UTF8.GetBytes(OutboundBody); 525 byte[] data = Util.UTF8.GetBytes(OutboundBody);
527 526
@@ -622,7 +621,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
622 { 621 {
623 if (!WorkItem.Cancel()) 622 if (!WorkItem.Cancel())
624 { 623 {
625 WorkItem.Abort(); 624 WorkItem.Cancel(true);
626 } 625 }
627 } 626 }
628 catch (Exception) 627 catch (Exception)
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs
new file mode 100644
index 0000000..e812d81
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/Tests/ScriptsHttpRequestsTests.cs
@@ -0,0 +1,198 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Net;
32using System.Reflection;
33using System.Runtime.Serialization;
34using System.Text;
35using System.Threading;
36using log4net.Config;
37using NUnit.Framework;
38using OpenMetaverse;
39using OpenMetaverse.Assets;
40using OpenSim.Framework;
41using OpenSim.Region.CoreModules.Scripting.HttpRequest;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Tests.Common;
44using OpenSim.Tests.Common.Mock;
45
46namespace OpenSim.Region.CoreModules.Scripting.HttpRequest.Tests
47{
48 class TestWebRequestCreate : IWebRequestCreate
49 {
50 public TestWebRequest NextRequest { get; set; }
51
52 public WebRequest Create(Uri uri)
53 {
54// NextRequest.RequestUri = uri;
55
56 return NextRequest;
57
58// return new TestWebRequest(new SerializationInfo(typeof(TestWebRequest), new FormatterConverter()), new StreamingContext());
59 }
60 }
61
62 class TestWebRequest : WebRequest
63 {
64 public override string ContentType { get; set; }
65 public override string Method { get; set; }
66
67 public Func<IAsyncResult, WebResponse> OnEndGetResponse { get; set; }
68
69 public TestWebRequest() : base()
70 {
71// Console.WriteLine("created");
72 }
73
74// public TestWebRequest(SerializationInfo serializationInfo, StreamingContext streamingContext)
75// : base(serializationInfo, streamingContext)
76// {
77// Console.WriteLine("created");
78// }
79
80 public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state)
81 {
82// Console.WriteLine("bish");
83 TestAsyncResult tasr = new TestAsyncResult();
84 callback(tasr);
85
86 return tasr;
87 }
88
89 public override WebResponse EndGetResponse(IAsyncResult asyncResult)
90 {
91// Console.WriteLine("bosh");
92 return OnEndGetResponse(asyncResult);
93 }
94 }
95
96 class TestHttpWebResponse : HttpWebResponse
97 {
98 public string Response { get; set; }
99
100 public TestHttpWebResponse(SerializationInfo serializationInfo, StreamingContext streamingContext)
101 : base(serializationInfo, streamingContext) {}
102
103 public override Stream GetResponseStream()
104 {
105 return new MemoryStream(Encoding.UTF8.GetBytes(Response));
106 }
107 }
108
109 class TestAsyncResult : IAsyncResult
110 {
111 WaitHandle m_wh = new ManualResetEvent(true);
112
113 object IAsyncResult.AsyncState
114 {
115 get {
116 throw new System.NotImplementedException ();
117 }
118 }
119
120 WaitHandle IAsyncResult.AsyncWaitHandle
121 {
122 get { return m_wh; }
123 }
124
125 bool IAsyncResult.CompletedSynchronously
126 {
127 get { return false; }
128 }
129
130 bool IAsyncResult.IsCompleted
131 {
132 get { return true; }
133 }
134 }
135
136 /// <summary>
137 /// Test script http request code.
138 /// </summary>
139 /// <remarks>
140 /// This class uses some very hacky workarounds in order to mock HttpWebResponse which are Mono dependent (though
141 /// alternative code can be written to make this work for Windows). However, the value of being able to
142 /// regression test this kind of code is very high.
143 /// </remarks>
144 [TestFixture]
145 public class ScriptsHttpRequestsTests : OpenSimTestCase
146 {
147 /// <summary>
148 /// Test what happens when we get a 404 response from a call.
149 /// </summary>
150 [Test]
151 public void Test404Response()
152 {
153 TestHelpers.InMethod();
154// TestHelpers.EnableLogging();
155
156 if (!Util.IsPlatformMono)
157 Assert.Ignore("Ignoring test since can only currently run on Mono");
158
159 string rawResponse = "boom";
160
161 TestWebRequestCreate twrc = new TestWebRequestCreate();
162
163 TestWebRequest twr = new TestWebRequest();
164 //twr.OnEndGetResponse += ar => new TestHttpWebResponse(null, new StreamingContext());
165 twr.OnEndGetResponse += ar =>
166 {
167 SerializationInfo si = new SerializationInfo(typeof(HttpWebResponse), new FormatterConverter());
168 StreamingContext sc = new StreamingContext();
169// WebHeaderCollection headers = new WebHeaderCollection();
170// si.AddValue("m_HttpResponseHeaders", headers);
171 si.AddValue("uri", new Uri("test://arrg"));
172// si.AddValue("m_Certificate", null);
173 si.AddValue("version", HttpVersion.Version11);
174 si.AddValue("statusCode", HttpStatusCode.NotFound);
175 si.AddValue("contentLength", 0);
176 si.AddValue("method", "GET");
177 si.AddValue("statusDescription", "Not Found");
178 si.AddValue("contentType", null);
179 si.AddValue("cookieCollection", new CookieCollection());
180
181 TestHttpWebResponse thwr = new TestHttpWebResponse(si, sc);
182 thwr.Response = rawResponse;
183
184 throw new WebException("no message", null, WebExceptionStatus.ProtocolError, thwr);
185 };
186
187 twrc.NextRequest = twr;
188
189 WebRequest.RegisterPrefix("test", twrc);
190 HttpRequestClass hr = new HttpRequestClass();
191 hr.Url = "test://something";
192 hr.SendRequest();
193
194 Assert.That(hr.Status, Is.EqualTo((int)HttpStatusCode.NotFound));
195 Assert.That(hr.ResponseBody, Is.EqualTo(rawResponse));
196 }
197 }
198} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 2a4d440..1983fed 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -219,7 +219,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
219 219
220 string uri = "/lslhttp/" + urlcode.ToString(); 220 string uri = "/lslhttp/" + urlcode.ToString();
221 221
222 PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); 222 PollServiceEventArgs args
223 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
223 args.Type = PollServiceEventArgs.EventType.LslHttp; 224 args.Type = PollServiceEventArgs.EventType.LslHttp;
224 m_HttpServer.AddPollServiceHTTPHandler(uri, args); 225 m_HttpServer.AddPollServiceHTTPHandler(uri, args);
225 226
@@ -266,7 +267,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
266 267
267 string uri = "/lslhttps/" + urlcode.ToString(); 268 string uri = "/lslhttps/" + urlcode.ToString();
268 269
269 PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, HasEvents, GetEvents, NoEvents, urlcode, 25000); 270 PollServiceEventArgs args
271 = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, urlcode, 25000);
270 args.Type = PollServiceEventArgs.EventType.LslHttp; 272 args.Type = PollServiceEventArgs.EventType.LslHttp;
271 m_HttpsServer.AddPollServiceHTTPHandler(uri, args); 273 m_HttpsServer.AddPollServiceHTTPHandler(uri, args);
272 274
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 65737fa..baf9f2f 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -161,9 +161,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
161 { 161 {
162 WebRequest request = HttpWebRequest.Create(url); 162 WebRequest request = HttpWebRequest.Create(url);
163 163
164 if (m_proxyurl != null && m_proxyurl.Length > 0) 164 if (!string.IsNullOrEmpty(m_proxyurl))
165 { 165 {
166 if (m_proxyexcepts != null && m_proxyexcepts.Length > 0) 166 if (!string.IsNullOrEmpty(m_proxyexcepts))
167 { 167 {
168 string[] elist = m_proxyexcepts.Split(';'); 168 string[] elist = m_proxyexcepts.Split(';');
169 request.Proxy = new WebProxy(m_proxyurl, true, elist); 169 request.Proxy = new WebProxy(m_proxyurl, true, elist);
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index fccf053..ad33f23 100644
--- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -45,6 +45,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
45 { 45 {
46 private static readonly ILog m_log = 46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 private static string LogHeader = "[MODULE COMMS]";
48 49
49 private Dictionary<string,object> m_constants = new Dictionary<string,object>(); 50 private Dictionary<string,object> m_constants = new Dictionary<string,object>();
50 51
@@ -148,7 +149,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
148 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true); 149 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
149 if (mi == null) 150 if (mi == null)
150 { 151 {
151 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth); 152 m_log.WarnFormat("{0} Failed to register method {1}", LogHeader, meth);
152 return; 153 return;
153 } 154 }
154 155
@@ -163,9 +164,9 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
163 164
164 public void RegisterScriptInvocation(object target, MethodInfo mi) 165 public void RegisterScriptInvocation(object target, MethodInfo mi)
165 { 166 {
166 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); 167// m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
167 168
168 Type delegateType; 169 Type delegateType = typeof(void);
169 List<Type> typeArgs = mi.GetParameters() 170 List<Type> typeArgs = mi.GetParameters()
170 .Select(p => p.ParameterType) 171 .Select(p => p.ParameterType)
171 .ToList(); 172 .ToList();
@@ -176,8 +177,16 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
176 } 177 }
177 else 178 else
178 { 179 {
179 typeArgs.Add(mi.ReturnType); 180 try
180 delegateType = Expression.GetFuncType(typeArgs.ToArray()); 181 {
182 typeArgs.Add(mi.ReturnType);
183 delegateType = Expression.GetFuncType(typeArgs.ToArray());
184 }
185 catch (Exception e)
186 {
187 m_log.ErrorFormat("{0} Failed to create function signature. Most likely more than 5 parameters. Method={1}. Error={2}",
188 LogHeader, mi.Name, e);
189 }
181 } 190 }
182 191
183 Delegate fcall; 192 Delegate fcall;
@@ -325,7 +334,7 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
325 /// </summary> 334 /// </summary>
326 public void RegisterConstant(string cname, object value) 335 public void RegisterConstant(string cname, object value)
327 { 336 {
328 m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString()); 337// m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString());
329 lock (m_constants) 338 lock (m_constants)
330 { 339 {
331 m_constants.Add(cname,value); 340 m_constants.Add(cname,value);
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index 41baccc..7119137 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -152,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
152 TestHelpers.InMethod(); 152 TestHelpers.InMethod();
153 153
154 string dtText 154 string dtText
155 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; 155 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://0.0.0.0/shouldnotexist.png";
156 156
157 SetupScene(false); 157 SetupScene(false);
158 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); 158 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
@@ -307,7 +307,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
307 TestHelpers.InMethod(); 307 TestHelpers.InMethod();
308 308
309 string dtText 309 string dtText
310 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; 310 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://0.0.0.0/shouldnotexist.png";
311 311
312 SetupScene(true); 312 SetupScene(true);
313 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); 313 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
index cbffca7..c6e05b1 100644
--- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
@@ -677,7 +677,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
677 // if not, use as method name 677 // if not, use as method name
678 UUID parseUID; 678 UUID parseUID;
679 string mName = "llRemoteData"; 679 string mName = "llRemoteData";
680 if ((Channel != null) && (Channel != "")) 680 if (!string.IsNullOrEmpty(Channel))
681 if (!UUID.TryParse(Channel, out parseUID)) 681 if (!UUID.TryParse(Channel, out parseUID))
682 mName = Channel; 682 mName = Channel;
683 else 683 else
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs
new file mode 100644
index 0000000..323535a
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs
@@ -0,0 +1,226 @@
1
2/*
3 * Copyright (c) Contributors, http://opensimulator.org/
4 * See CONTRIBUTORS.TXT for a full list of copyright holders.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the OpenSimulator Project nor the
14 * names of its contributors may be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29using log4net;
30using Mono.Addins;
31using Nini.Config;
32using System;
33using System.Collections.Generic;
34using System.Reflection;
35using OpenSim.Framework;
36using OpenSim.Framework.Console;
37using OpenSim.Server.Base;
38using OpenSim.Server.Handlers;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Framework.Servers.HttpServer;
41using OpenSim.Framework.Servers;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Services.Interfaces;
44using GridRegion = OpenSim.Services.Interfaces.GridRegion;
45using OpenMetaverse;
46
47namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Profile
48{
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalUserProfilesServicesConnector")]
50 public class LocalUserProfilesServicesConnector : ISharedRegionModule
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(
54 MethodBase.GetCurrentMethod().DeclaringType);
55
56 private Dictionary<UUID, Scene> regions = new Dictionary<UUID, Scene>();
57
58 public IUserProfilesService ServiceModule
59 {
60 get; private set;
61 }
62
63 public bool Enabled
64 {
65 get; private set;
66 }
67
68 public string Name
69 {
70 get
71 {
72 return "LocalUserProfilesServicesConnector";
73 }
74 }
75
76 public string ConfigName
77 {
78 get; private set;
79 }
80
81 public Type ReplaceableInterface
82 {
83 get { return null; }
84 }
85
86 public LocalUserProfilesServicesConnector()
87 {
88 m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector no params");
89 }
90
91 public LocalUserProfilesServicesConnector(IConfigSource source)
92 {
93 m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector instantiated directly.");
94 InitialiseService(source);
95 }
96
97 public void InitialiseService(IConfigSource source)
98 {
99 ConfigName = "UserProfilesService";
100
101 // Instantiate the request handler
102 IHttpServer Server = MainServer.Instance;
103
104 IConfig config = source.Configs[ConfigName];
105 if (config == null)
106 {
107 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: UserProfilesService missing from OpenSim.ini");
108 return;
109 }
110
111 if(!config.GetBoolean("Enabled",false))
112 {
113 Enabled = false;
114 return;
115 }
116
117 Enabled = true;
118
119 string serviceDll = config.GetString("LocalServiceModule",
120 String.Empty);
121
122 if (serviceDll == String.Empty)
123 {
124 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: No LocalServiceModule named in section UserProfilesService");
125 return;
126 }
127
128 Object[] args = new Object[] { source, ConfigName };
129 ServiceModule =
130 ServerUtils.LoadPlugin<IUserProfilesService>(serviceDll,
131 args);
132
133 if (ServiceModule == null)
134 {
135 m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: Can't load user profiles service");
136 return;
137 }
138
139 Enabled = true;
140
141 JsonRpcProfileHandlers handler = new JsonRpcProfileHandlers(ServiceModule);
142
143 Server.AddJsonRPCHandler("avatarclassifiedsrequest", handler.AvatarClassifiedsRequest);
144 Server.AddJsonRPCHandler("classified_update", handler.ClassifiedUpdate);
145 Server.AddJsonRPCHandler("classifieds_info_query", handler.ClassifiedInfoRequest);
146 Server.AddJsonRPCHandler("classified_delete", handler.ClassifiedDelete);
147 Server.AddJsonRPCHandler("avatarpicksrequest", handler.AvatarPicksRequest);
148 Server.AddJsonRPCHandler("pickinforequest", handler.PickInfoRequest);
149 Server.AddJsonRPCHandler("picks_update", handler.PicksUpdate);
150 Server.AddJsonRPCHandler("picks_delete", handler.PicksDelete);
151 Server.AddJsonRPCHandler("avatarnotesrequest", handler.AvatarNotesRequest);
152 Server.AddJsonRPCHandler("avatar_notes_update", handler.NotesUpdate);
153 Server.AddJsonRPCHandler("avatar_properties_request", handler.AvatarPropertiesRequest);
154 Server.AddJsonRPCHandler("avatar_properties_update", handler.AvatarPropertiesUpdate);
155 Server.AddJsonRPCHandler("avatar_interests_update", handler.AvatarInterestsUpdate);
156 Server.AddJsonRPCHandler("image_assets_request", handler.AvatarImageAssetsRequest);
157 Server.AddJsonRPCHandler("user_data_request", handler.RequestUserAppData);
158 Server.AddJsonRPCHandler("user_data_update", handler.UpdateUserAppData);
159
160 }
161
162 #region ISharedRegionModule implementation
163
164 void ISharedRegionModule.PostInitialise()
165 {
166 if(!Enabled)
167 return;
168 }
169
170 #endregion
171
172 #region IRegionModuleBase implementation
173
174 void IRegionModuleBase.Initialise(IConfigSource source)
175 {
176 IConfig moduleConfig = source.Configs["Modules"];
177 if (moduleConfig != null)
178 {
179 string name = moduleConfig.GetString("UserProfilesServices", "");
180 if (name == Name)
181 {
182 InitialiseService(source);
183 m_log.Info("[LOCAL USERPROFILES SERVICE CONNECTOR]: Local user profiles connector enabled");
184 }
185 }
186 }
187
188 void IRegionModuleBase.Close()
189 {
190 return;
191 }
192
193 void IRegionModuleBase.AddRegion(Scene scene)
194 {
195 if (!Enabled)
196 return;
197
198 lock (regions)
199 {
200 if (regions.ContainsKey(scene.RegionInfo.RegionID))
201 m_log.ErrorFormat("[LOCAL USERPROFILES SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
202 else
203 regions.Add(scene.RegionInfo.RegionID, scene);
204 }
205 }
206
207 void IRegionModuleBase.RemoveRegion(Scene scene)
208 {
209 if (!Enabled)
210 return;
211
212 lock (regions)
213 {
214 if (regions.ContainsKey(scene.RegionInfo.RegionID))
215 regions.Remove(scene.RegionInfo.RegionID);
216 }
217 }
218
219 void IRegionModuleBase.RegionLoaded(Scene scene)
220 {
221 if (!Enabled)
222 return;
223 }
224 #endregion
225 }
226} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
index d221d68..9f58175 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
@@ -322,7 +322,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
322 // a copy of the local asset. 322 // a copy of the local asset.
323 m_Cache.Cache(asset); 323 m_Cache.Cache(asset);
324 324
325 if (asset.Temporary || asset.Local) 325 if (asset.Local)
326 { 326 {
327 if (m_Cache != null) 327 if (m_Cache != null)
328 m_Cache.Cache(asset); 328 m_Cache.Cache(asset);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
index 480cd69..52b1039 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
@@ -258,7 +258,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
258 if (m_Cache != null) 258 if (m_Cache != null)
259 m_Cache.Cache(asset); 259 m_Cache.Cache(asset);
260 260
261 if (asset.Temporary || asset.Local) 261 if (asset.Local)
262 { 262 {
263// m_log.DebugFormat( 263// m_log.DebugFormat(
264// "[LOCAL ASSET SERVICE CONNECTOR]: Returning asset {0} {1} without querying database since status Temporary = {2}, Local = {3}", 264// "[LOCAL ASSET SERVICE CONNECTOR]: Returning asset {0} {1} without querying database since status Temporary = {2}, Local = {3}",
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
index 1982473..4f75191 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
@@ -42,7 +42,7 @@ using OpenSim.Tests.Common;
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests 42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
43{ 43{
44 [TestFixture] 44 [TestFixture]
45 public class AssetConnectorsTests : OpenSimTestCase 45 public class AssetConnectorTests : OpenSimTestCase
46 { 46 {
47 [Test] 47 [Test]
48 public void TestAddAsset() 48 public void TestAddAsset()
@@ -77,7 +77,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
77 // TODO: Add cache and check that this does receive a copy of the asset 77 // TODO: Add cache and check that this does receive a copy of the asset
78 } 78 }
79 79
80 [Test]
81 public void TestAddTemporaryAsset() 80 public void TestAddTemporaryAsset()
82 { 81 {
83 TestHelpers.InMethod(); 82 TestHelpers.InMethod();
@@ -93,8 +92,45 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
93 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); 92 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
94 lasc.Initialise(config); 93 lasc.Initialise(config);
95 94
95 // If it is remote, it should be stored
96 AssetBase a2 = AssetHelpers.CreateNotecardAsset();
97 a2.Local = false;
98 a2.Temporary = true;
99
100 lasc.Store(a2);
101
102 AssetBase retreivedA2 = lasc.Get(a2.ID);
103 Assert.That(retreivedA2.ID, Is.EqualTo(a2.ID));
104 Assert.That(retreivedA2.Metadata.ID, Is.EqualTo(a2.Metadata.ID));
105 Assert.That(retreivedA2.Data.Length, Is.EqualTo(a2.Data.Length));
106
107 AssetMetadata retrievedA2Metadata = lasc.GetMetadata(a2.ID);
108 Assert.That(retrievedA2Metadata.ID, Is.EqualTo(a2.ID));
109
110 byte[] retrievedA2Data = lasc.GetData(a2.ID);
111 Assert.That(retrievedA2Data.Length, Is.EqualTo(a2.Data.Length));
112
113 // TODO: Add cache and check that this does receive a copy of the asset
114 }
115
116 [Test]
117 public void TestAddLocalAsset()
118 {
119 TestHelpers.InMethod();
120// TestHelpers.EnableLogging();
121
122 IConfigSource config = new IniConfigSource();
123 config.AddConfig("Modules");
124 config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
125 config.AddConfig("AssetService");
126 config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
127 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
128
129 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
130 lasc.Initialise(config);
131
96 AssetBase a1 = AssetHelpers.CreateNotecardAsset(); 132 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
97 a1.Temporary = true; 133 a1.Local = true;
98 134
99 lasc.Store(a1); 135 lasc.Store(a1);
100 136
@@ -106,7 +142,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
106 } 142 }
107 143
108 [Test] 144 [Test]
109 public void TestAddLocalAsset() 145 public void TestAddTemporaryLocalAsset()
110 { 146 {
111 TestHelpers.InMethod(); 147 TestHelpers.InMethod();
112// TestHelpers.EnableLogging(); 148// TestHelpers.EnableLogging();
@@ -121,8 +157,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
121 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); 157 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
122 lasc.Initialise(config); 158 lasc.Initialise(config);
123 159
160 // If it is local, it should not be stored
124 AssetBase a1 = AssetHelpers.CreateNotecardAsset(); 161 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
125 a1.Local = true; 162 a1.Local = true;
163 a1.Temporary = true;
126 164
127 lasc.Store(a1); 165 lasc.Store(a1);
128 166
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
index c0c2ca7..31ef79b 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs
@@ -56,6 +56,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
56 56
57 public LocalGridServicesConnector() 57 public LocalGridServicesConnector()
58 { 58 {
59 m_log.Debug("[LOCAL GRID SERVICE CONNECTOR]: LocalGridServicesConnector no parms.");
59 } 60 }
60 61
61 public LocalGridServicesConnector(IConfigSource source) 62 public LocalGridServicesConnector(IConfigSource source)
@@ -142,10 +143,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
142 143
143 scene.RegisterModuleInterface<IGridService>(this); 144 scene.RegisterModuleInterface<IGridService>(this);
144 145
145 if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID)) 146 lock (m_LocalCache)
146 m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!"); 147 {
147 else 148 if (m_LocalCache.ContainsKey(scene.RegionInfo.RegionID))
148 m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene)); 149 m_log.ErrorFormat("[LOCAL GRID SERVICE CONNECTOR]: simulator seems to have more than one region with the same UUID. Please correct this!");
150 else
151 m_LocalCache.Add(scene.RegionInfo.RegionID, new RegionCache(scene));
152 }
149 } 153 }
150 154
151 public void RemoveRegion(Scene scene) 155 public void RemoveRegion(Scene scene)
@@ -153,8 +157,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
153 if (!m_Enabled) 157 if (!m_Enabled)
154 return; 158 return;
155 159
156 m_LocalCache[scene.RegionInfo.RegionID].Clear(); 160 lock (m_LocalCache)
157 m_LocalCache.Remove(scene.RegionInfo.RegionID); 161 {
162 m_LocalCache[scene.RegionInfo.RegionID].Clear();
163 m_LocalCache.Remove(scene.RegionInfo.RegionID);
164 }
158 } 165 }
159 166
160 public void RegionLoaded(Scene scene) 167 public void RegionLoaded(Scene scene)
@@ -191,12 +198,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
191 198
192 // First see if it's a neighbour, even if it isn't on this sim. 199 // First see if it's a neighbour, even if it isn't on this sim.
193 // Neighbour data is cached in memory, so this is fast 200 // Neighbour data is cached in memory, so this is fast
194 foreach (RegionCache rcache in m_LocalCache.Values) 201
202 lock (m_LocalCache)
195 { 203 {
196 region = rcache.GetRegionByPosition(x, y); 204 foreach (RegionCache rcache in m_LocalCache.Values)
197 if (region != null)
198 { 205 {
199 return region; 206 region = rcache.GetRegionByPosition(x, y);
207 if (region != null)
208 {
209 return region;
210 }
200 } 211 }
201 } 212 }
202 213
@@ -224,6 +235,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
224 return m_GridService.GetDefaultRegions(scopeID); 235 return m_GridService.GetDefaultRegions(scopeID);
225 } 236 }
226 237
238 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
239 {
240 return m_GridService.GetDefaultHypergridRegions(scopeID);
241 }
242
227 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 243 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
228 { 244 {
229 return m_GridService.GetFallbackRegions(scopeID, x, y); 245 return m_GridService.GetFallbackRegions(scopeID, x, y);
@@ -245,12 +261,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
245 { 261 {
246 System.Text.StringBuilder caps = new System.Text.StringBuilder(); 262 System.Text.StringBuilder caps = new System.Text.StringBuilder();
247 263
248 foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache) 264 lock (m_LocalCache)
249 { 265 {
250 caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key); 266 foreach (KeyValuePair<UUID, RegionCache> kvp in m_LocalCache)
251 List<GridRegion> regions = kvp.Value.GetNeighbours(); 267 {
252 foreach (GridRegion r in regions) 268 caps.AppendFormat("*** Neighbours of {0} ({1}) ***\n", kvp.Value.RegionName, kvp.Key);
253 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, r.RegionLocX / Constants.RegionSize, r.RegionLocY / Constants.RegionSize); 269 List<GridRegion> regions = kvp.Value.GetNeighbours();
270 foreach (GridRegion r in regions)
271 caps.AppendFormat(" {0} @ {1}-{2}\n", r.RegionName, r.RegionLocX / Constants.RegionSize, r.RegionLocY / Constants.RegionSize);
272 }
254 } 273 }
255 274
256 MainConsole.Instance.Output(caps.ToString()); 275 MainConsole.Instance.Output(caps.ToString());
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
index b2646ba..6a57d1f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs
@@ -277,6 +277,26 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
277 return rinfo; 277 return rinfo;
278 } 278 }
279 279
280 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
281 {
282 List<GridRegion> rinfo = m_LocalGridService.GetDefaultHypergridRegions(scopeID);
283 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Local GetDefaultHypergridRegions {0} found {1} regions", name, rinfo.Count);
284 List<GridRegion> grinfo = m_RemoteGridService.GetDefaultHypergridRegions(scopeID);
285
286 if (grinfo != null)
287 {
288 //m_log.DebugFormat("[REMOTE GRID CONNECTOR]: Remote GetDefaultHypergridRegions {0} found {1} regions", name, grinfo.Count);
289 foreach (GridRegion r in grinfo)
290 {
291 m_RegionInfoCache.Cache(r);
292 if (rinfo.Find(delegate(GridRegion gr) { return gr.RegionID == r.RegionID; }) == null)
293 rinfo.Add(r);
294 }
295 }
296
297 return rinfo;
298 }
299
280 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 300 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
281 { 301 {
282 List<GridRegion> rinfo = m_LocalGridService.GetFallbackRegions(scopeID, x, y); 302 List<GridRegion> rinfo = m_LocalGridService.GetFallbackRegions(scopeID, x, y);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
index 221f815..e05d186 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
@@ -81,6 +81,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
81 81
82 public void OnConnectionClose(IClientAPI client) 82 public void OnConnectionClose(IClientAPI client)
83 { 83 {
84 if (client == null)
85 return;
86 if (client.SceneAgent == null)
87 return;
88
84 if (client.SceneAgent.IsChildAgent) 89 if (client.SceneAgent.IsChildAgent)
85 return; 90 return;
86 91
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
index e474ef6..77a3c82 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
@@ -233,6 +233,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
233 if (sp != null) 233 if (sp != null)
234 { 234 {
235 AgentCircuitData aCircuit = scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); 235 AgentCircuitData aCircuit = scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode);
236 if (aCircuit == null)
237 return;
238 if (aCircuit.ServiceURLs == null)
239 return;
240
236 if (aCircuit.ServiceURLs.ContainsKey("InventoryServerURI")) 241 if (aCircuit.ServiceURLs.ContainsKey("InventoryServerURI"))
237 { 242 {
238 inventoryURL = aCircuit.ServiceURLs["InventoryServerURI"].ToString(); 243 inventoryURL = aCircuit.ServiceURLs["InventoryServerURI"].ToString();
@@ -254,7 +259,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
254 if (sp == null) 259 if (sp == null)
255 { 260 {
256 inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI"); 261 inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI");
257 if (inventoryURL != null && inventoryURL != string.Empty) 262 if (!string.IsNullOrEmpty(inventoryURL))
258 { 263 {
259 inventoryURL = inventoryURL.Trim(new char[] { '/' }); 264 inventoryURL = inventoryURL.Trim(new char[] { '/' });
260 m_InventoryURLs.Add(userID, inventoryURL); 265 m_InventoryURLs.Add(userID, inventoryURL);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
index 1e434b9..2fc8ee3 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs
@@ -1,11 +1,41 @@
1using System; 1/*
2using System.Collections.Generic; 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
3 27
28using System;
29using System.Collections.Generic;
30using System.Threading;
4using OpenSim.Framework; 31using OpenSim.Framework;
5using OpenMetaverse; 32using OpenMetaverse;
6 33
7namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory 34namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
8{ 35{
36 /// <summary>
37 /// Cache root and system inventory folders to reduce number of potentially remote inventory calls and associated holdups.
38 /// </summary>
9 public class InventoryCache 39 public class InventoryCache
10 { 40 {
11 private const double CACHE_EXPIRATION_SECONDS = 3600.0; // 1 hour 41 private const double CACHE_EXPIRATION_SECONDS = 3600.0; // 1 hour
@@ -16,8 +46,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
16 46
17 public void Cache(UUID userID, InventoryFolderBase root) 47 public void Cache(UUID userID, InventoryFolderBase root)
18 { 48 {
19 lock (m_RootFolders) 49 m_RootFolders.AddOrUpdate(userID, root, CACHE_EXPIRATION_SECONDS);
20 m_RootFolders.AddOrUpdate(userID, root, CACHE_EXPIRATION_SECONDS);
21 } 50 }
22 51
23 public InventoryFolderBase GetRootFolder(UUID userID) 52 public InventoryFolderBase GetRootFolder(UUID userID)
@@ -31,14 +60,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
31 60
32 public void Cache(UUID userID, AssetType type, InventoryFolderBase folder) 61 public void Cache(UUID userID, AssetType type, InventoryFolderBase folder)
33 { 62 {
34 lock (m_FolderTypes) 63 Dictionary<AssetType, InventoryFolderBase> ff = null;
64 if (!m_FolderTypes.TryGetValue(userID, out ff))
65 {
66 ff = new Dictionary<AssetType, InventoryFolderBase>();
67 m_FolderTypes.Add(userID, ff, CACHE_EXPIRATION_SECONDS);
68 }
69
70 // We need to lock here since two threads could potentially retrieve the same dictionary
71 // and try to add a folder for that type simultaneously. Dictionary<>.Add() is not described as thread-safe in the SDK
72 // even if the folders are identical.
73 lock (ff)
35 { 74 {
36 Dictionary<AssetType, InventoryFolderBase> ff = null;
37 if (!m_FolderTypes.TryGetValue(userID, out ff))
38 {
39 ff = new Dictionary<AssetType, InventoryFolderBase>();
40 m_FolderTypes.Add(userID, ff, CACHE_EXPIRATION_SECONDS);
41 }
42 if (!ff.ContainsKey(type)) 75 if (!ff.ContainsKey(type))
43 ff.Add(type, folder); 76 ff.Add(type, folder);
44 } 77 }
@@ -50,8 +83,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
50 if (m_FolderTypes.TryGetValue(userID, out ff)) 83 if (m_FolderTypes.TryGetValue(userID, out ff))
51 { 84 {
52 InventoryFolderBase f = null; 85 InventoryFolderBase f = null;
53 if (ff.TryGetValue(type, out f)) 86
54 return f; 87 lock (ff)
88 {
89 if (ff.TryGetValue(type, out f))
90 return f;
91 }
55 } 92 }
56 93
57 return null; 94 return null;
@@ -59,8 +96,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
59 96
60 public void Cache(UUID userID, InventoryCollection inv) 97 public void Cache(UUID userID, InventoryCollection inv)
61 { 98 {
62 lock (m_Inventories) 99 m_Inventories.AddOrUpdate(userID, inv, 120);
63 m_Inventories.AddOrUpdate(userID, inv, 120);
64 } 100 }
65 101
66 public InventoryCollection GetUserInventory(UUID userID) 102 public InventoryCollection GetUserInventory(UUID userID)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
index ec5751d..99913a9 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
@@ -196,7 +196,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
196 Util.FireAndForget(delegate 196 Util.FireAndForget(delegate
197 { 197 {
198 foreach (InventoryItemBase item in items) 198 foreach (InventoryItemBase item in items)
199 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); 199 if (!string.IsNullOrEmpty(item.CreatorData))
200 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
200 }); 201 });
201 } 202 }
202 203
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
index 2d3ba82..7f78076 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
@@ -195,18 +195,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
195 { 195 {
196 InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); 196 InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID);
197 197
198 if (invCol != null && UserManager != null) 198 // Commenting this for now, because it's causing more grief than good
199 { 199 //if (invCol != null && UserManager != null)
200 // Protect ourselves against the caller subsequently modifying the items list 200 //{
201 List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items); 201 // // Protect ourselves against the caller subsequently modifying the items list
202 202 // List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items);
203 if (items != null && items.Count > 0) 203
204 Util.FireAndForget(delegate 204 // if (items != null && items.Count > 0)
205 { 205 // //Util.FireAndForget(delegate
206 foreach (InventoryItemBase item in items) 206 // //{
207 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); 207 // foreach (InventoryItemBase item in items)
208 }); 208 // if (!string.IsNullOrEmpty(item.CreatorData))
209 } 209 // UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
210 // //});
211 //}
210 212
211 return invCol; 213 return invCol;
212 } 214 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
index 172bea1..516ad40 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
@@ -79,7 +79,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
79 79
80 public void OnConnectionClose(IClientAPI client) 80 public void OnConnectionClose(IClientAPI client)
81 { 81 {
82 if (!client.SceneAgent.IsChildAgent) 82 if (client != null && client.SceneAgent != null && !client.SceneAgent.IsChildAgent)
83 { 83 {
84// m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); 84// m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
85 m_PresenceService.LogoutAgent(client.SessionId); 85 m_PresenceService.LogoutAgent(client.SessionId);
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 8b8bb37..7a6a174 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -46,9 +46,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 /// <summary> 48 /// <summary>
49 /// Version of this service 49 /// Version of this service.
50 /// </summary> 50 /// </summary>
51 private const string m_Version = "SIMULATION/0.1"; 51 /// <remarks>
52 /// Currently valid versions are "SIMULATION/0.1" and "SIMULATION/0.2"
53 /// </remarks>
54 public string ServiceVersion { get; set; }
52 55
53 /// <summary> 56 /// <summary>
54 /// Map region ID to scene. 57 /// Map region ID to scene.
@@ -62,28 +65,39 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
62 65
63 #region Region Module interface 66 #region Region Module interface
64 67
65 public void Initialise(IConfigSource config) 68 public void Initialise(IConfigSource configSource)
66 { 69 {
67 IConfig moduleConfig = config.Configs["Modules"]; 70 IConfig moduleConfig = configSource.Configs["Modules"];
68 if (moduleConfig != null) 71 if (moduleConfig != null)
69 { 72 {
70 string name = moduleConfig.GetString("SimulationServices", ""); 73 string name = moduleConfig.GetString("SimulationServices", "");
71 if (name == Name) 74 if (name == Name)
72 { 75 {
73 //IConfig userConfig = config.Configs["SimulationService"]; 76 InitialiseService(configSource);
74 //if (userConfig == null)
75 //{
76 // m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpenSim.ini");
77 // return;
78 //}
79 77
80 m_ModuleEnabled = true; 78 m_ModuleEnabled = true;
81 79
82 m_log.Info("[SIMULATION CONNECTOR]: Local simulation enabled"); 80 m_log.Info("[LOCAL SIMULATION CONNECTOR]: Local simulation enabled.");
83 } 81 }
84 } 82 }
85 } 83 }
86 84
85 public void InitialiseService(IConfigSource configSource)
86 {
87 ServiceVersion = "SIMULATION/0.2";
88 IConfig config = configSource.Configs["SimulationService"];
89 if (config != null)
90 {
91 ServiceVersion = config.GetString("ConnectorProtocolVersion", ServiceVersion);
92
93 if (ServiceVersion != "SIMULATION/0.1" && ServiceVersion != "SIMULATION/0.2")
94 throw new Exception(string.Format("Invalid ConnectorProtocolVersion {0}", ServiceVersion));
95
96 m_log.InfoFormat(
97 "[LOCAL SIMULATION CONNECTOR]: Initialized with connector protocol version {0}", ServiceVersion);
98 }
99 }
100
87 public void PostInitialise() 101 public void PostInitialise()
88 { 102 {
89 } 103 }
@@ -160,7 +174,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
160 174
161 #endregion 175 #endregion
162 176
163 #region ISimulation 177 #region ISimulationService
164 178
165 public IScene GetScene(UUID regionId) 179 public IScene GetScene(UUID regionId)
166 { 180 {
@@ -221,7 +235,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
221// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", 235// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
222// destination.RegionName, destination.RegionID); 236// destination.RegionName, destination.RegionID);
223 237
224 return m_scenes[destination.RegionID].IncomingChildAgentDataUpdate(cAgentData); 238 return m_scenes[destination.RegionID].IncomingUpdateChildAgent(cAgentData);
225 } 239 }
226 240
227// m_log.DebugFormat( 241// m_log.DebugFormat(
@@ -231,7 +245,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
231 return false; 245 return false;
232 } 246 }
233 247
234 public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData) 248 public bool UpdateAgent(GridRegion destination, AgentPosition agentPosition)
235 { 249 {
236 if (destination == null) 250 if (destination == null)
237 return false; 251 return false;
@@ -243,37 +257,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
243 foreach (Scene s in m_scenes.Values) 257 foreach (Scene s in m_scenes.Values)
244 { 258 {
245// m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); 259// m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
246 s.IncomingChildAgentDataUpdate(cAgentData); 260 s.IncomingUpdateChildAgent(agentPosition);
247 } 261 }
248 262
249 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate"); 263 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
250 return true; 264 return true;
251 } 265 }
252 266
253 public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent)
254 {
255 agent = null;
256
257 if (destination == null)
258 return false;
259
260 if (m_scenes.ContainsKey(destination.RegionID))
261 {
262// m_log.DebugFormat(
263// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
264// s.RegionInfo.RegionName, destination.RegionHandle);
265
266 return m_scenes[destination.RegionID].IncomingRetrieveRootAgent(id, out agent);
267 }
268
269 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
270 return false;
271 }
272
273 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason) 267 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
274 { 268 {
275 reason = "Communications failure"; 269 reason = "Communications failure";
276 version = m_Version; 270 version = ServiceVersion;
277 if (destination == null) 271 if (destination == null)
278 return false; 272 return false;
279 273
@@ -306,12 +300,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
306 return false; 300 return false;
307 } 301 }
308 302
309 public bool CloseChildAgent(GridRegion destination, UUID id) 303 public bool CloseAgent(GridRegion destination, UUID id, string auth_token)
310 {
311 return CloseAgent(destination, id);
312 }
313
314 public bool CloseAgent(GridRegion destination, UUID id)
315 { 304 {
316 if (destination == null) 305 if (destination == null)
317 return false; 306 return false;
@@ -322,7 +311,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
322// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", 311// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
323// s.RegionInfo.RegionName, destination.RegionHandle); 312// s.RegionInfo.RegionName, destination.RegionHandle);
324 313
325 Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); }); 314 m_scenes[destination.RegionID].CloseAgent(id, false, auth_token);
326 return true; 315 return true;
327 } 316 }
328 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 317 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
@@ -363,7 +352,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
363 return false; 352 return false;
364 } 353 }
365 354
366 #endregion /* IInterregionComms */ 355 #endregion
367 356
368 #region Misc 357 #region Misc
369 358
@@ -383,4 +372,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
383 372
384 #endregion 373 #endregion
385 } 374 }
386} 375} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
index c8698ca..ab912ed 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs
@@ -50,9 +50,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteSimulationConnectorModule")] 50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteSimulationConnectorModule")]
51 public class RemoteSimulationConnectorModule : ISharedRegionModule, ISimulationService 51 public class RemoteSimulationConnectorModule : ISharedRegionModule, ISimulationService
52 { 52 {
53 private bool initialized = false;
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 54
55 private bool initialized = false;
56 protected bool m_enabled = false; 56 protected bool m_enabled = false;
57 protected Scene m_aScene; 57 protected Scene m_aScene;
58 // RemoteSimulationConnector does not care about local regions; it delegates that to the Local module 58 // RemoteSimulationConnector does not care about local regions; it delegates that to the Local module
@@ -64,27 +64,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
64 64
65 #region Region Module interface 65 #region Region Module interface
66 66
67 public virtual void Initialise(IConfigSource config) 67 public virtual void Initialise(IConfigSource configSource)
68 { 68 {
69 69 IConfig moduleConfig = configSource.Configs["Modules"];
70 IConfig moduleConfig = config.Configs["Modules"];
71 if (moduleConfig != null) 70 if (moduleConfig != null)
72 { 71 {
73 string name = moduleConfig.GetString("SimulationServices", ""); 72 string name = moduleConfig.GetString("SimulationServices", "");
74 if (name == Name) 73 if (name == Name)
75 { 74 {
76 //IConfig userConfig = config.Configs["SimulationService"]; 75 m_localBackend = new LocalSimulationConnectorModule();
77 //if (userConfig == null) 76
78 //{ 77 m_localBackend.InitialiseService(configSource);
79 // m_log.Error("[AVATAR CONNECTOR]: SimulationService missing from OpenSim.ini");
80 // return;
81 //}
82 78
83 m_remoteConnector = new SimulationServiceConnector(); 79 m_remoteConnector = new SimulationServiceConnector();
84 80
85 m_enabled = true; 81 m_enabled = true;
86 82
87 m_log.Info("[SIMULATION CONNECTOR]: Remote simulation enabled"); 83 m_log.Info("[REMOTE SIMULATION CONNECTOR]: Remote simulation enabled.");
88 } 84 }
89 } 85 }
90 } 86 }
@@ -142,8 +138,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
142 } 138 }
143 139
144 protected virtual void InitOnce(Scene scene) 140 protected virtual void InitOnce(Scene scene)
145 { 141 {
146 m_localBackend = new LocalSimulationConnectorModule();
147 m_aScene = scene; 142 m_aScene = scene;
148 //m_regionClient = new RegionToRegionClient(m_aScene, m_hyperlinkService); 143 //m_regionClient = new RegionToRegionClient(m_aScene, m_hyperlinkService);
149 m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName); 144 m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName);
@@ -151,7 +146,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
151 146
152 #endregion 147 #endregion
153 148
154 #region IInterregionComms 149 #region ISimulationService
155 150
156 public IScene GetScene(UUID regionId) 151 public IScene GetScene(UUID regionId)
157 { 152 {
@@ -194,7 +189,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
194 return false; 189 return false;
195 190
196 // Try local first 191 // Try local first
197 if (m_localBackend.IsLocalRegion(destination.RegionHandle)) 192 if (m_localBackend.IsLocalRegion(destination.RegionID))
198 return m_localBackend.UpdateAgent(destination, cAgentData); 193 return m_localBackend.UpdateAgent(destination, cAgentData);
199 194
200 return m_remoteConnector.UpdateAgent(destination, cAgentData); 195 return m_remoteConnector.UpdateAgent(destination, cAgentData);
@@ -206,30 +201,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
206 return false; 201 return false;
207 202
208 // Try local first 203 // Try local first
209 if (m_localBackend.IsLocalRegion(destination.RegionHandle)) 204 if (m_localBackend.IsLocalRegion(destination.RegionID))
210 return m_localBackend.UpdateAgent(destination, cAgentData); 205 return m_localBackend.UpdateAgent(destination, cAgentData);
211 206
212 return m_remoteConnector.UpdateAgent(destination, cAgentData); 207 return m_remoteConnector.UpdateAgent(destination, cAgentData);
213 } 208 }
214 209
215 public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent)
216 {
217 agent = null;
218
219 if (destination == null)
220 return false;
221
222 // Try local first
223 if (m_localBackend.RetrieveAgent(destination, id, out agent))
224 return true;
225
226 // else do the remote thing
227 if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
228 return m_remoteConnector.RetrieveAgent(destination, id, out agent);
229
230 return false;
231 }
232
233 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason) 210 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
234 { 211 {
235 reason = "Communications failure"; 212 reason = "Communications failure";
@@ -262,34 +239,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
262 return false; 239 return false;
263 } 240 }
264 241
265 public bool CloseChildAgent(GridRegion destination, UUID id) 242 public bool CloseAgent(GridRegion destination, UUID id, string auth_token)
266 {
267 if (destination == null)
268 return false;
269
270 // Try local first
271 if (m_localBackend.CloseChildAgent(destination, id))
272 return true;
273
274 // else do the remote thing
275 if (!m_localBackend.IsLocalRegion(destination.RegionHandle))
276 return m_remoteConnector.CloseChildAgent(destination, id);
277
278 return false;
279 }
280
281 public bool CloseAgent(GridRegion destination, UUID id)
282 { 243 {
283 if (destination == null) 244 if (destination == null)
284 return false; 245 return false;
285 246
286 // Try local first 247 // Try local first
287 if (m_localBackend.CloseAgent(destination, id)) 248 if (m_localBackend.CloseAgent(destination, id, auth_token))
288 return true; 249 return true;
289 250
290 // else do the remote thing 251 // else do the remote thing
291 if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) 252 if (!m_localBackend.IsLocalRegion(destination.RegionID))
292 return m_remoteConnector.CloseAgent(destination, id); 253 return m_remoteConnector.CloseAgent(destination, id, auth_token);
293 254
294 return false; 255 return false;
295 } 256 }
@@ -311,12 +272,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
311 } 272 }
312 273
313 // else do the remote thing 274 // else do the remote thing
314 if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) 275 if (!m_localBackend.IsLocalRegion(destination.RegionID))
315 return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall); 276 return m_remoteConnector.CreateObject(destination, newPosition, sog, isLocalCall);
316 277
317 return false; 278 return false;
318 } 279 }
319 280
320 #endregion /* IInterregionComms */ 281 #endregion
321 } 282 }
322} 283}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index fcfdf7c..efc4998 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -464,7 +464,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
464 // or creator data is present. Otherwise, use the estate owner instead. 464 // or creator data is present. Otherwise, use the estate owner instead.
465 foreach (SceneObjectPart part in sceneObject.Parts) 465 foreach (SceneObjectPart part in sceneObject.Parts)
466 { 466 {
467 if (part.CreatorData == null || part.CreatorData == string.Empty) 467 if (string.IsNullOrEmpty(part.CreatorData))
468 { 468 {
469 if (!ResolveUserUuid(scene, part.CreatorID)) 469 if (!ResolveUserUuid(scene, part.CreatorID))
470 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; 470 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
@@ -515,7 +515,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
515 kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; 515 kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
516 } 516 }
517 517
518 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) 518 if (string.IsNullOrEmpty(kvp.Value.CreatorData))
519 { 519 {
520 if (!ResolveUserUuid(scene, kvp.Value.CreatorID)) 520 if (!ResolveUserUuid(scene, kvp.Value.CreatorID))
521 kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; 521 kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index a990898..7a844f4 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -178,7 +178,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
178 178
179 // Archive the regions 179 // Archive the regions
180 180
181 Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>(); 181 Dictionary<UUID, sbyte> assetUuids = new Dictionary<UUID, sbyte>();
182 182
183 scenesGroup.ForEachScene(delegate(Scene scene) 183 scenesGroup.ForEachScene(delegate(Scene scene)
184 { 184 {
@@ -216,7 +216,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
216 } 216 }
217 } 217 }
218 218
219 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids) 219 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids)
220 { 220 {
221 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); 221 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName);
222 222
@@ -276,16 +276,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
276 RegionSettings regionSettings = scene.RegionInfo.RegionSettings; 276 RegionSettings regionSettings = scene.RegionInfo.RegionSettings;
277 277
278 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) 278 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
279 assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; 279 assetUuids[regionSettings.TerrainTexture1] = (sbyte)AssetType.Texture;
280 280
281 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) 281 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
282 assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; 282 assetUuids[regionSettings.TerrainTexture2] = (sbyte)AssetType.Texture;
283 283
284 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) 284 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
285 assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; 285 assetUuids[regionSettings.TerrainTexture3] = (sbyte)AssetType.Texture;
286 286
287 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) 287 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
288 assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; 288 assetUuids[regionSettings.TerrainTexture4] = (sbyte)AssetType.Texture;
289 289
290 Save(scene, sceneObjects, regionDir); 290 Save(scene, sceneObjects, regionDir);
291 } 291 }
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index ada7ecc..6c2a631 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -81,7 +81,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
81 /// <value> 81 /// <value>
82 /// uuids to request 82 /// uuids to request
83 /// </value> 83 /// </value>
84 protected IDictionary<UUID, AssetType> m_uuids; 84 protected IDictionary<UUID, sbyte> m_uuids;
85 85
86 /// <value> 86 /// <value>
87 /// Callback used when all the assets requested have been received. 87 /// Callback used when all the assets requested have been received.
@@ -115,7 +115,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
115 protected Dictionary<string, object> m_options; 115 protected Dictionary<string, object> m_options;
116 116
117 protected internal AssetsRequest( 117 protected internal AssetsRequest(
118 AssetsArchiver assetsArchiver, IDictionary<UUID, AssetType> uuids, 118 AssetsArchiver assetsArchiver, IDictionary<UUID, sbyte> uuids,
119 IAssetService assetService, IUserAccountService userService, 119 IAssetService assetService, IUserAccountService userService,
120 UUID scope, Dictionary<string, object> options, 120 UUID scope, Dictionary<string, object> options,
121 AssetsRequestCallback assetsRequestCallback) 121 AssetsRequestCallback assetsRequestCallback)
@@ -154,7 +154,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
154 154
155 m_requestCallbackTimer.Enabled = true; 155 m_requestCallbackTimer.Enabled = true;
156 156
157 foreach (KeyValuePair<UUID, AssetType> kvp in m_uuids) 157 foreach (KeyValuePair<UUID, sbyte> kvp in m_uuids)
158 { 158 {
159// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); 159// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key);
160 160
@@ -235,9 +235,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
235 // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer 235 // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer
236 if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown) 236 if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown)
237 { 237 {
238 AssetType type = (AssetType)assetType; 238 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, SLUtil.AssetTypeFromCode((sbyte)assetType));
239 m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, type); 239 fetchedAsset.Type = (sbyte)assetType;
240 fetchedAsset.Type = (sbyte)type;
241 } 240 }
242 241
243 AssetRequestCallback(fetchedAssetID, this, fetchedAsset); 242 AssetRequestCallback(fetchedAssetID, this, fetchedAsset);
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
index 4d49794..1659493 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementCommands.cs
@@ -60,7 +60,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
60 60
61 public void Initialise() 61 public void Initialise()
62 { 62 {
63 m_log.DebugFormat("[ESTATE MODULE]: Setting up estate commands for region {0}", m_module.Scene.RegionInfo.RegionName); 63// m_log.DebugFormat("[ESTATE MODULE]: Setting up estate commands for region {0}", m_module.Scene.RegionInfo.RegionName);
64 64
65 m_module.Scene.AddCommand("Regions", m_module, "set terrain texture", 65 m_module.Scene.AddCommand("Regions", m_module, "set terrain texture",
66 "set terrain texture <number> <uuid> [<x>] [<y>]", 66 "set terrain texture <number> <uuid> [<x>] [<y>]",
@@ -76,6 +76,13 @@ namespace OpenSim.Region.CoreModules.World.Estate
76 " that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.", 76 " that coordinate. Corner # SW = 0, NW = 1, SE = 2, NE = 3, all corners = -1.",
77 consoleSetTerrainHeights); 77 consoleSetTerrainHeights);
78 78
79 m_module.Scene.AddCommand("Regions", m_module, "set water height",
80 "set water height <height> [<x>] [<y>]",
81 "Sets the water height in meters. If <x> and <y> are specified, it will only set it on regions with a matching coordinate. " +
82 "Specify -1 in <x> or <y> to wildcard that coordinate.",
83 consoleSetWaterHeight);
84
85
79 m_module.Scene.AddCommand( 86 m_module.Scene.AddCommand(
80 "Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand); 87 "Estates", m_module, "estate show", "estate show", "Shows all estates on the simulator.", ShowEstatesCommand);
81 } 88 }
@@ -121,7 +128,29 @@ namespace OpenSim.Region.CoreModules.World.Estate
121 } 128 }
122 } 129 }
123 } 130 }
124 131 protected void consoleSetWaterHeight(string module, string[] args)
132 {
133 string heightstring = args[3];
134
135 int x = (args.Length > 4 ? int.Parse(args[4]) : -1);
136 int y = (args.Length > 5 ? int.Parse(args[5]) : -1);
137
138 if (x == -1 || m_module.Scene.RegionInfo.RegionLocX == x)
139 {
140 if (y == -1 || m_module.Scene.RegionInfo.RegionLocY == y)
141 {
142 double selectedheight = double.Parse(heightstring);
143
144 m_log.Debug("[ESTATEMODULE]: Setting water height in " + m_module.Scene.RegionInfo.RegionName + " to " +
145 string.Format(" {0}", selectedheight));
146 m_module.Scene.RegionInfo.RegionSettings.WaterHeight = selectedheight;
147
148 m_module.Scene.RegionInfo.RegionSettings.Save();
149 m_module.TriggerRegionInfoChange();
150 m_module.sendRegionHandshakeToAll();
151 }
152 }
153 }
125 protected void consoleSetTerrainHeights(string module, string[] args) 154 protected void consoleSetTerrainHeights(string module, string[] args)
126 { 155 {
127 string num = args[3]; 156 string num = args[3];
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 834fd77..47390e7 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -576,7 +576,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
576 if (!Scene.TeleportClientHome(user, s.ControllingClient)) 576 if (!Scene.TeleportClientHome(user, s.ControllingClient))
577 { 577 {
578 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out."); 578 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out.");
579 s.ControllingClient.Close(); 579 Scene.CloseAgent(s.UUID, false);
580 } 580 }
581 } 581 }
582 } 582 }
@@ -716,7 +716,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
716 } 716 }
717 } 717 }
718 718
719 public void handleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) 719 public void HandleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1)
720 { 720 {
721 SceneObjectPart part; 721 SceneObjectPart part;
722 722
@@ -756,7 +756,9 @@ namespace OpenSim.Region.CoreModules.World.Estate
756 default: 756 default:
757 break; 757 break;
758 } 758 }
759 SendTelehubInfo(client); 759
760 if (client != null)
761 SendTelehubInfo(client);
760 } 762 }
761 763
762 private void SendSimulatorBlueBoxMessage( 764 private void SendSimulatorBlueBoxMessage(
@@ -811,7 +813,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
811 if (!Scene.TeleportClientHome(prey, s.ControllingClient)) 813 if (!Scene.TeleportClientHome(prey, s.ControllingClient))
812 { 814 {
813 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); 815 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
814 s.ControllingClient.Close(); 816 Scene.CloseAgent(s.UUID, false);
815 } 817 }
816 } 818 }
817 } 819 }
@@ -834,7 +836,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
834 if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient)) 836 if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient))
835 { 837 {
836 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); 838 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
837 p.ControllingClient.Close(); 839 Scene.CloseAgent(p.UUID, false);
838 } 840 }
839 } 841 }
840 } 842 }
@@ -843,26 +845,23 @@ namespace OpenSim.Region.CoreModules.World.Estate
843 845
844 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID) 846 private void AbortTerrainXferHandler(IClientAPI remoteClient, ulong XferID)
845 { 847 {
846 if (TerrainUploader != null) 848 lock (this)
847 { 849 {
848 lock (TerrainUploader) 850 if ((TerrainUploader != null) && (XferID == TerrainUploader.XferID))
849 { 851 {
850 if (XferID == TerrainUploader.XferID) 852 remoteClient.OnXferReceive -= TerrainUploader.XferReceive;
851 { 853 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
852 remoteClient.OnXferReceive -= TerrainUploader.XferReceive; 854 TerrainUploader.TerrainUploadDone -= HandleTerrainApplication;
853 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
854 TerrainUploader.TerrainUploadDone -= HandleTerrainApplication;
855 855
856 TerrainUploader = null; 856 TerrainUploader = null;
857 remoteClient.SendAlertMessage("Terrain Upload aborted by the client"); 857 remoteClient.SendAlertMessage("Terrain Upload aborted by the client");
858 }
859 } 858 }
860 } 859 }
861
862 } 860 }
861
863 private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient) 862 private void HandleTerrainApplication(string filename, byte[] terrainData, IClientAPI remoteClient)
864 { 863 {
865 lock (TerrainUploader) 864 lock (this)
866 { 865 {
867 remoteClient.OnXferReceive -= TerrainUploader.XferReceive; 866 remoteClient.OnXferReceive -= TerrainUploader.XferReceive;
868 remoteClient.OnAbortXfer -= AbortTerrainXferHandler; 867 remoteClient.OnAbortXfer -= AbortTerrainXferHandler;
@@ -921,22 +920,32 @@ namespace OpenSim.Region.CoreModules.World.Estate
921 920
922 private void handleUploadTerrain(IClientAPI remote_client, string clientFileName) 921 private void handleUploadTerrain(IClientAPI remote_client, string clientFileName)
923 { 922 {
924 if (TerrainUploader == null) 923 lock (this)
925 { 924 {
926 925 if (TerrainUploader == null)
927 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName);
928 lock (TerrainUploader)
929 { 926 {
927 m_log.DebugFormat("Starting to receive uploaded terrain");
928 TerrainUploader = new EstateTerrainXferHandler(remote_client, clientFileName);
930 remote_client.OnXferReceive += TerrainUploader.XferReceive; 929 remote_client.OnXferReceive += TerrainUploader.XferReceive;
931 remote_client.OnAbortXfer += AbortTerrainXferHandler; 930 remote_client.OnAbortXfer += AbortTerrainXferHandler;
932 TerrainUploader.TerrainUploadDone += HandleTerrainApplication; 931 TerrainUploader.TerrainUploadDone += HandleTerrainApplication;
932 TerrainUploader.RequestStartXfer(remote_client);
933 }
934 else
935 {
936 remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!");
933 } 937 }
934 TerrainUploader.RequestStartXfer(remote_client);
935
936 } 938 }
937 else 939 }
940
941 public bool IsTerrainXfer(ulong xferID)
942 {
943 lock (this)
938 { 944 {
939 remote_client.SendAlertMessage("Another Terrain Upload is in progress. Please wait your turn!"); 945 if (TerrainUploader == null)
946 return false;
947 else
948 return TerrainUploader.XferID == xferID;
940 } 949 }
941 } 950 }
942 951
@@ -1221,7 +1230,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
1221 client.OnEstateRestartSimRequest += handleEstateRestartSimRequest; 1230 client.OnEstateRestartSimRequest += handleEstateRestartSimRequest;
1222 client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest; 1231 client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest;
1223 client.OnEstateChangeInfo += handleEstateChangeInfo; 1232 client.OnEstateChangeInfo += handleEstateChangeInfo;
1224 client.OnEstateManageTelehub += handleOnEstateManageTelehub; 1233 client.OnEstateManageTelehub += HandleOnEstateManageTelehub;
1225 client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest; 1234 client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest;
1226 client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage; 1235 client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage;
1227 client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage; 1236 client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage;
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs b/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
index b8d8b10..2d74eaf 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateTerrainXferHandler.cs
@@ -78,7 +78,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
78 /// <param name="data"></param> 78 /// <param name="data"></param>
79 public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data) 79 public void XferReceive(IClientAPI remoteClient, ulong xferID, uint packetID, byte[] data)
80 { 80 {
81 if (mXferID == xferID) 81 if (mXferID != xferID)
82 return;
83
84 lock (this)
82 { 85 {
83 if (m_asset.Data.Length > 1) 86 if (m_asset.Data.Length > 1)
84 { 87 {
@@ -99,7 +102,6 @@ namespace OpenSim.Region.CoreModules.World.Estate
99 if ((packetID & 0x80000000) != 0) 102 if ((packetID & 0x80000000) != 0)
100 { 103 {
101 SendCompleteMessage(remoteClient); 104 SendCompleteMessage(remoteClient);
102
103 } 105 }
104 } 106 }
105 } 107 }
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs
new file mode 100644
index 0000000..73e706c
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs
@@ -0,0 +1,218 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31
32using OpenSim.Services.Interfaces;
33using GridRegion = OpenSim.Services.Interfaces.GridRegion;
34using OpenSim.Server.Base;
35using OpenSim.Framework.Servers.HttpServer;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Scenes;
38
39using OpenMetaverse;
40using log4net;
41
42namespace OpenSim.Region.CoreModules.World.Estate
43{
44 public class EstateConnector
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 protected XEstateModule m_EstateModule;
49
50 public EstateConnector(XEstateModule module)
51 {
52 m_EstateModule = module;
53 }
54
55 public void SendTeleportHomeOneUser(uint EstateID, UUID PreyID)
56 {
57 Dictionary<string, object> sendData = new Dictionary<string, object>();
58 sendData["METHOD"] = "teleport_home_one_user";
59
60 sendData["EstateID"] = EstateID.ToString();
61 sendData["PreyID"] = PreyID.ToString();
62
63 SendToEstate(EstateID, sendData);
64 }
65
66 public void SendTeleportHomeAllUsers(uint EstateID)
67 {
68 Dictionary<string, object> sendData = new Dictionary<string, object>();
69 sendData["METHOD"] = "teleport_home_all_users";
70
71 sendData["EstateID"] = EstateID.ToString();
72
73 SendToEstate(EstateID, sendData);
74 }
75
76 public bool SendUpdateCovenant(uint EstateID, UUID CovenantID)
77 {
78 Dictionary<string, object> sendData = new Dictionary<string, object>();
79 sendData["METHOD"] = "update_covenant";
80
81 sendData["CovenantID"] = CovenantID.ToString();
82 sendData["EstateID"] = EstateID.ToString();
83
84 // Handle local regions locally
85 //
86 foreach (Scene s in m_EstateModule.Scenes)
87 {
88 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
89 s.RegionInfo.RegionSettings.Covenant = CovenantID;
90// s.ReloadEstateData();
91 }
92
93 SendToEstate(EstateID, sendData);
94
95 return true;
96 }
97
98 public bool SendUpdateEstate(uint EstateID)
99 {
100 Dictionary<string, object> sendData = new Dictionary<string, object>();
101 sendData["METHOD"] = "update_estate";
102
103 sendData["EstateID"] = EstateID.ToString();
104
105 // Handle local regions locally
106 //
107 foreach (Scene s in m_EstateModule.Scenes)
108 {
109 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
110 s.ReloadEstateData();
111 }
112
113 SendToEstate(EstateID, sendData);
114
115 return true;
116 }
117
118 public void SendEstateMessage(uint EstateID, UUID FromID, string FromName, string Message)
119 {
120 Dictionary<string, object> sendData = new Dictionary<string, object>();
121 sendData["METHOD"] = "estate_message";
122
123 sendData["EstateID"] = EstateID.ToString();
124 sendData["FromID"] = FromID.ToString();
125 sendData["FromName"] = FromName;
126 sendData["Message"] = Message;
127
128 SendToEstate(EstateID, sendData);
129 }
130
131 private void SendToEstate(uint EstateID, Dictionary<string, object> sendData)
132 {
133 List<UUID> regions = m_EstateModule.Scenes[0].GetEstateRegions((int)EstateID);
134
135 UUID ScopeID = UUID.Zero;
136
137 // Handle local regions locally
138 //
139 lock (m_EstateModule.Scenes)
140 {
141 foreach (Scene s in m_EstateModule.Scenes)
142 {
143 if (regions.Contains(s.RegionInfo.RegionID))
144 {
145 // All regions in one estate are in the same scope.
146 // Use that scope.
147 //
148 ScopeID = s.RegionInfo.ScopeID;
149 regions.Remove(s.RegionInfo.RegionID);
150 }
151 }
152 }
153
154 // Our own region should always be in the above list.
155 // In a standalone this would not be true. But then,
156 // Scope ID is not relevat there. Use first scope.
157 //
158 if (ScopeID == UUID.Zero)
159 ScopeID = m_EstateModule.Scenes[0].RegionInfo.ScopeID;
160
161 // Don't send to the same instance twice
162 //
163 List<string> done = new List<string>();
164
165 // Send to remote regions
166 //
167 foreach (UUID regionID in regions)
168 {
169 GridRegion region = m_EstateModule.Scenes[0].GridService.GetRegionByUUID(ScopeID, regionID);
170 if (region != null)
171 {
172 string url = "http://" + region.ExternalHostName + ":" + region.HttpPort;
173 if (done.Contains(url))
174 continue;
175
176 Call(region, sendData);
177 done.Add(url);
178 }
179 }
180 }
181
182 private bool Call(GridRegion region, Dictionary<string, object> sendData)
183 {
184 string reqString = ServerUtils.BuildQueryString(sendData);
185 // m_log.DebugFormat("[XESTATE CONNECTOR]: queryString = {0}", reqString);
186 try
187 {
188 string url = "http://" + region.ExternalHostName + ":" + region.HttpPort;
189 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
190 url + "/estate",
191 reqString);
192 if (reply != string.Empty)
193 {
194 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
195
196 if (replyData.ContainsKey("RESULT"))
197 {
198 if (replyData["RESULT"].ToString().ToLower() == "true")
199 return true;
200 else
201 return false;
202 }
203 else
204 m_log.DebugFormat("[XESTATE CONNECTOR]: reply data does not contain result field");
205
206 }
207 else
208 m_log.DebugFormat("[XESTATE CONNECTOR]: received empty reply");
209 }
210 catch (Exception e)
211 {
212 m_log.DebugFormat("[XESTATE CONNECTOR]: Exception when contacting remote sim: {0}", e.Message);
213 }
214
215 return false;
216 }
217 }
218}
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs
new file mode 100644
index 0000000..f54ab2c
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs
@@ -0,0 +1,256 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using Nwc.XmlRpc;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Framework.Communications;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Server.Base;
42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Servers.HttpServer;
44using Mono.Addins;
45
46namespace OpenSim.Region.CoreModules.World.Estate
47{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XEstate")]
49 public class XEstateModule : ISharedRegionModule
50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 protected List<Scene> m_Scenes = new List<Scene>();
54 protected bool m_InInfoUpdate = false;
55
56 public bool InInfoUpdate
57 {
58 get { return m_InInfoUpdate; }
59 set { m_InInfoUpdate = value; }
60 }
61
62 public List<Scene> Scenes
63 {
64 get { return m_Scenes; }
65 }
66
67 protected EstateConnector m_EstateConnector;
68
69 public void Initialise(IConfigSource config)
70 {
71 int port = 0;
72
73 IConfig estateConfig = config.Configs["Estate"];
74 if (estateConfig != null)
75 {
76 port = estateConfig.GetInt("Port", 0);
77 }
78
79 m_EstateConnector = new EstateConnector(this);
80
81 // Instantiate the request handler
82 IHttpServer server = MainServer.GetHttpServer((uint)port);
83 server.AddStreamHandler(new EstateRequestHandler(this));
84 }
85
86 public void PostInitialise()
87 {
88 }
89
90 public void Close()
91 {
92 }
93
94 public void AddRegion(Scene scene)
95 {
96 lock (m_Scenes)
97 m_Scenes.Add(scene);
98
99 scene.EventManager.OnNewClient += OnNewClient;
100 }
101
102 public void RegionLoaded(Scene scene)
103 {
104 IEstateModule em = scene.RequestModuleInterface<IEstateModule>();
105
106 em.OnRegionInfoChange += OnRegionInfoChange;
107 em.OnEstateInfoChange += OnEstateInfoChange;
108 em.OnEstateMessage += OnEstateMessage;
109 }
110
111 public void RemoveRegion(Scene scene)
112 {
113 scene.EventManager.OnNewClient -= OnNewClient;
114
115 lock (m_Scenes)
116 m_Scenes.Remove(scene);
117 }
118
119 public string Name
120 {
121 get { return "EstateModule"; }
122 }
123
124 public Type ReplaceableInterface
125 {
126 get { return null; }
127 }
128
129 private Scene FindScene(UUID RegionID)
130 {
131 foreach (Scene s in Scenes)
132 {
133 if (s.RegionInfo.RegionID == RegionID)
134 return s;
135 }
136
137 return null;
138 }
139
140 private void OnRegionInfoChange(UUID RegionID)
141 {
142 Scene s = FindScene(RegionID);
143 if (s == null)
144 return;
145
146 if (!m_InInfoUpdate)
147 m_EstateConnector.SendUpdateCovenant(s.RegionInfo.EstateSettings.EstateID, s.RegionInfo.RegionSettings.Covenant);
148 }
149
150 private void OnEstateInfoChange(UUID RegionID)
151 {
152 Scene s = FindScene(RegionID);
153 if (s == null)
154 return;
155
156 if (!m_InInfoUpdate)
157 m_EstateConnector.SendUpdateEstate(s.RegionInfo.EstateSettings.EstateID);
158 }
159
160 private void OnEstateMessage(UUID RegionID, UUID FromID, string FromName, string Message)
161 {
162 Scene senderScenes = FindScene(RegionID);
163 if (senderScenes == null)
164 return;
165
166 uint estateID = senderScenes.RegionInfo.EstateSettings.EstateID;
167
168 foreach (Scene s in Scenes)
169 {
170 if (s.RegionInfo.EstateSettings.EstateID == estateID)
171 {
172 IDialogModule dm = s.RequestModuleInterface<IDialogModule>();
173
174 if (dm != null)
175 {
176 dm.SendNotificationToUsersInRegion(FromID, FromName,
177 Message);
178 }
179 }
180 }
181 if (!m_InInfoUpdate)
182 m_EstateConnector.SendEstateMessage(estateID, FromID, FromName, Message);
183 }
184
185 private void OnNewClient(IClientAPI client)
186 {
187 client.OnEstateTeleportOneUserHomeRequest += OnEstateTeleportOneUserHomeRequest;
188 client.OnEstateTeleportAllUsersHomeRequest += OnEstateTeleportAllUsersHomeRequest;
189
190 }
191
192 private void OnEstateTeleportOneUserHomeRequest(IClientAPI client, UUID invoice, UUID senderID, UUID prey)
193 {
194 if (prey == UUID.Zero)
195 return;
196
197 if (!(client.Scene is Scene))
198 return;
199
200 Scene scene = (Scene)client.Scene;
201
202 uint estateID = scene.RegionInfo.EstateSettings.EstateID;
203
204 if (!scene.Permissions.CanIssueEstateCommand(client.AgentId, false))
205 return;
206
207 foreach (Scene s in Scenes)
208 {
209 if (s == scene)
210 continue; // Already handles by estate module
211 if (s.RegionInfo.EstateSettings.EstateID != estateID)
212 continue;
213
214 ScenePresence p = scene.GetScenePresence(prey);
215 if (p != null && !p.IsChildAgent)
216 {
217 p.ControllingClient.SendTeleportStart(16);
218 scene.TeleportClientHome(prey, p.ControllingClient);
219 }
220 }
221
222 m_EstateConnector.SendTeleportHomeOneUser(estateID, prey);
223 }
224
225 private void OnEstateTeleportAllUsersHomeRequest(IClientAPI client, UUID invoice, UUID senderID)
226 {
227 if (!(client.Scene is Scene))
228 return;
229
230 Scene scene = (Scene)client.Scene;
231
232 uint estateID = scene.RegionInfo.EstateSettings.EstateID;
233
234 if (!scene.Permissions.CanIssueEstateCommand(client.AgentId, false))
235 return;
236
237 foreach (Scene s in Scenes)
238 {
239 if (s == scene)
240 continue; // Already handles by estate module
241 if (s.RegionInfo.EstateSettings.EstateID != estateID)
242 continue;
243
244 scene.ForEachScenePresence(delegate(ScenePresence p) {
245 if (p != null && !p.IsChildAgent)
246 {
247 p.ControllingClient.SendTeleportStart(16);
248 scene.TeleportClientHome(p.ControllingClient.AgentId, p.ControllingClient);
249 }
250 });
251 }
252
253 m_EstateConnector.SendTeleportHomeAllUsers(estateID);
254 }
255 }
256}
diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs
new file mode 100644
index 0000000..2366767
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs
@@ -0,0 +1,298 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Xml;
33
34using OpenSim.Framework;
35using OpenSim.Server.Base;
36using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Region.Framework.Interfaces;
39
40using OpenMetaverse;
41using log4net;
42
43namespace OpenSim.Region.CoreModules.World.Estate
44{
45 public class EstateRequestHandler : BaseStreamHandler
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 protected XEstateModule m_EstateModule;
50 protected Object m_RequestLock = new Object();
51
52 public EstateRequestHandler(XEstateModule fmodule)
53 : base("POST", "/estate")
54 {
55 m_EstateModule = fmodule;
56 }
57
58 protected override byte[] ProcessRequest(string path, Stream requestData,
59 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
60 {
61 StreamReader sr = new StreamReader(requestData);
62 string body = sr.ReadToEnd();
63 sr.Close();
64 body = body.Trim();
65
66 m_log.DebugFormat("[XESTATE HANDLER]: query String: {0}", body);
67
68 try
69 {
70 lock (m_RequestLock)
71 {
72 Dictionary<string, object> request =
73 ServerUtils.ParseQueryString(body);
74
75 if (!request.ContainsKey("METHOD"))
76 return FailureResult();
77
78 string method = request["METHOD"].ToString();
79 request.Remove("METHOD");
80
81 try
82 {
83 m_EstateModule.InInfoUpdate = false;
84
85 switch (method)
86 {
87 case "update_covenant":
88 return UpdateCovenant(request);
89 case "update_estate":
90 return UpdateEstate(request);
91 case "estate_message":
92 return EstateMessage(request);
93 case "teleport_home_one_user":
94 return TeleportHomeOneUser(request);
95 case "teleport_home_all_users":
96 return TeleportHomeAllUsers(request);
97 }
98 }
99 finally
100 {
101 m_EstateModule.InInfoUpdate = false;
102 }
103 }
104 }
105 catch (Exception e)
106 {
107 m_log.Debug("[XESTATE]: Exception {0}" + e.ToString());
108 }
109
110 return FailureResult();
111 }
112
113 byte[] TeleportHomeAllUsers(Dictionary<string, object> request)
114 {
115 UUID PreyID = UUID.Zero;
116 int EstateID = 0;
117
118 if (!request.ContainsKey("EstateID"))
119 return FailureResult();
120
121 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
122 return FailureResult();
123
124 foreach (Scene s in m_EstateModule.Scenes)
125 {
126 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
127 {
128 s.ForEachScenePresence(delegate(ScenePresence p) {
129 if (p != null && !p.IsChildAgent)
130 {
131 p.ControllingClient.SendTeleportStart(16);
132 s.TeleportClientHome(p.ControllingClient.AgentId, p.ControllingClient);
133 }
134 });
135 }
136 }
137
138 return SuccessResult();
139 }
140
141 byte[] TeleportHomeOneUser(Dictionary<string, object> request)
142 {
143 UUID PreyID = UUID.Zero;
144 int EstateID = 0;
145
146 if (!request.ContainsKey("PreyID") ||
147 !request.ContainsKey("EstateID"))
148 {
149 return FailureResult();
150 }
151
152 if (!UUID.TryParse(request["PreyID"].ToString(), out PreyID))
153 return FailureResult();
154
155 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
156 return FailureResult();
157
158 foreach (Scene s in m_EstateModule.Scenes)
159 {
160 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
161 {
162 ScenePresence p = s.GetScenePresence(PreyID);
163 if (p != null && !p.IsChildAgent)
164 {
165 p.ControllingClient.SendTeleportStart(16);
166 s.TeleportClientHome(PreyID, p.ControllingClient);
167 }
168 }
169 }
170
171 return SuccessResult();
172 }
173
174 byte[] EstateMessage(Dictionary<string, object> request)
175 {
176 UUID FromID = UUID.Zero;
177 string FromName = String.Empty;
178 string Message = String.Empty;
179 int EstateID = 0;
180
181 if (!request.ContainsKey("FromID") ||
182 !request.ContainsKey("FromName") ||
183 !request.ContainsKey("Message") ||
184 !request.ContainsKey("EstateID"))
185 {
186 return FailureResult();
187 }
188
189 if (!UUID.TryParse(request["FromID"].ToString(), out FromID))
190 return FailureResult();
191
192 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
193 return FailureResult();
194
195 FromName = request["FromName"].ToString();
196 Message = request["Message"].ToString();
197
198 foreach (Scene s in m_EstateModule.Scenes)
199 {
200 if (s.RegionInfo.EstateSettings.EstateID == EstateID)
201 {
202 IDialogModule dm = s.RequestModuleInterface<IDialogModule>();
203
204 if (dm != null)
205 {
206 dm.SendNotificationToUsersInRegion(FromID, FromName,
207 Message);
208 }
209 }
210 }
211
212 return SuccessResult();
213 }
214
215 byte[] UpdateCovenant(Dictionary<string, object> request)
216 {
217 UUID CovenantID = UUID.Zero;
218 int EstateID = 0;
219
220 if (!request.ContainsKey("CovenantID") || !request.ContainsKey("EstateID"))
221 return FailureResult();
222
223 if (!UUID.TryParse(request["CovenantID"].ToString(), out CovenantID))
224 return FailureResult();
225
226 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
227 return FailureResult();
228
229 foreach (Scene s in m_EstateModule.Scenes)
230 {
231 if (s.RegionInfo.EstateSettings.EstateID == (uint)EstateID)
232 s.RegionInfo.RegionSettings.Covenant = CovenantID;
233 }
234
235 return SuccessResult();
236 }
237
238 byte[] UpdateEstate(Dictionary<string, object> request)
239 {
240 int EstateID = 0;
241
242 if (!request.ContainsKey("EstateID"))
243 return FailureResult();
244 if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID))
245 return FailureResult();
246
247 foreach (Scene s in m_EstateModule.Scenes)
248 {
249 if (s.RegionInfo.EstateSettings.EstateID == (uint)EstateID)
250 s.ReloadEstateData();
251 }
252 return SuccessResult();
253 }
254
255 private byte[] FailureResult()
256 {
257 return BoolResult(false);
258 }
259
260 private byte[] SuccessResult()
261 {
262 return BoolResult(true);
263 }
264
265 private byte[] BoolResult(bool value)
266 {
267 XmlDocument doc = new XmlDocument();
268
269 XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
270 "", "");
271
272 doc.AppendChild(xmlnode);
273
274 XmlElement rootElement = doc.CreateElement("", "ServerResponse",
275 "");
276
277 doc.AppendChild(rootElement);
278
279 XmlElement result = doc.CreateElement("", "RESULT", "");
280 result.AppendChild(doc.CreateTextNode(value.ToString()));
281
282 rootElement.AppendChild(result);
283
284 return DocToBytes(doc);
285 }
286
287 private byte[] DocToBytes(XmlDocument doc)
288 {
289 MemoryStream ms = new MemoryStream();
290 XmlTextWriter xw = new XmlTextWriter(ms, null);
291 xw.Formatting = Formatting.Indented;
292 doc.WriteTo(xw);
293 xw.Flush();
294
295 return ms.ToArray();
296 }
297 }
298}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 4e21724..0e2aba9 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -42,7 +42,6 @@ using OpenSim.Framework.Capabilities;
42using OpenSim.Framework.Console; 42using OpenSim.Framework.Console;
43using OpenSim.Framework.Servers; 43using OpenSim.Framework.Servers;
44using OpenSim.Framework.Servers.HttpServer; 44using OpenSim.Framework.Servers.HttpServer;
45using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
46using OpenSim.Region.Framework.Interfaces; 45using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes; 46using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Physics.Manager; 47using OpenSim.Region.Physics.Manager;
@@ -70,10 +69,10 @@ namespace OpenSim.Region.CoreModules.World.Land
70 69
71 private LandChannel landChannel; 70 private LandChannel landChannel;
72 private Scene m_scene; 71 private Scene m_scene;
73 protected Commander m_commander = new Commander("land");
74 72
75 protected IUserManagement m_userManager; 73 protected IUserManagement m_userManager;
76 protected IPrimCountModule m_primCountModule; 74 protected IPrimCountModule m_primCountModule;
75 protected IDialogModule m_Dialog;
77 76
78 // Minimum for parcels to work is 64m even if we don't actually use them. 77 // Minimum for parcels to work is 64m even if we don't actually use them.
79 #pragma warning disable 0429 78 #pragma warning disable 0429
@@ -147,52 +146,33 @@ namespace OpenSim.Region.CoreModules.World.Land
147 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage; 146 m_scene.EventManager.OnIncomingLandDataFromStorage += EventManagerOnIncomingLandDataFromStorage;
148 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan; 147 m_scene.EventManager.OnSetAllowForcefulBan += EventManagerOnSetAllowedForcefulBan;
149 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps; 148 m_scene.EventManager.OnRegisterCaps += EventManagerOnRegisterCaps;
150 m_scene.EventManager.OnPluginConsole += EventManagerOnPluginConsole;
151 149
152 lock (m_scene) 150 lock (m_scene)
153 { 151 {
154 m_scene.LandChannel = (ILandChannel)landChannel; 152 m_scene.LandChannel = (ILandChannel)landChannel;
155 } 153 }
156 154
157 InstallInterfaces(); 155 RegisterCommands();
158 } 156 }
159 157
160 public void RegionLoaded(Scene scene) 158 public void RegionLoaded(Scene scene)
161 { 159 {
162 m_userManager = m_scene.RequestModuleInterface<IUserManagement>(); 160 m_userManager = m_scene.RequestModuleInterface<IUserManagement>();
163 m_primCountModule = m_scene.RequestModuleInterface<IPrimCountModule>(); 161 m_primCountModule = m_scene.RequestModuleInterface<IPrimCountModule>();
162 m_Dialog = m_scene.RequestModuleInterface<IDialogModule>();
164 } 163 }
165 164
166 public void RemoveRegion(Scene scene) 165 public void RemoveRegion(Scene scene)
167 { 166 {
168 // TODO: Also release other event manager listeners here 167 // TODO: Release event manager listeners here
169
170 m_scene.EventManager.OnPluginConsole -= EventManagerOnPluginConsole;
171 m_scene.UnregisterModuleCommander(m_commander.Name);
172 } 168 }
173 169
174 /// <summary> 170// private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason)
175 /// Processes commandline input. Do not call directly. 171// {
176 /// </summary> 172// ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y);
177 /// <param name="args">Commandline arguments</param> 173// reason = "You are not allowed to enter this sim.";
178 protected void EventManagerOnPluginConsole(string[] args) 174// return nearestParcel != null;
179 { 175// }
180 if (args[0] == "land")
181 {
182 if (args.Length == 1)
183 {
184 m_commander.ProcessConsoleCommand("help", new string[0]);
185 return;
186 }
187
188 string[] tmpArgs = new string[args.Length - 2];
189 int i;
190 for (i = 2; i < args.Length; i++)
191 tmpArgs[i - 2] = args[i];
192
193 m_commander.ProcessConsoleCommand(args[1], tmpArgs);
194 }
195 }
196 176
197 void EventManagerOnNewClient(IClientAPI client) 177 void EventManagerOnNewClient(IClientAPI client)
198 { 178 {
@@ -213,6 +193,7 @@ namespace OpenSim.Region.CoreModules.World.Land
213 client.OnPreAgentUpdate += ClientOnPreAgentUpdate; 193 client.OnPreAgentUpdate += ClientOnPreAgentUpdate;
214 client.OnParcelEjectUser += ClientOnParcelEjectUser; 194 client.OnParcelEjectUser += ClientOnParcelEjectUser;
215 client.OnParcelFreezeUser += ClientOnParcelFreezeUser; 195 client.OnParcelFreezeUser += ClientOnParcelFreezeUser;
196 client.OnSetStartLocationRequest += ClientOnSetHome;
216 197
217 EntityBase presenceEntity; 198 EntityBase presenceEntity;
218 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) 199 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence)
@@ -1896,44 +1877,131 @@ namespace OpenSim.Region.CoreModules.World.Land
1896 land.LandData.ParcelAccessList.Add(entry); 1877 land.LandData.ParcelAccessList.Add(entry);
1897 } 1878 }
1898 } 1879 }
1899 1880
1900 protected void InstallInterfaces() 1881 /// <summary>
1882 /// Sets the Home Point. The LoginService uses this to know where to put a user when they log-in
1883 /// </summary>
1884 /// <param name="remoteClient"></param>
1885 /// <param name="regionHandle"></param>
1886 /// <param name="position"></param>
1887 /// <param name="lookAt"></param>
1888 /// <param name="flags"></param>
1889 public virtual void ClientOnSetHome(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
1890 {
1891 // Let's find the parcel in question
1892 ILandObject land = landChannel.GetLandObject(position);
1893 if (land == null || m_scene.GridUserService == null)
1894 {
1895 m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed.");
1896 return;
1897 }
1898
1899 // Gather some data
1900 ulong gpowers = remoteClient.GetGroupPowers(land.LandData.GroupID);
1901 SceneObjectGroup telehub = null;
1902 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero)
1903 // Does the telehub exist in the scene?
1904 telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject);
1905
1906 // Can the user set home here?
1907 if (// (a) gods and land managers can set home
1908 m_scene.Permissions.IsAdministrator(remoteClient.AgentId) ||
1909 m_scene.Permissions.IsGod(remoteClient.AgentId) ||
1910 // (b) land owners can set home
1911 remoteClient.AgentId == land.LandData.OwnerID ||
1912 // (c) members of the land-associated group in roles that can set home
1913 ((gpowers & (ulong)GroupPowers.AllowSetHome) == (ulong)GroupPowers.AllowSetHome) ||
1914 // (d) parcels with telehubs can be the home of anyone
1915 (telehub != null && land.ContainsPoint((int)telehub.AbsolutePosition.X, (int)telehub.AbsolutePosition.Y)))
1916 {
1917 if (m_scene.GridUserService.SetHome(remoteClient.AgentId.ToString(), land.RegionUUID, position, lookAt))
1918 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
1919 m_Dialog.SendAlertToUser(remoteClient, "Home position set.");
1920 else
1921 m_Dialog.SendAlertToUser(remoteClient, "Set Home request failed.");
1922 }
1923 else
1924 m_Dialog.SendAlertToUser(remoteClient, "You are not allowed to set your home location in this parcel.");
1925 }
1926
1927 protected void RegisterCommands()
1901 { 1928 {
1902 Command clearCommand 1929 ICommands commands = MainConsole.Instance.Commands;
1903 = new Command("clear", CommandIntentions.COMMAND_HAZARDOUS, ClearCommand, "Clears all the parcels from the region.");
1904 Command showCommand
1905 = new Command("show", CommandIntentions.COMMAND_STATISTICAL, ShowParcelsCommand, "Shows all parcels on the region.");
1906 1930
1907 m_commander.RegisterCommand("clear", clearCommand); 1931 commands.AddCommand(
1908 m_commander.RegisterCommand("show", showCommand); 1932 "Land", false, "land clear",
1933 "land clear",
1934 "Clear all the parcels from the region.",
1935 "Command will ask for confirmation before proceeding.",
1936 HandleClearCommand);
1909 1937
1910 // Add this to our scene so scripts can call these functions 1938 commands.AddCommand(
1911 m_scene.RegisterModuleCommander(m_commander); 1939 "Land", false, "land show",
1940 "land show [<local-land-id>]",
1941 "Show information about the parcels on the region.",
1942 "If no local land ID is given, then summary information about all the parcels is shown.\n"
1943 + "If a local land ID is given then full information about that parcel is shown.",
1944 HandleShowCommand);
1912 } 1945 }
1913 1946
1914 protected void ClearCommand(Object[] args) 1947 protected void HandleClearCommand(string module, string[] args)
1915 { 1948 {
1949 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
1950 return;
1951
1916 string response = MainConsole.Instance.CmdPrompt( 1952 string response = MainConsole.Instance.CmdPrompt(
1917 string.Format( 1953 string.Format(
1918 "Are you sure that you want to clear all land parcels from {0} (y or n)", 1954 "Are you sure that you want to clear all land parcels from {0} (y or n)", m_scene.Name),
1919 m_scene.RegionInfo.RegionName),
1920 "n"); 1955 "n");
1921 1956
1922 if (response.ToLower() == "y") 1957 if (response.ToLower() == "y")
1923 { 1958 {
1924 Clear(true); 1959 Clear(true);
1925 MainConsole.Instance.OutputFormat("Cleared all parcels from {0}", m_scene.RegionInfo.RegionName); 1960 MainConsole.Instance.OutputFormat("Cleared all parcels from {0}", m_scene.Name);
1926 } 1961 }
1927 else 1962 else
1928 { 1963 {
1929 MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.RegionInfo.RegionName); 1964 MainConsole.Instance.OutputFormat("Aborting clear of all parcels from {0}", m_scene.Name);
1930 } 1965 }
1931 } 1966 }
1932 1967
1933 protected void ShowParcelsCommand(Object[] args) 1968 protected void HandleShowCommand(string module, string[] args)
1934 { 1969 {
1935 StringBuilder report = new StringBuilder(); 1970 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_scene))
1936 1971 return;
1972
1973 StringBuilder report = new StringBuilder();
1974
1975 if (args.Length <= 2)
1976 {
1977 AppendParcelsSummaryReport(report);
1978 }
1979 else
1980 {
1981 int landLocalId;
1982
1983 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[2], out landLocalId))
1984 return;
1985
1986 ILandObject lo;
1987
1988 lock (m_landList)
1989 {
1990 if (!m_landList.TryGetValue(landLocalId, out lo))
1991 {
1992 MainConsole.Instance.OutputFormat("No parcel found with local ID {0}", landLocalId);
1993 return;
1994 }
1995 }
1996
1997 AppendParcelReport(report, lo);
1998 }
1999
2000 MainConsole.Instance.Output(report.ToString());
2001 }
2002
2003 private void AppendParcelsSummaryReport(StringBuilder report)
2004 {
1937 report.AppendFormat("Land information for {0}\n", m_scene.RegionInfo.RegionName); 2005 report.AppendFormat("Land information for {0}\n", m_scene.RegionInfo.RegionName);
1938 report.AppendFormat( 2006 report.AppendFormat(
1939 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n", 2007 "{0,-20} {1,-10} {2,-9} {3,-18} {4,-18} {5,-20}\n",
@@ -1979,6 +2047,69 @@ namespace OpenSim.Region.CoreModules.World.Land
1979 ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition); 2047 ForceAvatarToPosition(avatar, avatar.lastKnownAllowedPosition);
1980 } 2048 }
1981 } 2049 }
2050 }
2051
2052 private void AppendParcelReport(StringBuilder report, ILandObject lo)
2053 {
2054 LandData ld = lo.LandData;
2055
2056 ConsoleDisplayList cdl = new ConsoleDisplayList();
2057 cdl.AddRow("Parcel name", ld.Name);
2058 cdl.AddRow("Local ID", ld.LocalID);
2059 cdl.AddRow("Description", ld.Description);
2060 cdl.AddRow("Snapshot ID", ld.SnapshotID);
2061 cdl.AddRow("Area", ld.Area);
2062 cdl.AddRow("Starts", lo.StartPoint);
2063 cdl.AddRow("Ends", lo.EndPoint);
2064 cdl.AddRow("AABB Min", ld.AABBMin);
2065 cdl.AddRow("AABB Max", ld.AABBMax);
2066
2067 cdl.AddRow("Owner", m_userManager.GetUserName(ld.OwnerID));
2068 cdl.AddRow("Is group owned?", ld.IsGroupOwned);
2069 cdl.AddRow("GroupID", ld.GroupID);
2070
2071 cdl.AddRow("Status", ld.Status);
2072 cdl.AddRow("Flags", (ParcelFlags)ld.Flags);
2073
2074 cdl.AddRow("Landing Type", (LandingType)ld.LandingType);
2075 cdl.AddRow("User Location", ld.UserLocation);
2076 cdl.AddRow("User look at", ld.UserLookAt);
2077
2078 cdl.AddRow("Other clean time", ld.OtherCleanTime);
2079
2080 cdl.AddRow("Max Prims", lo.GetParcelMaxPrimCount());
2081 IPrimCounts pc = lo.PrimCounts;
2082 cdl.AddRow("Owner Prims", pc.Owner);
2083 cdl.AddRow("Group Prims", pc.Group);
2084 cdl.AddRow("Other Prims", pc.Others);
2085 cdl.AddRow("Selected Prims", pc.Selected);
2086 cdl.AddRow("Total Prims", pc.Total);
2087
2088 cdl.AddRow("Music URL", ld.MusicURL);
2089 cdl.AddRow("Obscure Music", ld.ObscureMusic);
2090
2091 cdl.AddRow("Media ID", ld.MediaID);
2092 cdl.AddRow("Media Autoscale", Convert.ToBoolean(ld.MediaAutoScale));
2093 cdl.AddRow("Media URL", ld.MediaURL);
2094 cdl.AddRow("Media Type", ld.MediaType);
2095 cdl.AddRow("Media Description", ld.MediaDescription);
2096 cdl.AddRow("Media Width", ld.MediaWidth);
2097 cdl.AddRow("Media Height", ld.MediaHeight);
2098 cdl.AddRow("Media Loop", ld.MediaLoop);
2099 cdl.AddRow("Obscure Media", ld.ObscureMedia);
2100
2101 cdl.AddRow("Parcel Category", ld.Category);
2102
2103 cdl.AddRow("Claim Date", ld.ClaimDate);
2104 cdl.AddRow("Claim Price", ld.ClaimPrice);
2105 cdl.AddRow("Pass Hours", ld.PassHours);
2106 cdl.AddRow("Pass Price", ld.PassPrice);
2107
2108 cdl.AddRow("Auction ID", ld.AuctionID);
2109 cdl.AddRow("Authorized Buyer ID", ld.AuthBuyerID);
2110 cdl.AddRow("Sale Price", ld.SalePrice);
2111
2112 cdl.AddToStringBuilder(report);
1982 } 2113 }
1983 } 2114 }
1984} 2115}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 2eafd44..74c2144 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -82,14 +82,14 @@ namespace OpenSim.Region.CoreModules.World.Land
82 82
83 set { m_landData = value; } 83 set { m_landData = value; }
84 } 84 }
85 85
86 public IPrimCounts PrimCounts { get; set; } 86 public IPrimCounts PrimCounts { get; set; }
87 87
88 public UUID RegionUUID 88 public UUID RegionUUID
89 { 89 {
90 get { return m_scene.RegionInfo.RegionID; } 90 get { return m_scene.RegionInfo.RegionID; }
91 } 91 }
92 92
93 public Vector3 StartPoint 93 public Vector3 StartPoint
94 { 94 {
95 get 95 get
@@ -102,11 +102,11 @@ namespace OpenSim.Region.CoreModules.World.Land
102 return new Vector3(x * 4, y * 4, 0); 102 return new Vector3(x * 4, y * 4, 0);
103 } 103 }
104 } 104 }
105 105
106 return new Vector3(-1, -1, -1); 106 return new Vector3(-1, -1, -1);
107 } 107 }
108 } 108 }
109 109
110 public Vector3 EndPoint 110 public Vector3 EndPoint
111 { 111 {
112 get 112 get
@@ -117,15 +117,15 @@ namespace OpenSim.Region.CoreModules.World.Land
117 { 117 {
118 if (LandBitmap[x, y]) 118 if (LandBitmap[x, y])
119 { 119 {
120 return new Vector3(x * 4, y * 4, 0); 120 return new Vector3(x * 4 + 4, y * 4 + 4, 0);
121 } 121 }
122 } 122 }
123 } 123 }
124 124
125 return new Vector3(-1, -1, -1); 125 return new Vector3(-1, -1, -1);
126 } 126 }
127 } 127 }
128 128
129 #region Constructors 129 #region Constructors
130 130
131 public LandObject(UUID owner_id, bool is_group_owned, Scene scene) 131 public LandObject(UUID owner_id, bool is_group_owned, Scene scene)
@@ -249,13 +249,6 @@ namespace OpenSim.Region.CoreModules.World.Land
249 if (estateModule != null) 249 if (estateModule != null)
250 regionFlags = estateModule.GetRegionFlags(); 250 regionFlags = estateModule.GetRegionFlags();
251 251
252 // In a perfect world, this would have worked.
253 //
254// if ((landData.Flags & (uint)ParcelFlags.AllowLandmark) != 0)
255// regionFlags |= (uint)RegionFlags.AllowLandmark;
256// if (landData.OwnerID == remote_client.AgentId)
257// regionFlags |= (uint)RegionFlags.AllowSetHome;
258
259 int seq_id; 252 int seq_id;
260 if (snap_selection && (sequence_id == 0)) 253 if (snap_selection && (sequence_id == 0))
261 { 254 {
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
index 40638f8..bc52a43 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
55 public struct DrawStruct 55 public struct DrawStruct
56 { 56 {
57 public DrawRoutine dr; 57 public DrawRoutine dr;
58 public Rectangle rect; 58// public Rectangle rect;
59 public SolidBrush brush; 59 public SolidBrush brush;
60 public face[] trns; 60 public face[] trns;
61 } 61 }
@@ -119,6 +119,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
119 { 119 {
120 mapbmp = FetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID); 120 mapbmp = FetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID);
121 } 121 }
122
122 return mapbmp; 123 return mapbmp;
123 } 124 }
124 125
@@ -127,7 +128,10 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
127 try 128 try
128 { 129 {
129 using (Bitmap mapbmp = CreateMapTile()) 130 using (Bitmap mapbmp = CreateMapTile())
130 return OpenJPEG.EncodeFromImage(mapbmp, true); 131 {
132 if (mapbmp != null)
133 return OpenJPEG.EncodeFromImage(mapbmp, true);
134 }
131 } 135 }
132 catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke 136 catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke
133 { 137 {
@@ -277,321 +281,331 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
277 tc = Environment.TickCount; 281 tc = Environment.TickCount;
278 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile"); 282 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Object Volume Profile");
279 EntityBase[] objs = whichScene.GetEntities(); 283 EntityBase[] objs = whichScene.GetEntities();
280 Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>();
281 //SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>();
282 List<float> z_sortheights = new List<float>(); 284 List<float> z_sortheights = new List<float>();
283 List<uint> z_localIDs = new List<uint>(); 285 List<uint> z_localIDs = new List<uint>();
286 Dictionary<uint, DrawStruct> z_sort = new Dictionary<uint, DrawStruct>();
284 287
285 lock (objs) 288 try
286 { 289 {
287 foreach (EntityBase obj in objs) 290 //SortedList<float, RectangleDrawStruct> z_sort = new SortedList<float, RectangleDrawStruct>();
291
292 lock (objs)
288 { 293 {
289 // Only draw the contents of SceneObjectGroup 294 foreach (EntityBase obj in objs)
290 if (obj is SceneObjectGroup)
291 { 295 {
292 SceneObjectGroup mapdot = (SceneObjectGroup)obj; 296 // Only draw the contents of SceneObjectGroup
293 Color mapdotspot = Color.Gray; // Default color when prim color is white 297 if (obj is SceneObjectGroup)
294
295 // Loop over prim in group
296 foreach (SceneObjectPart part in mapdot.Parts)
297 { 298 {
298 if (part == null) 299 SceneObjectGroup mapdot = (SceneObjectGroup)obj;
299 continue; 300 Color mapdotspot = Color.Gray; // Default color when prim color is white
300 301
301 // Draw if the object is at least 1 meter wide in any direction 302 // Loop over prim in group
302 if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f) 303 foreach (SceneObjectPart part in mapdot.Parts)
303 { 304 {
304 // Try to get the RGBA of the default texture entry.. 305 if (part == null)
305 // 306 continue;
306 try 307
308 // Draw if the object is at least 1 meter wide in any direction
309 if (part.Scale.X > 1f || part.Scale.Y > 1f || part.Scale.Z > 1f)
307 { 310 {
308 // get the null checks out of the way 311 // Try to get the RGBA of the default texture entry..
309 // skip the ones that break 312 //
310 if (part == null) 313 try
311 continue; 314 {
315 // get the null checks out of the way
316 // skip the ones that break
317 if (part == null)
318 continue;
312 319
313 if (part.Shape == null) 320 if (part.Shape == null)
314 continue; 321 continue;
315 322
316 if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass) 323 if (part.Shape.PCode == (byte)PCode.Tree || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Grass)
317 continue; // eliminates trees from this since we don't really have a good tree representation 324 continue; // eliminates trees from this since we don't really have a good tree representation
318 // if you want tree blocks on the map comment the above line and uncomment the below line 325 // if you want tree blocks on the map comment the above line and uncomment the below line
319 //mapdotspot = Color.PaleGreen; 326 //mapdotspot = Color.PaleGreen;
320 327
321 Primitive.TextureEntry textureEntry = part.Shape.Textures; 328 Primitive.TextureEntry textureEntry = part.Shape.Textures;
322 329
323 if (textureEntry == null || textureEntry.DefaultTexture == null) 330 if (textureEntry == null || textureEntry.DefaultTexture == null)
324 continue; 331 continue;
325 332
326 Color4 texcolor = textureEntry.DefaultTexture.RGBA; 333 Color4 texcolor = textureEntry.DefaultTexture.RGBA;
327 334
328 // Not sure why some of these are null, oh well. 335 // Not sure why some of these are null, oh well.
329 336
330 int colorr = 255 - (int)(texcolor.R * 255f); 337 int colorr = 255 - (int)(texcolor.R * 255f);
331 int colorg = 255 - (int)(texcolor.G * 255f); 338 int colorg = 255 - (int)(texcolor.G * 255f);
332 int colorb = 255 - (int)(texcolor.B * 255f); 339 int colorb = 255 - (int)(texcolor.B * 255f);
333 340
334 if (!(colorr == 255 && colorg == 255 && colorb == 255)) 341 if (!(colorr == 255 && colorg == 255 && colorb == 255))
335 {
336 //Try to set the map spot color
337 try
338 {
339 // If the color gets goofy somehow, skip it *shakes fist at Color4
340 mapdotspot = Color.FromArgb(colorr, colorg, colorb);
341 }
342 catch (ArgumentException)
343 { 342 {
343 //Try to set the map spot color
344 try
345 {
346 // If the color gets goofy somehow, skip it *shakes fist at Color4
347 mapdotspot = Color.FromArgb(colorr, colorg, colorb);
348 }
349 catch (ArgumentException)
350 {
351 }
344 } 352 }
345 } 353 }
346 } 354 catch (IndexOutOfRangeException)
347 catch (IndexOutOfRangeException) 355 {
348 { 356 // Windows Array
349 // Windows Array 357 }
350 } 358 catch (ArgumentOutOfRangeException)
351 catch (ArgumentOutOfRangeException) 359 {
352 { 360 // Mono Array
353 // Mono Array 361 }
354 }
355
356 Vector3 pos = part.GetWorldPosition();
357
358 // skip prim outside of retion
359 if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
360 continue;
361
362 // skip prim in non-finite position
363 if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) ||
364 Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y))
365 continue;
366
367 // Figure out if object is under 256m above the height of the terrain
368 bool isBelow256AboveTerrain = false;
369 362
370 try 363 Vector3 pos = part.GetWorldPosition();
371 {
372 isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f));
373 }
374 catch (Exception)
375 {
376 }
377 364
378 if (isBelow256AboveTerrain) 365 // skip prim outside of retion
379 { 366 if (pos.X < 0f || pos.X > 256f || pos.Y < 0f || pos.Y > 256f)
380 // Translate scale by rotation so scale is represented properly when object is rotated
381 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
382 Vector3 scale = new Vector3();
383 Vector3 tScale = new Vector3();
384 Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
385
386 Quaternion llrot = part.GetWorldRotation();
387 Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
388 scale = lscale * rot;
389
390 // negative scales don't work in this situation
391 scale.X = Math.Abs(scale.X);
392 scale.Y = Math.Abs(scale.Y);
393 scale.Z = Math.Abs(scale.Z);
394
395 // This scaling isn't very accurate and doesn't take into account the face rotation :P
396 int mapdrawstartX = (int)(pos.X - scale.X);
397 int mapdrawstartY = (int)(pos.Y - scale.Y);
398 int mapdrawendX = (int)(pos.X + scale.X);
399 int mapdrawendY = (int)(pos.Y + scale.Y);
400
401 // If object is beyond the edge of the map, don't draw it to avoid errors
402 if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1)
403 || mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0
404 || mapdrawendY > ((int)Constants.RegionSize - 1))
405 continue; 367 continue;
406 368
407#region obb face reconstruction part duex 369 // skip prim in non-finite position
408 Vector3[] vertexes = new Vector3[8]; 370 if (Single.IsNaN(pos.X) || Single.IsNaN(pos.Y) ||
409 371 Single.IsInfinity(pos.X) || Single.IsInfinity(pos.Y))
410 // float[] distance = new float[6]; 372 continue;
411 Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
412 Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
413 Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
414 Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
415
416 tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z);
417 scale = ((tScale * rot));
418 vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
419 // vertexes[0].x = pos.X + vertexes[0].x;
420 //vertexes[0].y = pos.Y + vertexes[0].y;
421 //vertexes[0].z = pos.Z + vertexes[0].z;
422
423 FaceA[0] = vertexes[0];
424 FaceB[3] = vertexes[0];
425 FaceA[4] = vertexes[0];
426
427 tScale = lscale;
428 scale = ((tScale * rot));
429 vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
430
431 // vertexes[1].x = pos.X + vertexes[1].x;
432 // vertexes[1].y = pos.Y + vertexes[1].y;
433 //vertexes[1].z = pos.Z + vertexes[1].z;
434
435 FaceB[0] = vertexes[1];
436 FaceA[1] = vertexes[1];
437 FaceC[4] = vertexes[1];
438
439 tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
440 scale = ((tScale * rot));
441
442 vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
443
444 //vertexes[2].x = pos.X + vertexes[2].x;
445 //vertexes[2].y = pos.Y + vertexes[2].y;
446 //vertexes[2].z = pos.Z + vertexes[2].z;
447
448 FaceC[0] = vertexes[2];
449 FaceD[3] = vertexes[2];
450 FaceC[5] = vertexes[2];
451
452 tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z);
453 scale = ((tScale * rot));
454 vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
455
456 //vertexes[3].x = pos.X + vertexes[3].x;
457 // vertexes[3].y = pos.Y + vertexes[3].y;
458 // vertexes[3].z = pos.Z + vertexes[3].z;
459
460 FaceD[0] = vertexes[3];
461 FaceC[1] = vertexes[3];
462 FaceA[5] = vertexes[3];
463
464 tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z);
465 scale = ((tScale * rot));
466 vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
467
468 // vertexes[4].x = pos.X + vertexes[4].x;
469 // vertexes[4].y = pos.Y + vertexes[4].y;
470 // vertexes[4].z = pos.Z + vertexes[4].z;
471
472 FaceB[1] = vertexes[4];
473 FaceA[2] = vertexes[4];
474 FaceD[4] = vertexes[4];
475
476 tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z);
477 scale = ((tScale * rot));
478 vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
479
480 // vertexes[5].x = pos.X + vertexes[5].x;
481 // vertexes[5].y = pos.Y + vertexes[5].y;
482 // vertexes[5].z = pos.Z + vertexes[5].z;
483
484 FaceD[1] = vertexes[5];
485 FaceC[2] = vertexes[5];
486 FaceB[5] = vertexes[5];
487 373
488 tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z); 374 // Figure out if object is under 256m above the height of the terrain
489 scale = ((tScale * rot)); 375 bool isBelow256AboveTerrain = false;
490 vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
491 376
492 // vertexes[6].x = pos.X + vertexes[6].x; 377 try
493 // vertexes[6].y = pos.Y + vertexes[6].y; 378 {
494 // vertexes[6].z = pos.Z + vertexes[6].z; 379 isBelow256AboveTerrain = (pos.Z < ((float)hm[(int)pos.X, (int)pos.Y] + 256f));
380 }
381 catch (Exception)
382 {
383 }
495 384
496 FaceB[2] = vertexes[6]; 385 if (isBelow256AboveTerrain)
497 FaceA[3] = vertexes[6]; 386 {
498 FaceB[4] = vertexes[6]; 387 // Translate scale by rotation so scale is represented properly when object is rotated
388 Vector3 lscale = new Vector3(part.Shape.Scale.X, part.Shape.Scale.Y, part.Shape.Scale.Z);
389 Vector3 scale = new Vector3();
390 Vector3 tScale = new Vector3();
391 Vector3 axPos = new Vector3(pos.X,pos.Y,pos.Z);
392
393 Quaternion llrot = part.GetWorldRotation();
394 Quaternion rot = new Quaternion(llrot.W, llrot.X, llrot.Y, llrot.Z);
395 scale = lscale * rot;
396
397 // negative scales don't work in this situation
398 scale.X = Math.Abs(scale.X);
399 scale.Y = Math.Abs(scale.Y);
400 scale.Z = Math.Abs(scale.Z);
401
402 // This scaling isn't very accurate and doesn't take into account the face rotation :P
403 int mapdrawstartX = (int)(pos.X - scale.X);
404 int mapdrawstartY = (int)(pos.Y - scale.Y);
405 int mapdrawendX = (int)(pos.X + scale.X);
406 int mapdrawendY = (int)(pos.Y + scale.Y);
407
408 // If object is beyond the edge of the map, don't draw it to avoid errors
409 if (mapdrawstartX < 0 || mapdrawstartX > ((int)Constants.RegionSize - 1) || mapdrawendX < 0 || mapdrawendX > ((int)Constants.RegionSize - 1)
410 || mapdrawstartY < 0 || mapdrawstartY > ((int)Constants.RegionSize - 1) || mapdrawendY < 0
411 || mapdrawendY > ((int)Constants.RegionSize - 1))
412 continue;
413
414 #region obb face reconstruction part duex
415 Vector3[] vertexes = new Vector3[8];
416
417 // float[] distance = new float[6];
418 Vector3[] FaceA = new Vector3[6]; // vertex A for Facei
419 Vector3[] FaceB = new Vector3[6]; // vertex B for Facei
420 Vector3[] FaceC = new Vector3[6]; // vertex C for Facei
421 Vector3[] FaceD = new Vector3[6]; // vertex D for Facei
422
423 tScale = new Vector3(lscale.X, -lscale.Y, lscale.Z);
424 scale = ((tScale * rot));
425 vertexes[0] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
426 // vertexes[0].x = pos.X + vertexes[0].x;
427 //vertexes[0].y = pos.Y + vertexes[0].y;
428 //vertexes[0].z = pos.Z + vertexes[0].z;
429
430 FaceA[0] = vertexes[0];
431 FaceB[3] = vertexes[0];
432 FaceA[4] = vertexes[0];
433
434 tScale = lscale;
435 scale = ((tScale * rot));
436 vertexes[1] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
437
438 // vertexes[1].x = pos.X + vertexes[1].x;
439 // vertexes[1].y = pos.Y + vertexes[1].y;
440 //vertexes[1].z = pos.Z + vertexes[1].z;
441
442 FaceB[0] = vertexes[1];
443 FaceA[1] = vertexes[1];
444 FaceC[4] = vertexes[1];
445
446 tScale = new Vector3(lscale.X, -lscale.Y, -lscale.Z);
447 scale = ((tScale * rot));
448
449 vertexes[2] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
450
451 //vertexes[2].x = pos.X + vertexes[2].x;
452 //vertexes[2].y = pos.Y + vertexes[2].y;
453 //vertexes[2].z = pos.Z + vertexes[2].z;
454
455 FaceC[0] = vertexes[2];
456 FaceD[3] = vertexes[2];
457 FaceC[5] = vertexes[2];
458
459 tScale = new Vector3(lscale.X, lscale.Y, -lscale.Z);
460 scale = ((tScale * rot));
461 vertexes[3] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
462
463 //vertexes[3].x = pos.X + vertexes[3].x;
464 // vertexes[3].y = pos.Y + vertexes[3].y;
465 // vertexes[3].z = pos.Z + vertexes[3].z;
466
467 FaceD[0] = vertexes[3];
468 FaceC[1] = vertexes[3];
469 FaceA[5] = vertexes[3];
470
471 tScale = new Vector3(-lscale.X, lscale.Y, lscale.Z);
472 scale = ((tScale * rot));
473 vertexes[4] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
474
475 // vertexes[4].x = pos.X + vertexes[4].x;
476 // vertexes[4].y = pos.Y + vertexes[4].y;
477 // vertexes[4].z = pos.Z + vertexes[4].z;
478
479 FaceB[1] = vertexes[4];
480 FaceA[2] = vertexes[4];
481 FaceD[4] = vertexes[4];
482
483 tScale = new Vector3(-lscale.X, lscale.Y, -lscale.Z);
484 scale = ((tScale * rot));
485 vertexes[5] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
486
487 // vertexes[5].x = pos.X + vertexes[5].x;
488 // vertexes[5].y = pos.Y + vertexes[5].y;
489 // vertexes[5].z = pos.Z + vertexes[5].z;
490
491 FaceD[1] = vertexes[5];
492 FaceC[2] = vertexes[5];
493 FaceB[5] = vertexes[5];
494
495 tScale = new Vector3(-lscale.X, -lscale.Y, lscale.Z);
496 scale = ((tScale * rot));
497 vertexes[6] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
498
499 // vertexes[6].x = pos.X + vertexes[6].x;
500 // vertexes[6].y = pos.Y + vertexes[6].y;
501 // vertexes[6].z = pos.Z + vertexes[6].z;
502
503 FaceB[2] = vertexes[6];
504 FaceA[3] = vertexes[6];
505 FaceB[4] = vertexes[6];
499 506
500 tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z); 507 tScale = new Vector3(-lscale.X, -lscale.Y, -lscale.Z);
501 scale = ((tScale * rot)); 508 scale = ((tScale * rot));
502 vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z))); 509 vertexes[7] = (new Vector3((pos.X + scale.X), (pos.Y + scale.Y), (pos.Z + scale.Z)));
503 510
504 // vertexes[7].x = pos.X + vertexes[7].x; 511 // vertexes[7].x = pos.X + vertexes[7].x;
505 // vertexes[7].y = pos.Y + vertexes[7].y; 512 // vertexes[7].y = pos.Y + vertexes[7].y;
506 // vertexes[7].z = pos.Z + vertexes[7].z; 513 // vertexes[7].z = pos.Z + vertexes[7].z;
507 514
508 FaceD[2] = vertexes[7]; 515 FaceD[2] = vertexes[7];
509 FaceC[3] = vertexes[7]; 516 FaceC[3] = vertexes[7];
510 FaceD[5] = vertexes[7]; 517 FaceD[5] = vertexes[7];
511#endregion 518 #endregion
512 519
513 //int wy = 0; 520 //int wy = 0;
514 521
515 //bool breakYN = false; // If we run into an error drawing, break out of the 522 //bool breakYN = false; // If we run into an error drawing, break out of the
516 // loop so we don't lag to death on error handling 523 // loop so we don't lag to death on error handling
517 DrawStruct ds = new DrawStruct(); 524 DrawStruct ds = new DrawStruct();
518 ds.brush = new SolidBrush(mapdotspot); 525 ds.brush = new SolidBrush(mapdotspot);
519 //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY); 526 //ds.rect = new Rectangle(mapdrawstartX, (255 - mapdrawstartY), mapdrawendX - mapdrawstartX, mapdrawendY - mapdrawstartY);
520 527
521 ds.trns = new face[FaceA.Length]; 528 ds.trns = new face[FaceA.Length];
522 529
523 for (int i = 0; i < FaceA.Length; i++) 530 for (int i = 0; i < FaceA.Length; i++)
524 { 531 {
525 Point[] working = new Point[5]; 532 Point[] working = new Point[5];
526 working[0] = project(FaceA[i], axPos); 533 working[0] = project(FaceA[i], axPos);
527 working[1] = project(FaceB[i], axPos); 534 working[1] = project(FaceB[i], axPos);
528 working[2] = project(FaceD[i], axPos); 535 working[2] = project(FaceD[i], axPos);
529 working[3] = project(FaceC[i], axPos); 536 working[3] = project(FaceC[i], axPos);
530 working[4] = project(FaceA[i], axPos); 537 working[4] = project(FaceA[i], axPos);
531 538
532 face workingface = new face(); 539 face workingface = new face();
533 workingface.pts = working; 540 workingface.pts = working;
534 541
535 ds.trns[i] = workingface; 542 ds.trns[i] = workingface;
536 } 543 }
537 544
538 z_sort.Add(part.LocalId, ds); 545 z_sort.Add(part.LocalId, ds);
539 z_localIDs.Add(part.LocalId); 546 z_localIDs.Add(part.LocalId);
540 z_sortheights.Add(pos.Z); 547 z_sortheights.Add(pos.Z);
541 548
542 //for (int wx = mapdrawstartX; wx < mapdrawendX; wx++) 549 //for (int wx = mapdrawstartX; wx < mapdrawendX; wx++)
543 //{
544 //for (wy = mapdrawstartY; wy < mapdrawendY; wy++)
545 //{ 550 //{
546 //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy); 551 //for (wy = mapdrawstartY; wy < mapdrawendY; wy++)
547 //try
548 //{
549 // Remember, flip the y!
550 // mapbmp.SetPixel(wx, (255 - wy), mapdotspot);
551 //}
552 //catch (ArgumentException)
553 //{ 552 //{
554 // breakYN = true; 553 //m_log.InfoFormat("[MAPDEBUG]: {0},{1}({2})", wx, (255 - wy),wy);
554 //try
555 //{
556 // Remember, flip the y!
557 // mapbmp.SetPixel(wx, (255 - wy), mapdotspot);
558 //}
559 //catch (ArgumentException)
560 //{
561 // breakYN = true;
562 //}
563
564 //if (breakYN)
565 // break;
555 //} 566 //}
556 567
557 //if (breakYN) 568 //if (breakYN)
558 // break; 569 // break;
559 //} 570 //}
571 } // Object is within 256m Z of terrain
572 } // object is at least a meter wide
573 } // loop over group children
574 } // entitybase is sceneobject group
575 } // foreach loop over entities
560 576
561 //if (breakYN) 577 float[] sortedZHeights = z_sortheights.ToArray();
562 // break; 578 uint[] sortedlocalIds = z_localIDs.ToArray();
563 //}
564 } // Object is within 256m Z of terrain
565 } // object is at least a meter wide
566 } // loop over group children
567 } // entitybase is sceneobject group
568 } // foreach loop over entities
569
570 float[] sortedZHeights = z_sortheights.ToArray();
571 uint[] sortedlocalIds = z_localIDs.ToArray();
572
573 // Sort prim by Z position
574 Array.Sort(sortedZHeights, sortedlocalIds);
575 579
576 Graphics g = Graphics.FromImage(mapbmp); 580 // Sort prim by Z position
581 Array.Sort(sortedZHeights, sortedlocalIds);
577 582
578 for (int s = 0; s < sortedZHeights.Length; s++) 583 using (Graphics g = Graphics.FromImage(mapbmp))
579 {
580 if (z_sort.ContainsKey(sortedlocalIds[s]))
581 { 584 {
582 DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]]; 585 for (int s = 0; s < sortedZHeights.Length; s++)
583 for (int r = 0; r < rectDrawStruct.trns.Length; r++)
584 { 586 {
585 g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts); 587 if (z_sort.ContainsKey(sortedlocalIds[s]))
588 {
589 DrawStruct rectDrawStruct = z_sort[sortedlocalIds[s]];
590 for (int r = 0; r < rectDrawStruct.trns.Length; r++)
591 {
592 g.FillPolygon(rectDrawStruct.brush,rectDrawStruct.trns[r].pts);
593 }
594 //g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect);
595 }
586 } 596 }
587 //g.FillRectangle(rectDrawStruct.brush , rectDrawStruct.rect);
588 } 597 }
589 } 598 } // lock entities objs
590 599
591 g.Dispose(); 600 }
592 } // lock entities objs 601 finally
602 {
603 foreach (DrawStruct ds in z_sort.Values)
604 ds.brush.Dispose();
605 }
593 606
594 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Done in " + (Environment.TickCount - tc) + " ms"); 607 m_log.Debug("[MAPTILE]: Generating Maptile Step 2: Done in " + (Environment.TickCount - tc) + " ms");
608
595 return mapbmp; 609 return mapbmp;
596 } 610 }
597 611
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
index 992bff3..cb06fd4 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/ShadedMapTileRenderer.cs
@@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
54 public void TerrainToBitmap(Bitmap mapbmp) 54 public void TerrainToBitmap(Bitmap mapbmp)
55 { 55 {
56 int tc = Environment.TickCount; 56 int tc = Environment.TickCount;
57 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain"); 57 m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain");
58 58
59 double[,] hm = m_scene.Heightmap.GetDoubles(); 59 double[,] hm = m_scene.Heightmap.GetDoubles();
60 bool ShadowDebugContinue = true; 60 bool ShadowDebugContinue = true;
@@ -199,7 +199,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
199 { 199 {
200 if (!terraincorruptedwarningsaid) 200 if (!terraincorruptedwarningsaid)
201 { 201 {
202 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); 202 m_log.WarnFormat("[SHADED MAP TILE RENDERER]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName);
203 terraincorruptedwarningsaid = true; 203 terraincorruptedwarningsaid = true;
204 } 204 }
205 color = Color.Black; 205 color = Color.Black;
@@ -229,7 +229,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
229 { 229 {
230 if (!terraincorruptedwarningsaid) 230 if (!terraincorruptedwarningsaid)
231 { 231 {
232 m_log.WarnFormat("[MAPIMAGE]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName); 232 m_log.WarnFormat("[SHADED MAP TILE RENDERER]: Your terrain is corrupted in region {0}, it might take a few minutes to generate the map image depending on the corruption level", m_scene.RegionInfo.RegionName);
233 terraincorruptedwarningsaid = true; 233 terraincorruptedwarningsaid = true;
234 } 234 }
235 Color black = Color.Black; 235 Color black = Color.Black;
@@ -238,7 +238,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
238 } 238 }
239 } 239 }
240 } 240 }
241 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); 241
242 m_log.Debug("[SHADED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
242 } 243 }
243 } 244 }
244} 245} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
index d13c2ef..e895178 100644
--- a/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
+++ b/OpenSim/Region/CoreModules/World/LegacyMap/TexturedMapTileRenderer.cs
@@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
173 private Bitmap fetchTexture(UUID id) 173 private Bitmap fetchTexture(UUID id)
174 { 174 {
175 AssetBase asset = m_scene.AssetService.Get(id.ToString()); 175 AssetBase asset = m_scene.AssetService.Get(id.ToString());
176 m_log.DebugFormat("[TexturedMapTileRenderer]: Fetched texture {0}, found: {1}", id, asset != null); 176 m_log.DebugFormat("[TEXTURED MAP TILE RENDERER]: Fetched texture {0}, found: {1}", id, asset != null);
177 if (asset == null) return null; 177 if (asset == null) return null;
178 178
179 ManagedImage managedImage; 179 ManagedImage managedImage;
@@ -188,17 +188,17 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
188 } 188 }
189 catch (DllNotFoundException) 189 catch (DllNotFoundException)
190 { 190 {
191 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id); 191 m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg is not installed correctly on this system. Asset Data is empty for {0}", id);
192 192
193 } 193 }
194 catch (IndexOutOfRangeException) 194 catch (IndexOutOfRangeException)
195 { 195 {
196 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id); 196 m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id);
197 197
198 } 198 }
199 catch (Exception) 199 catch (Exception)
200 { 200 {
201 m_log.ErrorFormat("[TexturedMapTileRenderer]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id); 201 m_log.ErrorFormat("[TEXTURED MAP TILE RENDERER]: OpenJpeg was unable to encode this. Asset Data is empty for {0}", id);
202 202
203 } 203 }
204 return null; 204 return null;
@@ -233,10 +233,14 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
233 if (textureID == UUID.Zero) return defaultColor; // not set 233 if (textureID == UUID.Zero) return defaultColor; // not set
234 if (m_mapping.ContainsKey(textureID)) return m_mapping[textureID]; // one of the predefined textures 234 if (m_mapping.ContainsKey(textureID)) return m_mapping[textureID]; // one of the predefined textures
235 235
236 Bitmap bmp = fetchTexture(textureID); 236 Color color;
237 Color color = bmp == null ? defaultColor : computeAverageColor(bmp); 237
238 // store it for future reference 238 using (Bitmap bmp = fetchTexture(textureID))
239 m_mapping[textureID] = color; 239 {
240 color = bmp == null ? defaultColor : computeAverageColor(bmp);
241 // store it for future reference
242 m_mapping[textureID] = color;
243 }
240 244
241 return color; 245 return color;
242 } 246 }
@@ -278,7 +282,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
278 public void TerrainToBitmap(Bitmap mapbmp) 282 public void TerrainToBitmap(Bitmap mapbmp)
279 { 283 {
280 int tc = Environment.TickCount; 284 int tc = Environment.TickCount;
281 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Terrain"); 285 m_log.Debug("[TEXTURED MAP TILE RENDERER]: Generating Maptile Step 1: Terrain");
282 286
283 // These textures should be in the AssetCache anyway, as every client conneting to this 287 // These textures should be in the AssetCache anyway, as every client conneting to this
284 // region needs them. Except on start, when the map is recreated (before anyone connected), 288 // region needs them. Except on start, when the map is recreated (before anyone connected),
@@ -412,7 +416,8 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap
412 } 416 }
413 } 417 }
414 } 418 }
415 m_log.Debug("[MAPTILE]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms"); 419
420 m_log.Debug("[TEXTURED MAP TILE RENDERER]: Generating Maptile Step 1: Done in " + (Environment.TickCount - tc) + " ms");
416 } 421 }
417 } 422 }
418} 423} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
index 28daf2f..d4e4c25 100644
--- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs
@@ -205,13 +205,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell
205 item.InvType = (int)InventoryType.Object; 205 item.InvType = (int)InventoryType.Object;
206 item.Folder = categoryID; 206 item.Folder = categoryID;
207 207
208 uint nextPerms=(perms & 7) << 13; 208 PermissionsUtil.ApplyFoldedPermissions(perms, ref perms);
209 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
210 perms &= ~(uint)PermissionMask.Copy;
211 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
212 perms &= ~(uint)PermissionMask.Transfer;
213 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
214 perms &= ~(uint)PermissionMask.Modify;
215 209
216 item.BasePermissions = perms & part.NextOwnerMask; 210 item.BasePermissions = perms & part.NextOwnerMask;
217 item.CurrentPermissions = perms & part.NextOwnerMask; 211 item.CurrentPermissions = perms & part.NextOwnerMask;
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index e434b2e..e77f0aa 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -546,7 +546,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
546 { 546 {
547 ConsoleDisplayList cdl = new ConsoleDisplayList(); 547 ConsoleDisplayList cdl = new ConsoleDisplayList();
548 cdl.AddRow("Name", so.Name); 548 cdl.AddRow("Name", so.Name);
549 cdl.AddRow("Descrition", so.Description); 549 cdl.AddRow("Description", so.Description);
550 cdl.AddRow("Local ID", so.LocalId); 550 cdl.AddRow("Local ID", so.LocalId);
551 cdl.AddRow("UUID", so.UUID); 551 cdl.AddRow("UUID", so.UUID);
552 cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name)); 552 cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name));
@@ -631,7 +631,22 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
631 cdl.AddRow("SculptType", s.SculptType); 631 cdl.AddRow("SculptType", s.SculptType);
632 cdl.AddRow("State", s.State); 632 cdl.AddRow("State", s.State);
633 633
634 // TODO, unpack and display texture entries 634 // TODO, need to display more information about textures but in a compact format
635 // to stop output becoming huge.
636 for (int i = 0; i < sop.GetNumberOfSides(); i++)
637 {
638 Primitive.TextureEntryFace teFace = s.Textures.FaceTextures[i];
639
640 UUID textureID;
641
642 if (teFace != null)
643 textureID = teFace.TextureID;
644 else
645 textureID = s.Textures.DefaultTexture.TextureID;
646
647 cdl.AddRow(string.Format("Face {0} texture ID", i), textureID);
648 }
649
635 //cdl.AddRow("Textures", string.Format("{0} entries", s.Textures. 650 //cdl.AddRow("Textures", string.Format("{0} entries", s.Textures.
636 } 651 }
637 652
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 4f5b9b7..616fe98 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -1453,6 +1453,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1453 1453
1454 bool permission = false; 1454 bool permission = false;
1455 1455
1456// m_log.DebugFormat("[PERMISSIONS MODULE]: Checking rez object at {0} in {1}", objectPosition, m_scene.Name);
1457
1456 ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); 1458 ILandObject land = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y);
1457 if (land == null) return false; 1459 if (land == null) return false;
1458 1460
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index 9c441ed..0c74b49 100644
--- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
@@ -48,8 +48,8 @@ namespace OpenSim.Region.CoreModules.World.Region
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RestartModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RestartModule")]
49 public class RestartModule : INonSharedRegionModule, IRestartModule 49 public class RestartModule : INonSharedRegionModule, IRestartModule
50 { 50 {
51// private static readonly ILog m_log = 51 private static readonly ILog m_log =
52// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 53
54 protected Scene m_Scene; 54 protected Scene m_Scene;
55 protected Timer m_CountdownTimer = null; 55 protected Timer m_CountdownTimer = null;
@@ -223,11 +223,25 @@ namespace OpenSim.Region.CoreModules.World.Region
223 223
224 public void SetTimer(int intervalSeconds) 224 public void SetTimer(int intervalSeconds)
225 { 225 {
226 m_CountdownTimer = new Timer(); 226 if (intervalSeconds > 0)
227 m_CountdownTimer.AutoReset = false; 227 {
228 m_CountdownTimer.Interval = intervalSeconds * 1000; 228 m_CountdownTimer = new Timer();
229 m_CountdownTimer.Elapsed += OnTimer; 229 m_CountdownTimer.AutoReset = false;
230 m_CountdownTimer.Start(); 230 m_CountdownTimer.Interval = intervalSeconds * 1000;
231 m_CountdownTimer.Elapsed += OnTimer;
232 m_CountdownTimer.Start();
233 }
234 else if (m_CountdownTimer != null)
235 {
236 m_CountdownTimer.Stop();
237 m_CountdownTimer = null;
238 }
239 else
240 {
241 m_log.WarnFormat(
242 "[RESTART MODULE]: Tried to set restart timer to {0} in {1}, which is not a valid interval",
243 intervalSeconds, m_Scene.Name);
244 }
231 } 245 }
232 246
233 private void OnTimer(object source, ElapsedEventArgs e) 247 private void OnTimer(object source, ElapsedEventArgs e)
@@ -332,4 +346,4 @@ namespace OpenSim.Region.CoreModules.World.Region
332 } 346 }
333 } 347 }
334 } 348 }
335} \ No newline at end of file 349}
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
index b4348c9..66059fb 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
@@ -144,7 +144,20 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
144 <Flags>None</Flags> 144 <Flags>None</Flags>
145 <CollisionSound><Guid>00000000-0000-0000-0000-000000000000</Guid></CollisionSound> 145 <CollisionSound><Guid>00000000-0000-0000-0000-000000000000</Guid></CollisionSound>
146 <CollisionSoundVolume>0</CollisionSoundVolume> 146 <CollisionSoundVolume>0</CollisionSoundVolume>
147 <DynAttrs><llsd><map><key>MyStore</key><map><key>the answer</key><integer>42</integer></map></map></llsd></DynAttrs> 147 <DynAttrs>
148 <llsd>
149 <map>
150 <key>MyNamespace</key>
151 <map>
152 <key>MyStore</key>
153 <map>
154 <key>the answer</key>
155 <integer>42</integer>
156 </map>
157 </map>
158 </map>
159 </llsd>
160 </DynAttrs>
148 </SceneObjectPart> 161 </SceneObjectPart>
149 </RootPart> 162 </RootPart>
150 <OtherParts /> 163 <OtherParts />
@@ -333,7 +346,20 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
333 <EveryoneMask>0</EveryoneMask> 346 <EveryoneMask>0</EveryoneMask>
334 <NextOwnerMask>2147483647</NextOwnerMask> 347 <NextOwnerMask>2147483647</NextOwnerMask>
335 <Flags>None</Flags> 348 <Flags>None</Flags>
336 <DynAttrs><llsd><map><key>MyStore</key><map><key>last words</key><string>Rosebud</string></map></map></llsd></DynAttrs> 349 <DynAttrs>
350 <llsd>
351 <map>
352 <key>MyNamespace</key>
353 <map>
354 <key>MyStore</key>
355 <map>
356 <key>last words</key>
357 <string>Rosebud</string>
358 </map>
359 </map>
360 </map>
361 </llsd>
362 </DynAttrs>
337 <SitTargetAvatar><UUID>00000000-0000-0000-0000-000000000000</UUID></SitTargetAvatar> 363 <SitTargetAvatar><UUID>00000000-0000-0000-0000-000000000000</UUID></SitTargetAvatar>
338 </SceneObjectPart> 364 </SceneObjectPart>
339 <OtherParts /> 365 <OtherParts />
@@ -362,7 +388,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
362 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790"))); 388 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("e6a5a05e-e8cc-4816-8701-04165e335790")));
363 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d"))); 389 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("a6dacf01-4636-4bb9-8a97-30609438af9d")));
364 Assert.That(rootPart.Name, Is.EqualTo("PrimMyRide")); 390 Assert.That(rootPart.Name, Is.EqualTo("PrimMyRide"));
365 OSDMap store = rootPart.DynAttrs["MyStore"]; 391 OSDMap store = rootPart.DynAttrs.GetStore("MyNamespace", "MyStore");
366 Assert.AreEqual(42, store["the answer"].AsInteger()); 392 Assert.AreEqual(42, store["the answer"].AsInteger());
367 393
368 // TODO: Check other properties 394 // TODO: Check other properties
@@ -414,13 +440,14 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
414 rp.CreatorID = rpCreatorId; 440 rp.CreatorID = rpCreatorId;
415 rp.Shape = shape; 441 rp.Shape = shape;
416 442
443 string daNamespace = "MyNamespace";
417 string daStoreName = "MyStore"; 444 string daStoreName = "MyStore";
418 string daKey = "foo"; 445 string daKey = "foo";
419 string daValue = "bar"; 446 string daValue = "bar";
420 OSDMap myStore = new OSDMap(); 447 OSDMap myStore = new OSDMap();
421 myStore.Add(daKey, daValue); 448 myStore.Add(daKey, daValue);
422 rp.DynAttrs = new DAMap(); 449 rp.DynAttrs = new DAMap();
423 rp.DynAttrs[daStoreName] = myStore; 450 rp.DynAttrs.SetStore(daNamespace, daStoreName, myStore);
424 451
425 SceneObjectGroup so = new SceneObjectGroup(rp); 452 SceneObjectGroup so = new SceneObjectGroup(rp);
426 453
@@ -481,7 +508,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
481 Assert.That(name, Is.EqualTo(rpName)); 508 Assert.That(name, Is.EqualTo(rpName));
482 Assert.That(creatorId, Is.EqualTo(rpCreatorId)); 509 Assert.That(creatorId, Is.EqualTo(rpCreatorId));
483 Assert.NotNull(daMap); 510 Assert.NotNull(daMap);
484 Assert.AreEqual(daValue, daMap[daStoreName][daKey].AsString()); 511 Assert.AreEqual(daValue, daMap.GetStore(daNamespace, daStoreName)[daKey].AsString());
485 } 512 }
486 513
487 [Test] 514 [Test]
@@ -496,7 +523,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
496 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("9be68fdd-f740-4a0f-9675-dfbbb536b946"))); 523 Assert.That(rootPart.UUID, Is.EqualTo(new UUID("9be68fdd-f740-4a0f-9675-dfbbb536b946")));
497 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("b46ef588-411e-4a8b-a284-d7dcfe8e74ef"))); 524 Assert.That(rootPart.CreatorID, Is.EqualTo(new UUID("b46ef588-411e-4a8b-a284-d7dcfe8e74ef")));
498 Assert.That(rootPart.Name, Is.EqualTo("PrimFun")); 525 Assert.That(rootPart.Name, Is.EqualTo("PrimFun"));
499 OSDMap store = rootPart.DynAttrs["MyStore"]; 526 OSDMap store = rootPart.DynAttrs.GetStore("MyNamespace", "MyStore");
500 Assert.AreEqual("Rosebud", store["last words"].AsString()); 527 Assert.AreEqual("Rosebud", store["last words"].AsString());
501 528
502 // TODO: Check other properties 529 // TODO: Check other properties
@@ -522,13 +549,14 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
522 rp.CreatorID = rpCreatorId; 549 rp.CreatorID = rpCreatorId;
523 rp.Shape = shape; 550 rp.Shape = shape;
524 551
552 string daNamespace = "MyNamespace";
525 string daStoreName = "MyStore"; 553 string daStoreName = "MyStore";
526 string daKey = "foo"; 554 string daKey = "foo";
527 string daValue = "bar"; 555 string daValue = "bar";
528 OSDMap myStore = new OSDMap(); 556 OSDMap myStore = new OSDMap();
529 myStore.Add(daKey, daValue); 557 myStore.Add(daKey, daValue);
530 rp.DynAttrs = new DAMap(); 558 rp.DynAttrs = new DAMap();
531 rp.DynAttrs[daStoreName] = myStore; 559 rp.DynAttrs.SetStore(daNamespace, daStoreName, myStore);
532 560
533 SceneObjectGroup so = new SceneObjectGroup(rp); 561 SceneObjectGroup so = new SceneObjectGroup(rp);
534 562
@@ -585,7 +613,7 @@ namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
585 Assert.That(name, Is.EqualTo(rpName)); 613 Assert.That(name, Is.EqualTo(rpName));
586 Assert.That(creatorId, Is.EqualTo(rpCreatorId)); 614 Assert.That(creatorId, Is.EqualTo(rpCreatorId));
587 Assert.NotNull(daMap); 615 Assert.NotNull(daMap);
588 Assert.AreEqual(daValue, daMap[daStoreName][daKey].AsString()); 616 Assert.AreEqual(daValue, daMap.GetStore(daNamespace, daStoreName)[daKey].AsString());
589 } 617 }
590 } 618 }
591} \ No newline at end of file 619} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index 883045a..d093224 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -369,6 +369,15 @@ namespace OpenSim.Region.CoreModules.World.Sound
369 }); 369 });
370 } 370 }
371 371
372 public void SetSoundQueueing(UUID objectID, bool shouldQueue)
373 {
374 SceneObjectPart part;
375 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
376 return;
377
378 part.SoundQueueing = shouldQueue;
379 }
380
372 #endregion 381 #endregion
373 } 382 }
374} 383}
diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
index 9de588c..35014f5 100644
--- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
@@ -216,13 +216,13 @@ namespace OpenSim.Region.CoreModules
216 // FIXME: If console region is root then this will be printed by every module. Currently, there is no 216 // FIXME: If console region is root then this will be printed by every module. Currently, there is no
217 // way to prevent this, short of making the entire module shared (which is complete overkill). 217 // way to prevent this, short of making the entire module shared (which is complete overkill).
218 // One possibility is to return a bool to signal whether the module has completely handled the command 218 // One possibility is to return a bool to signal whether the module has completely handled the command
219 m_log.InfoFormat("[WIND]: Please change to a specific region in order to set Sun parameters."); 219 MainConsole.Instance.Output("Please change to a specific region in order to set Sun parameters.");
220 return; 220 return;
221 } 221 }
222 222
223 if (m_scene.ConsoleScene() != m_scene) 223 if (m_scene.ConsoleScene() != m_scene)
224 { 224 {
225 m_log.InfoFormat("[WIND]: Console Scene is not my scene."); 225 MainConsole.Instance.Output("Console Scene is not my scene.");
226 return; 226 return;
227 } 227 }
228 } 228 }
@@ -233,7 +233,9 @@ namespace OpenSim.Region.CoreModules
233 private void HandleConsoleCommand(string module, string[] cmdparams) 233 private void HandleConsoleCommand(string module, string[] cmdparams)
234 { 234 {
235 ValidateConsole(); 235 ValidateConsole();
236 m_log.Info("[WIND] The wind command can be used to change the currently active wind model plugin and update the parameters for wind plugins."); 236
237 MainConsole.Instance.Output(
238 "The wind command can be used to change the currently active wind model plugin and update the parameters for wind plugins.");
237 } 239 }
238 240
239 /// <summary> 241 /// <summary>
@@ -246,7 +248,9 @@ namespace OpenSim.Region.CoreModules
246 if ((cmdparams.Length != 4) 248 if ((cmdparams.Length != 4)
247 || !cmdparams[1].Equals("base")) 249 || !cmdparams[1].Equals("base"))
248 { 250 {
249 m_log.Info("[WIND] Invalid parameters to change parameters for Wind module base, usage: wind base <parameter> <value>"); 251 MainConsole.Instance.Output(
252 "Invalid parameters to change parameters for Wind module base, usage: wind base <parameter> <value>");
253
250 return; 254 return;
251 } 255 }
252 256
@@ -261,7 +265,9 @@ namespace OpenSim.Region.CoreModules
261 } 265 }
262 else 266 else
263 { 267 {
264 m_log.InfoFormat("[WIND] Invalid value {0} specified for {1}", cmdparams[3], cmdparams[2]); 268 MainConsole.Instance.OutputFormat(
269 "Invalid value {0} specified for {1}", cmdparams[3], cmdparams[2]);
270
265 return; 271 return;
266 } 272 }
267 273
@@ -271,22 +277,23 @@ namespace OpenSim.Region.CoreModules
271 277
272 if (desiredPlugin.Equals(m_activeWindPlugin.Name)) 278 if (desiredPlugin.Equals(m_activeWindPlugin.Name))
273 { 279 {
274 m_log.InfoFormat("[WIND] Wind model plugin {0} is already active", cmdparams[3]); 280 MainConsole.Instance.OutputFormat("Wind model plugin {0} is already active", cmdparams[3]);
281
275 return; 282 return;
276 } 283 }
277 284
278 if (m_availableWindPlugins.ContainsKey(desiredPlugin)) 285 if (m_availableWindPlugins.ContainsKey(desiredPlugin))
279 { 286 {
280 m_activeWindPlugin = m_availableWindPlugins[cmdparams[3]]; 287 m_activeWindPlugin = m_availableWindPlugins[cmdparams[3]];
281 m_log.InfoFormat("[WIND] {0} wind model plugin now active", m_activeWindPlugin.Name); 288
289 MainConsole.Instance.OutputFormat("{0} wind model plugin now active", m_activeWindPlugin.Name);
282 } 290 }
283 else 291 else
284 { 292 {
285 m_log.InfoFormat("[WIND] Could not find wind model plugin {0}", desiredPlugin); 293 MainConsole.Instance.OutputFormat("Could not find wind model plugin {0}", desiredPlugin);
286 } 294 }
287 break; 295 break;
288 } 296 }
289
290 } 297 }
291 298
292 /// <summary> 299 /// <summary>
@@ -300,7 +307,7 @@ namespace OpenSim.Region.CoreModules
300 if ((cmdparams.Length != 4) 307 if ((cmdparams.Length != 4)
301 && (cmdparams.Length != 3)) 308 && (cmdparams.Length != 3))
302 { 309 {
303 m_log.Info("[WIND] Usage: wind <plugin> <param> [value]"); 310 MainConsole.Instance.Output("Usage: wind <plugin> <param> [value]");
304 return; 311 return;
305 } 312 }
306 313
@@ -311,16 +318,17 @@ namespace OpenSim.Region.CoreModules
311 { 318 {
312 if (!float.TryParse(cmdparams[3], out value)) 319 if (!float.TryParse(cmdparams[3], out value))
313 { 320 {
314 m_log.InfoFormat("[WIND] Invalid value {0}", cmdparams[3]); 321 MainConsole.Instance.OutputFormat("Invalid value {0}", cmdparams[3]);
315 } 322 }
316 323
317 try 324 try
318 { 325 {
319 WindParamSet(plugin, param, value); 326 WindParamSet(plugin, param, value);
327 MainConsole.Instance.OutputFormat("{0} set to {1}", param, value);
320 } 328 }
321 catch (Exception e) 329 catch (Exception e)
322 { 330 {
323 m_log.InfoFormat("[WIND] {0}", e.Message); 331 MainConsole.Instance.OutputFormat("{0}", e.Message);
324 } 332 }
325 } 333 }
326 else 334 else
@@ -328,11 +336,11 @@ namespace OpenSim.Region.CoreModules
328 try 336 try
329 { 337 {
330 value = WindParamGet(plugin, param); 338 value = WindParamGet(plugin, param);
331 m_log.InfoFormat("[WIND] {0} : {1}", param, value); 339 MainConsole.Instance.OutputFormat("{0} : {1}", param, value);
332 } 340 }
333 catch (Exception e) 341 catch (Exception e)
334 { 342 {
335 m_log.InfoFormat("[WIND] {0}", e.Message); 343 MainConsole.Instance.OutputFormat("{0}", e.Message);
336 } 344 }
337 } 345 }
338 346
@@ -366,13 +374,11 @@ namespace OpenSim.Region.CoreModules
366 { 374 {
367 IWindModelPlugin windPlugin = m_availableWindPlugins[plugin]; 375 IWindModelPlugin windPlugin = m_availableWindPlugins[plugin];
368 windPlugin.WindParamSet(param, value); 376 windPlugin.WindParamSet(param, value);
369 m_log.InfoFormat("[WIND] {0} set to {1}", param, value);
370 } 377 }
371 else 378 else
372 { 379 {
373 throw new Exception(String.Format("Could not find plugin {0}", plugin)); 380 throw new Exception(String.Format("Could not find plugin {0}", plugin));
374 } 381 }
375
376 } 382 }
377 383
378 public float WindParamGet(string plugin, string param) 384 public float WindParamGet(string plugin, string param)
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index bf18616..5412359 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -115,6 +115,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
115 "export-map [<path>]", 115 "export-map [<path>]",
116 "Save an image of the world map", HandleExportWorldMapConsoleCommand); 116 "Save an image of the world map", HandleExportWorldMapConsoleCommand);
117 117
118 m_scene.AddCommand(
119 "Regions", this, "generate map",
120 "generate map",
121 "Generates and stores a new maptile.", HandleGenerateMapConsoleCommand);
122
118 AddHandlers(); 123 AddHandlers();
119 } 124 }
120 } 125 }
@@ -162,7 +167,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
162 regionimage = regionimage.Replace("-", ""); 167 regionimage = regionimage.Replace("-", "");
163 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage); 168 m_log.Info("[WORLD MAP]: JPEG Map location: " + m_scene.RegionInfo.ServerURI + "index.php?method=" + regionimage);
164 169
165 MainServer.Instance.AddHTTPHandler(regionimage, OnHTTPGetMapImage); 170 MainServer.Instance.AddHTTPHandler(regionimage,
171 new GenericHTTPDOSProtector(OnHTTPGetMapImage, OnHTTPThrottled, new BasicDosProtectorOptions()
172 {
173 AllowXForwardedFor = false,
174 ForgetTimeSpan = TimeSpan.FromMinutes(2),
175 MaxRequestsInTimeframe = 4,
176 ReportingName = "MAPDOSPROTECTOR",
177 RequestTimeSpan = TimeSpan.FromSeconds(10),
178 ThrottledAction = BasicDOSProtector.ThrottleAction.DoThrottledMethod
179 }).Process);
166 MainServer.Instance.AddLLSDHandler( 180 MainServer.Instance.AddLLSDHandler(
167 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest); 181 "/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), HandleRemoteMapItemRequest);
168 182
@@ -1131,6 +1145,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1131 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize); 1145 block.Y = (ushort)(r.RegionLocY / Constants.RegionSize);
1132 } 1146 }
1133 1147
1148 public Hashtable OnHTTPThrottled(Hashtable keysvals)
1149 {
1150 Hashtable reply = new Hashtable();
1151 int statuscode = 500;
1152 reply["str_response_string"] = "";
1153 reply["int_response_code"] = statuscode;
1154 reply["content_type"] = "text/plain";
1155 return reply;
1156 }
1157
1134 public Hashtable OnHTTPGetMapImage(Hashtable keysvals) 1158 public Hashtable OnHTTPGetMapImage(Hashtable keysvals)
1135 { 1159 {
1136 m_log.Debug("[WORLD MAP]: Sending map image jpeg"); 1160 m_log.Debug("[WORLD MAP]: Sending map image jpeg");
@@ -1305,6 +1329,16 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1305 m_scene.RegionInfo.RegionName, exportPath); 1329 m_scene.RegionInfo.RegionName, exportPath);
1306 } 1330 }
1307 1331
1332 public void HandleGenerateMapConsoleCommand(string module, string[] cmdparams)
1333 {
1334 Scene consoleScene = m_scene.ConsoleScene();
1335
1336 if (consoleScene != null && consoleScene != m_scene)
1337 return;
1338
1339 GenerateMaptile();
1340 }
1341
1308 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint) 1342 public OSD HandleRemoteMapItemRequest(string path, OSD request, string endpoint)
1309 { 1343 {
1310 uint xstart = 0; 1344 uint xstart = 0;
@@ -1542,88 +1576,69 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
1542 1576
1543 private Byte[] GenerateOverlay() 1577 private Byte[] GenerateOverlay()
1544 { 1578 {
1545 Bitmap overlay = new Bitmap(256, 256); 1579 using (Bitmap overlay = new Bitmap(256, 256))
1546
1547 bool[,] saleBitmap = new bool[64, 64];
1548 for (int x = 0 ; x < 64 ; x++)
1549 { 1580 {
1550 for (int y = 0 ; y < 64 ; y++) 1581 bool[,] saleBitmap = new bool[64, 64];
1551 saleBitmap[x, y] = false; 1582 for (int x = 0 ; x < 64 ; x++)
1552 } 1583 {
1553 1584 for (int y = 0 ; y < 64 ; y++)
1554 bool landForSale = false; 1585 saleBitmap[x, y] = false;
1586 }
1555 1587
1556 List<ILandObject> parcels = m_scene.LandChannel.AllParcels(); 1588 bool landForSale = false;
1557 1589
1558 Color background = Color.FromArgb(0, 0, 0, 0); 1590 List<ILandObject> parcels = m_scene.LandChannel.AllParcels();
1559 SolidBrush transparent = new SolidBrush(background);
1560 Graphics g = Graphics.FromImage(overlay);
1561 g.FillRectangle(transparent, 0, 0, 255, 255);
1562 1591
1563 SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)); 1592 Color background = Color.FromArgb(0, 0, 0, 0);
1564 Pen grey = new Pen(Color.FromArgb(255, 92, 92, 92));
1565 1593
1566 foreach (ILandObject land in parcels) 1594 using (Graphics g = Graphics.FromImage(overlay))
1567 {
1568 // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags);
1569 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1570 { 1595 {
1571 landForSale = true; 1596 using (SolidBrush transparent = new SolidBrush(background))
1572 1597 g.FillRectangle(transparent, 0, 0, 256, 256);
1573 bool[,] landBitmap = land.GetLandBitmap();
1574 1598
1575 for (int x = 0 ; x < 64 ; x++) 1599
1600 foreach (ILandObject land in parcels)
1576 { 1601 {
1577 for (int y = 0 ; y < 64 ; y++) 1602 // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags);
1603 if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0)
1578 { 1604 {
1579 if (landBitmap[x, y]) 1605 landForSale = true;
1606
1607 saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap());
1608 }
1609 }
1610
1611 if (!landForSale)
1612 {
1613 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName);
1614 return null;
1615 }
1616
1617 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1618
1619 using (SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)))
1620 {
1621 for (int x = 0 ; x < 64 ; x++)
1622 {
1623 for (int y = 0 ; y < 64 ; y++)
1580 { 1624 {
1581 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4); 1625 if (saleBitmap[x, y])
1582 1626 g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4);
1583 if (x > 0)
1584 {
1585 if ((saleBitmap[x - 1, y] || landBitmap[x - 1, y]) == false)
1586 g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4, 255 - (y * 4));
1587 }
1588 if (y > 0)
1589 {
1590 if ((saleBitmap[x, y-1] || landBitmap[x, y-1]) == false)
1591 g.DrawLine(grey, x * 4, 255 - (y * 4), x * 4 + 3, 255 - (y * 4));
1592 }
1593 if (x < 63)
1594 {
1595 if ((saleBitmap[x + 1, y] || landBitmap[x + 1, y]) == false)
1596 g.DrawLine(grey, x * 4 + 3, 252 - (y * 4), x * 4 + 3, 255 - (y * 4));
1597 }
1598 if (y < 63)
1599 {
1600 if ((saleBitmap[x, y + 1] || landBitmap[x, y + 1]) == false)
1601 g.DrawLine(grey, x * 4, 252 - (y * 4), x * 4 + 3, 252 - (y * 4));
1602 }
1603 } 1627 }
1604 } 1628 }
1605 } 1629 }
1606
1607 saleBitmap = land.MergeLandBitmaps(saleBitmap, landBitmap);
1608 } 1630 }
1609 }
1610 1631
1611 if (!landForSale) 1632 try
1612 { 1633 {
1613 m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not generating overlay", m_scene.RegionInfo.RegionName); 1634 return OpenJPEG.EncodeFromImage(overlay, true);
1614 return null; 1635 }
1636 catch (Exception e)
1637 {
1638 m_log.DebugFormat("[WORLD MAP]: Error creating parcel overlay: " + e.ToString());
1639 }
1615 } 1640 }
1616 1641
1617 m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, generating overlay", m_scene.RegionInfo.RegionName);
1618
1619 try
1620 {
1621 return OpenJPEG.EncodeFromImage(overlay, true);
1622 }
1623 catch (Exception e)
1624 {
1625 m_log.DebugFormat("[WORLD MAP]: Error creating parcel overlay: " + e.ToString());
1626 }
1627 return null; 1642 return null;
1628 } 1643 }
1629 } 1644 }
diff --git a/OpenSim/Region/DataSnapshot/DataRequestHandler.cs b/OpenSim/Region/DataSnapshot/DataRequestHandler.cs
index 32e93b4..50276ae 100644
--- a/OpenSim/Region/DataSnapshot/DataRequestHandler.cs
+++ b/OpenSim/Region/DataSnapshot/DataRequestHandler.cs
@@ -63,7 +63,7 @@ namespace OpenSim.Region.DataSnapshot
63 63
64 public Hashtable OnGetSnapshot(Hashtable keysvals) 64 public Hashtable OnGetSnapshot(Hashtable keysvals)
65 { 65 {
66 m_log.Info("[DATASNAPSHOT] Received collection request"); 66 m_log.Debug("[DATASNAPSHOT] Received collection request");
67 Hashtable reply = new Hashtable(); 67 Hashtable reply = new Hashtable();
68 int statuscode = 200; 68 int statuscode = 200;
69 69
@@ -80,7 +80,7 @@ namespace OpenSim.Region.DataSnapshot
80 80
81 public Hashtable OnValidate(Hashtable keysvals) 81 public Hashtable OnValidate(Hashtable keysvals)
82 { 82 {
83 m_log.Info("[DATASNAPSHOT] Received validation request"); 83 m_log.Debug("[DATASNAPSHOT] Received validation request");
84 Hashtable reply = new Hashtable(); 84 Hashtable reply = new Hashtable();
85 int statuscode = 200; 85 int statuscode = 200;
86 86
diff --git a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
index dd48dd5..0c0a7aa 100644
--- a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
+++ b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs
@@ -307,7 +307,7 @@ namespace OpenSim.Region.DataSnapshot
307 XmlNode regiondata = requestedSnap.CreateNode(XmlNodeType.Element, "regiondata", ""); 307 XmlNode regiondata = requestedSnap.CreateNode(XmlNodeType.Element, "regiondata", "");
308 try 308 try
309 { 309 {
310 if (regionName == null || regionName == "") 310 if (string.IsNullOrEmpty(regionName))
311 { 311 {
312 XmlNode timerblock = requestedSnap.CreateNode(XmlNodeType.Element, "expire", ""); 312 XmlNode timerblock = requestedSnap.CreateNode(XmlNodeType.Element, "expire", "");
313 timerblock.InnerText = m_period.ToString(); 313 timerblock.InnerText = m_period.ToString();
diff --git a/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs b/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
index 0e7df07..3d74597 100644
--- a/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/DataSnapshot/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/DataSnapshot/SnapshotStore.cs b/OpenSim/Region/DataSnapshot/SnapshotStore.cs
index aa3d2ff..480aaaf 100644
--- a/OpenSim/Region/DataSnapshot/SnapshotStore.cs
+++ b/OpenSim/Region/DataSnapshot/SnapshotStore.cs
@@ -120,7 +120,7 @@ namespace OpenSim.Region.DataSnapshot
120 provider.Stale = false; 120 provider.Stale = false;
121 m_scenes[provider.GetParentScene] = true; 121 m_scenes[provider.GetParentScene] = true;
122 122
123 m_log.Info("[DATASNAPSHOT]: Generated fragment response for provider type " + provider.Name); 123 m_log.Debug("[DATASNAPSHOT]: Generated fragment response for provider type " + provider.Name);
124 } 124 }
125 else 125 else
126 { 126 {
@@ -134,7 +134,7 @@ namespace OpenSim.Region.DataSnapshot
134 data = factory.ImportNode(node, true); 134 data = factory.ImportNode(node, true);
135 } 135 }
136 136
137 m_log.Info("[DATASNAPSHOT]: Retrieved fragment response for provider type " + provider.Name); 137 m_log.Debug("[DATASNAPSHOT]: Retrieved fragment response for provider type " + provider.Name);
138 } 138 }
139 139
140 return data; 140 return data;
@@ -154,7 +154,7 @@ namespace OpenSim.Region.DataSnapshot
154 154
155 if (!m_scenes[scene]) 155 if (!m_scenes[scene])
156 { 156 {
157 m_log.Info("[DATASNAPSHOT]: Attempting to retrieve snapshot from cache."); 157 m_log.Debug("[DATASNAPSHOT]: Attempting to retrieve snapshot from cache.");
158 //get snapshot from cache 158 //get snapshot from cache
159 String path = DataFileNameScene(scene); 159 String path = DataFileNameScene(scene);
160 160
@@ -168,11 +168,11 @@ namespace OpenSim.Region.DataSnapshot
168 regionElement = factory.ImportNode(node, true); 168 regionElement = factory.ImportNode(node, true);
169 } 169 }
170 170
171 m_log.Info("[DATASNAPSHOT]: Obtained snapshot from cache for " + scene.RegionInfo.RegionName); 171 m_log.Debug("[DATASNAPSHOT]: Obtained snapshot from cache for " + scene.RegionInfo.RegionName);
172 } 172 }
173 else 173 else
174 { 174 {
175 m_log.Info("[DATASNAPSHOT]: Attempting to generate snapshot."); 175 m_log.Debug("[DATASNAPSHOT]: Attempting to generate snapshot.");
176 //make snapshot 176 //make snapshot
177 regionElement = MakeRegionNode(scene, factory); 177 regionElement = MakeRegionNode(scene, factory);
178 178
@@ -211,7 +211,7 @@ namespace OpenSim.Region.DataSnapshot
211 211
212 m_scenes[scene] = false; 212 m_scenes[scene] = false;
213 213
214 m_log.Info("[DATASNAPSHOT]: Generated new snapshot for " + scene.RegionInfo.RegionName); 214 m_log.Debug("[DATASNAPSHOT]: Generated new snapshot for " + scene.RegionInfo.RegionName);
215 } 215 }
216 216
217 return regionElement; 217 return regionElement;
diff --git a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
index 21ed44f..b536a49 100644
--- a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
@@ -1,9 +1,30 @@
1//////////////////////////////////////////////////////////////// 1/*
2// 2 * Copyright (c) Contributors, http://opensimulator.org/
3// (c) 2009, 2010 Careminster Limited and Melanie Thielker 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4// 4 *
5// All rights reserved 5 * Redistribution and use in source and binary forms, with or without
6// 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
7using System; 28using System;
8using Nini.Config; 29using Nini.Config;
9using OpenSim.Framework; 30using OpenSim.Framework;
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 8028d87..eba881f 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -236,15 +236,17 @@ namespace OpenSim.Region.Framework.Interfaces
236 List<TaskInventoryItem> GetInventoryItems(InventoryType type); 236 List<TaskInventoryItem> GetInventoryItems(InventoryType type);
237 237
238 /// <summary> 238 /// <summary>
239 /// Get the scene object referenced by an inventory item. 239 /// Get the scene object(s) referenced by an inventory item.
240 /// </summary> 240 /// </summary>
241 /// 241 ///
242 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have 242 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have
243 /// been adjusted to reflect the part and item from which it originates. 243 /// been adjusted to reflect the part and item from which it originates.
244 /// 244 ///
245 /// <param name="item"></param> 245 /// <param name="item">Inventory item</param>
246 /// <returns>The scene object. Null if the scene object asset couldn't be found</returns> 246 /// <param name="objlist">The scene objects</param>
247 SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item); 247 /// <param name="veclist">Relative offsets for each object</param>
248 /// <returns>true = success, false = the scene object asset couldn't be found</returns>
249 bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist);
248 250
249 /// <summary> 251 /// <summary>
250 /// Update an existing inventory item. 252 /// Update an existing inventory item.
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 1949a90..214b07a 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -47,13 +47,33 @@ namespace OpenSim.Region.Framework.Interfaces
47 /// The handle of the destination region. If it's the same as the region currently 47 /// The handle of the destination region. If it's the same as the region currently
48 /// occupied by the agent then the teleport will be within that region. 48 /// occupied by the agent then the teleport will be within that region.
49 /// </param> 49 /// </param>
50 /// <param name='agent'></param>
51 /// <param name='regionHandle'></param>
50 /// <param name='position'></param> 52 /// <param name='position'></param>
51 /// <param name='lookAt'></param> 53 /// <param name='lookAt'></param>
52 /// <param name='teleportFlags'></param> 54 /// <param name='teleportFlags'></param>
53 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); 55 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags);
54 56
57 /// <summary>
58 /// Teleports the agent for the given client to their home destination.
59 /// </summary>
60 /// <param name='id'></param>
61 /// <param name='client'></param>
55 bool TeleportHome(UUID id, IClientAPI client); 62 bool TeleportHome(UUID id, IClientAPI client);
56 63
64 /// <summary>
65 /// Teleport an agent directly to a given region without checking whether the region should be substituted.
66 /// </summary>
67 /// <remarks>
68 /// Please use Teleport() instead unless you know exactly what you're doing.
69 /// Do not use for same region teleports.
70 /// </remarks>
71 /// <param name='sp'></param>
72 /// <param name='reg'></param>
73 /// <param name='finalDestination'>/param>
74 /// <param name='position'></param>
75 /// <param name='lookAt'></param>
76 /// <param name='teleportFlags'></param>
57 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, 77 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
58 Vector3 position, Vector3 lookAt, uint teleportFlags); 78 Vector3 position, Vector3 lookAt, uint teleportFlags);
59 79
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 292efa4..944c66b 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Interfaces
40 40
41 uint GetRegionFlags(); 41 uint GetRegionFlags();
42 bool IsManager(UUID avatarID); 42 bool IsManager(UUID avatarID);
43 43
44 /// <summary> 44 /// <summary>
45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.). 45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.).
46 /// </summary> 46 /// </summary>
@@ -54,5 +54,10 @@ namespace OpenSim.Region.Framework.Interfaces
54 54
55 void setEstateTerrainBaseTexture(int level, UUID texture); 55 void setEstateTerrainBaseTexture(int level, UUID texture);
56 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue); 56 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue);
57
58 /// <summary>
59 /// Returns whether the transfer ID is being used for a terrain transfer.
60 /// </summary>
61 bool IsTerrainXfer(ulong xferID);
57 } 62 }
58} 63}
diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
index 5512642..dfc269e 100644
--- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
@@ -39,21 +39,22 @@ namespace OpenSim.Region.Framework.Interfaces
39 39
40 // These are required to decouple Scenes from EventQueueHelper 40 // These are required to decouple Scenes from EventQueueHelper
41 void DisableSimulator(ulong handle, UUID avatarID); 41 void DisableSimulator(ulong handle, UUID avatarID);
42 void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID); 42 void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY);
43 void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, 43 void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint,
44 string capsPath); 44 string capsPath, ulong regionHandle, int regionSizeX, int regionSizeY);
45 void TeleportFinishEvent(ulong regionHandle, byte simAccess, 45 void TeleportFinishEvent(ulong regionHandle, byte simAccess,
46 IPEndPoint regionExternalEndPoint, 46 IPEndPoint regionExternalEndPoint,
47 uint locationID, uint flags, string capsURL, 47 uint locationID, uint flags, string capsURL,
48 UUID agentID); 48 UUID agentID, int regionSizeX, int regionSizeY);
49 void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, 49 void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
50 IPEndPoint newRegionExternalEndPoint, 50 IPEndPoint newRegionExternalEndPoint,
51 string capsURL, UUID avatarID, UUID sessionID); 51 string capsURL, UUID avatarID, UUID sessionID,
52 int regionSizeX, int regionSizeY);
52 void ChatterboxInvitation(UUID sessionID, string sessionName, 53 void ChatterboxInvitation(UUID sessionID, string sessionName,
53 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, 54 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
54 uint timeStamp, bool offline, int parentEstateID, Vector3 position, 55 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
55 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket); 56 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket);
56 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat, 57 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, bool canVoiceChat,
57 bool isModerator, bool textMute); 58 bool isModerator, bool textMute);
58 void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID); 59 void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID);
59 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID); 60 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID);
diff --git a/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs b/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs
new file mode 100644
index 0000000..a730cfd
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs
@@ -0,0 +1,48 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using OpenMetaverse;
30using OpenSim.Framework;
31using Caps=OpenSim.Framework.Capabilities.Caps;
32
33namespace OpenSim.Region.Framework.Interfaces
34{
35 public interface IExternalCapsModule
36 {
37 /// <summary>
38 /// This function extends the simple URL configuration in the caps handlers
39 /// to facilitate more interesting computation when an external handler is
40 /// sent to the viewer.
41 /// </summary>
42 /// <param name="agentID">New user UUID</param>
43 /// <param name="caps">Internal caps registry, where the external handler will be registered</param>
44 /// <param name="capName">Name of the specific cap we are registering</param>
45 /// <param name="urlSkel">The skeleton URL provided in the caps configuration</param>
46 bool RegisterExternalUserCapsHandler(UUID agentID, Caps caps, String capName, String urlSkel);
47 }
48}
diff --git a/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs b/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs
index 6885327..9ae5e87 100644
--- a/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs
@@ -97,5 +97,7 @@ namespace OpenSim.Region.Framework.Interfaces
97 void InviteGroupRequest(IClientAPI remoteClient, UUID GroupID, UUID InviteeID, UUID RoleID); 97 void InviteGroupRequest(IClientAPI remoteClient, UUID GroupID, UUID InviteeID, UUID RoleID);
98 void InviteGroup(IClientAPI remoteClient, UUID agentID, UUID GroupID, UUID InviteeID, UUID RoleID); 98 void InviteGroup(IClientAPI remoteClient, UUID agentID, UUID GroupID, UUID InviteeID, UUID RoleID);
99 void NotifyChange(UUID GroupID); 99 void NotifyChange(UUID GroupID);
100
101 List<DirGroupsReplyData> FindGroups(IClientAPI remoteClient, string query);
100 } 102 }
101} \ No newline at end of file 103} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
deleted file mode 100644
index 67a500f..0000000
--- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
+++ /dev/null
@@ -1,119 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenMetaverse;
29using OpenSim.Framework;
30using OpenSim.Region.Framework.Scenes;
31
32namespace OpenSim.Region.Framework.Interfaces
33{
34 public delegate bool ChildAgentUpdateReceived(AgentData data);
35
36 public interface IInterregionCommsOut
37 {
38 #region Agents
39
40 bool SendCreateChildAgent(ulong regionHandle, AgentCircuitData aCircuit, uint teleportFlags, out string reason);
41
42 /// <summary>
43 /// Full child agent update.
44 /// </summary>
45 /// <param name="regionHandle"></param>
46 /// <param name="data"></param>
47 /// <returns></returns>
48 bool SendChildAgentUpdate(ulong regionHandle, AgentData data);
49
50 /// <summary>
51 /// Short child agent update, mostly for position.
52 /// </summary>
53 /// <param name="regionHandle"></param>
54 /// <param name="data"></param>
55 /// <returns></returns>
56 bool SendChildAgentUpdate(ulong regionHandle, AgentPosition data);
57
58 bool SendRetrieveRootAgent(ulong regionHandle, UUID id, out IAgentData agent);
59
60 /// <summary>
61 /// Message from receiving region to departing region, telling it got contacted by the client.
62 /// When sent over REST, it invokes the opaque uri.
63 /// </summary>
64 /// <param name="regionHandle"></param>
65 /// <param name="id"></param>
66 /// <param name="uri"></param>
67 /// <returns></returns>
68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri);
69
70 /// <summary>
71 /// Close chid agent.
72 /// </summary>
73 /// <param name="regionHandle"></param>
74 /// <param name="id"></param>
75 /// <returns></returns>
76 bool SendCloseChildAgent(ulong regionHandle, UUID id);
77
78 /// <summary>
79 /// Close agent.
80 /// </summary>
81 /// <param name="regionHandle"></param>
82 /// <param name="id"></param>
83 /// <returns></returns>
84 bool SendCloseAgent(ulong regionHandle, UUID id);
85
86 #endregion Agents
87
88 #region Objects
89
90 /// <summary>
91 /// Create an object in the destination region. This message is used primarily for prim crossing.
92 /// </summary>
93 /// <param name="regionHandle"></param>
94 /// <param name="sog"></param>
95 /// <param name="isLocalCall"></param>
96 /// <returns></returns>
97 bool SendCreateObject(ulong regionHandle, SceneObjectGroup sog, bool isLocalCall);
98
99 /// <summary>
100 /// Create an object from the user's inventory in the destination region.
101 /// This message is used primarily by clients.
102 /// </summary>
103 /// <param name="regionHandle"></param>
104 /// <param name="userID"></param>
105 /// <param name="itemID"></param>
106 /// <returns></returns>
107 bool SendCreateObject(ulong regionHandle, UUID userID, UUID itemID);
108
109 #endregion Objects
110
111 }
112
113 // This may not be needed, but having it here for now.
114 public interface IInterregionCommsIn
115 {
116 event ChildAgentUpdateReceived OnChildAgentUpdate;
117 }
118
119}
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
index b67312e..1a89721 100644
--- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
@@ -51,10 +51,17 @@ namespace OpenSim.Region.Framework.Interfaces
51 UUID = 5 51 UUID = 5
52 } 52 }
53 53
54 public struct JsonStoreStats
55 {
56 public int StoreCount;
57 }
58
54 public delegate void TakeValueCallback(string s); 59 public delegate void TakeValueCallback(string s);
55 60
56 public interface IJsonStoreModule 61 public interface IJsonStoreModule
57 { 62 {
63 JsonStoreStats GetStoreStats();
64
58 bool AttachObjectStore(UUID objectID); 65 bool AttachObjectStore(UUID objectID);
59 bool CreateStore(string value, ref UUID result); 66 bool CreateStore(string value, ref UUID result);
60 bool DestroyStore(UUID storeID); 67 bool DestroyStore(UUID storeID);
diff --git a/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs b/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs
new file mode 100644
index 0000000..198256f
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IServiceThrottleModule.cs
@@ -0,0 +1,19 @@
1using System;
2using System.Collections.Generic;
3
4namespace OpenSim.Region.Framework.Interfaces
5{
6 public interface IServiceThrottleModule
7 {
8 /// <summary>
9 /// Enqueue a continuation meant to get a resource from elsewhere.
10 /// As usual with CPS, caller beware: if that continuation is a never-ending computation,
11 /// the whole thread will be blocked, and no requests are processed
12 /// </summary>
13 /// <param name="category">Category of the resource (e.g. name, region)</param>
14 /// <param name="itemid">The resource identifier</param>
15 /// <param name="continuation">The continuation to be executed</param>
16 void Enqueue(string category, string itemid, Action continuation);
17 }
18
19}
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
index 68af492..8372ddd 100644
--- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
@@ -104,7 +104,6 @@ namespace OpenSim.Region.Framework.Interfaces
104 /// <param name="sound">Sound asset ID</param> 104 /// <param name="sound">Sound asset ID</param>
105 /// <param name="volume">Sound volume</param> 105 /// <param name="volume">Sound volume</param>
106 /// <param name="triggered">Triggered or not.</param> 106 /// <param name="triggered">Triggered or not.</param>
107 /// <param name="flags"></param>
108 /// <param name="radius">Sound radius</param> 107 /// <param name="radius">Sound radius</param>
109 /// <param name="useMaster">Play using sound master</param> 108 /// <param name="useMaster">Play using sound master</param>
110 /// <param name="isMaster">Play as sound master</param> 109 /// <param name="isMaster">Play as sound master</param>
@@ -123,5 +122,12 @@ namespace OpenSim.Region.Framework.Interfaces
123 /// <param name="max">AABB top north-east corner</param> 122 /// <param name="max">AABB top north-east corner</param>
124 void TriggerSoundLimited(UUID objectID, UUID sound, double volume, 123 void TriggerSoundLimited(UUID objectID, UUID sound, double volume,
125 Vector3 min, Vector3 max); 124 Vector3 min, Vector3 max);
125
126 /// <summary>
127 /// Set whether sounds on the given prim should be queued.
128 /// </summary>
129 /// <param name='objectID'></param>
130 /// <param name='shouldQueue'></param>
131 void SetSoundQueueing(UUID objectID, bool shouldQueue);
126 } 132 }
127} \ No newline at end of file 133} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
index 167c248..a2a99d4 100644
--- a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
index 66edfed..b7400ea 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
@@ -28,8 +28,11 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Text;
31using log4net; 32using log4net;
32using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.StructuredData;
35
33using OpenSim.Framework; 36using OpenSim.Framework;
34 37
35using Animation = OpenSim.Framework.Animation; 38using Animation = OpenSim.Framework.Animation;
@@ -60,6 +63,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
60 ResetDefaultAnimation(); 63 ResetDefaultAnimation();
61 } 64 }
62 65
66 public AnimationSet(OSDArray pArray)
67 {
68 ResetDefaultAnimation();
69 FromOSDArray(pArray);
70 }
71
63 public bool HasAnimation(UUID animID) 72 public bool HasAnimation(UUID animID)
64 { 73 {
65 if (m_defaultAnimation.AnimID == animID) 74 if (m_defaultAnimation.AnimID == animID)
@@ -218,5 +227,110 @@ namespace OpenSim.Region.Framework.Scenes.Animation
218 foreach (OpenSim.Framework.Animation anim in theArray) 227 foreach (OpenSim.Framework.Animation anim in theArray)
219 m_animations.Add(anim); 228 m_animations.Add(anim);
220 } 229 }
230
231 // Create representation of this AnimationSet as an OSDArray.
232 // First two entries in the array are the default and implicitDefault animations
233 // followed by the other animations.
234 public OSDArray ToOSDArray()
235 {
236 OSDArray ret = new OSDArray();
237 ret.Add(DefaultAnimation.PackUpdateMessage());
238 ret.Add(ImplicitDefaultAnimation.PackUpdateMessage());
239
240 foreach (OpenSim.Framework.Animation anim in m_animations)
241 ret.Add(anim.PackUpdateMessage());
242
243 return ret;
244 }
245
246 public void FromOSDArray(OSDArray pArray)
247 {
248 this.Clear();
249
250 if (pArray.Count >= 1)
251 {
252 m_defaultAnimation = new OpenSim.Framework.Animation((OSDMap)pArray[0]);
253 }
254 if (pArray.Count >= 2)
255 {
256 m_implicitDefaultAnimation = new OpenSim.Framework.Animation((OSDMap)pArray[1]);
257 }
258 for (int ii = 2; ii < pArray.Count; ii++)
259 {
260 m_animations.Add(new OpenSim.Framework.Animation((OSDMap)pArray[ii]));
261 }
262 }
263
264 // Compare two AnimationSets and return 'true' if the default animations are the same
265 // and all of the animations in the list are equal.
266 public override bool Equals(object obj)
267 {
268 AnimationSet other = obj as AnimationSet;
269 if (other != null)
270 {
271 if (this.DefaultAnimation.Equals(other.DefaultAnimation)
272 && this.ImplicitDefaultAnimation.Equals(other.ImplicitDefaultAnimation))
273 {
274 // The defaults are the same. Is the list of animations the same?
275 OpenSim.Framework.Animation[] thisAnims = this.ToArray();
276 OpenSim.Framework.Animation[] otherAnims = other.ToArray();
277 if (thisAnims.Length == 0 && otherAnims.Length == 0)
278 return true; // the common case
279 if (thisAnims.Length == otherAnims.Length)
280 {
281 // Do this the hard way but since the list is usually short this won't take long.
282 foreach (OpenSim.Framework.Animation thisAnim in thisAnims)
283 {
284 bool found = false;
285 foreach (OpenSim.Framework.Animation otherAnim in otherAnims)
286 {
287 if (thisAnim.Equals(otherAnim))
288 {
289 found = true;
290 break;
291 }
292 }
293 if (!found)
294 {
295 // If anything is not in the other list, these are not equal
296 return false;
297 }
298 }
299 // Found everything in the other list. Since lists are equal length, they must be equal.
300 return true;
301 }
302 }
303 return false;
304 }
305 // Don't know what was passed, but the base system will figure it out for me.
306 return base.Equals(obj);
307 }
308
309 public override string ToString()
310 {
311 StringBuilder buff = new StringBuilder();
312 buff.Append("dflt=");
313 buff.Append(DefaultAnimation.ToString());
314 buff.Append(",iDflt=");
315 if (DefaultAnimation.Equals(ImplicitDefaultAnimation))
316 buff.Append("same");
317 else
318 buff.Append(ImplicitDefaultAnimation.ToString());
319 if (m_animations.Count > 0)
320 {
321 buff.Append(",anims=");
322 bool firstTime = true;
323 foreach (OpenSim.Framework.Animation anim in m_animations)
324 {
325 if (!firstTime)
326 buff.Append(",");
327 buff.Append("<");
328 buff.Append(anim.ToString());
329 buff.Append(">");
330 firstTime = false;
331 }
332 }
333 return buff.ToString();
334 }
221 } 335 }
222} 336}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs b/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs
index c2b0468..b79dd8f 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs
@@ -104,5 +104,31 @@ namespace OpenSim.Region.Framework.Scenes.Animation
104 104
105 return UUID.Zero; 105 return UUID.Zero;
106 } 106 }
107
108 /// <summary>
109 /// Get the name of the animation given a UUID. If there is no matching animation
110 /// return the UUID as a string.
111 /// </summary>
112 public static string GetDefaultAnimationName(UUID uuid)
113 {
114 string ret = "unknown";
115 if (AnimsUUID.ContainsValue(uuid))
116 {
117 foreach (KeyValuePair<string, UUID> kvp in AnimsUUID)
118 {
119 if (kvp.Value == uuid)
120 {
121 ret = kvp.Key;
122 break;
123 }
124 }
125 }
126 else
127 {
128 ret = uuid.ToString();
129 }
130
131 return ret;
132 }
107 } 133 }
108} \ No newline at end of file 134} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 65c279e..c1394aa 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -93,7 +93,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
93 GetAnimName(animID), animID, m_scenePresence.Name); 93 GetAnimName(animID), animID, m_scenePresence.Name);
94 94
95 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) 95 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
96 {
96 SendAnimPack(); 97 SendAnimPack();
98 m_scenePresence.TriggerScenePresenceUpdated();
99 }
97 } 100 }
98 101
99 // Called from scripts 102 // Called from scripts
@@ -132,7 +135,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
132 GetAnimName(animID), animID, m_scenePresence.Name); 135 GetAnimName(animID), animID, m_scenePresence.Name);
133 136
134 if (m_animations.Remove(animID, allowNoDefault)) 137 if (m_animations.Remove(animID, allowNoDefault))
138 {
135 SendAnimPack(); 139 SendAnimPack();
140 m_scenePresence.TriggerScenePresenceUpdated();
141 }
136 } 142 }
137 143
138 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack) 144 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack)
@@ -180,8 +186,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
180 /// The movement animation is reserved for "main" animations 186 /// The movement animation is reserved for "main" animations
181 /// that are mutually exclusive, e.g. flying and sitting. 187 /// that are mutually exclusive, e.g. flying and sitting.
182 /// </summary> 188 /// </summary>
183 public void TrySetMovementAnimation(string anim) 189 /// <returns>'true' if the animation was updated</returns>
190 public bool TrySetMovementAnimation(string anim)
184 { 191 {
192 bool ret = false;
185 if (!m_scenePresence.IsChildAgent) 193 if (!m_scenePresence.IsChildAgent)
186 { 194 {
187// m_log.DebugFormat( 195// m_log.DebugFormat(
@@ -198,6 +206,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
198 // 16384 is CHANGED_ANIMATION 206 // 16384 is CHANGED_ANIMATION
199 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION}); 207 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION});
200 SendAnimPack(); 208 SendAnimPack();
209 ret = true;
201 } 210 }
202 } 211 }
203 else 212 else
@@ -206,6 +215,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
206 "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}", 215 "[SCENE PRESENCE ANIMATOR]: Tried to set movement animation {0} on child presence {1}",
207 anim, m_scenePresence.Name); 216 anim, m_scenePresence.Name);
208 } 217 }
218 return ret;
209 } 219 }
210 220
211 /// <summary> 221 /// <summary>
@@ -410,11 +420,18 @@ namespace OpenSim.Region.Framework.Scenes.Animation
410 Falling = false; 420 Falling = false;
411 // Walking / crouchwalking / running 421 // Walking / crouchwalking / running
412 if (move.Z < 0f) 422 if (move.Z < 0f)
423 {
413 return "CROUCHWALK"; 424 return "CROUCHWALK";
414 else if (m_scenePresence.SetAlwaysRun) 425 }
415 return "RUN"; 426 // We need to prevent these animations if the user tries to make their avatar walk or run whilst
416 else 427 // specifying AGENT_CONTROL_STOP (pressing down space on viewers).
417 return "WALK"; 428 else if (!m_scenePresence.AgentControlStopActive)
429 {
430 if (m_scenePresence.SetAlwaysRun)
431 return "RUN";
432 else
433 return "WALK";
434 }
418 } 435 }
419 else if (!m_jumping) 436 else if (!m_jumping)
420 { 437 {
@@ -439,8 +456,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
439 /// <summary> 456 /// <summary>
440 /// Update the movement animation of this avatar according to its current state 457 /// Update the movement animation of this avatar according to its current state
441 /// </summary> 458 /// </summary>
442 public void UpdateMovementAnimations() 459 /// <returns>'true' if the animation was changed</returns>
460 public bool UpdateMovementAnimations()
443 { 461 {
462// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name);
463
464 bool ret = false;
444 lock (m_animations) 465 lock (m_animations)
445 { 466 {
446 string newMovementAnimation = DetermineMovementAnimation(); 467 string newMovementAnimation = DetermineMovementAnimation();
@@ -454,9 +475,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
454 475
455 // Only set it if it's actually changed, give a script 476 // Only set it if it's actually changed, give a script
456 // a chance to stop a default animation 477 // a chance to stop a default animation
457 TrySetMovementAnimation(CurrentMovementAnimation); 478 ret = TrySetMovementAnimation(CurrentMovementAnimation);
458 } 479 }
459 } 480 }
481 return ret;
460 } 482 }
461 483
462 public UUID[] GetAnimationArray() 484 public UUID[] GetAnimationArray()
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index f555b49..11a0146 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -104,14 +104,8 @@ namespace OpenSim.Region.Framework.Scenes
104 // better than losing the object for now. 104 // better than losing the object for now.
105 if (permissionToDelete) 105 if (permissionToDelete)
106 { 106 {
107 List<uint> killIDs = new List<uint>();
108
109 foreach (SceneObjectGroup g in objectGroups) 107 foreach (SceneObjectGroup g in objectGroups)
110 { killIDs.Add(g.LocalId); 108 g.DeleteGroupFromScene(false);
111 g.DeleteGroupFromScene(true);
112 }
113
114 m_scene.SendKillObject(killIDs);
115 } 109 }
116 } 110 }
117 111
@@ -160,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
160 if (x.permissionToDelete) 154 if (x.permissionToDelete)
161 { 155 {
162 foreach (SceneObjectGroup g in x.objectGroups) 156 foreach (SceneObjectGroup g in x.objectGroups)
163 m_scene.DeleteSceneObject(g, false); 157 m_scene.DeleteSceneObject(g, true);
164 } 158 }
165 } 159 }
166 catch (Exception e) 160 catch (Exception e)
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 4733547..7f06e82 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -148,7 +148,7 @@ namespace OpenSim.Region.Framework.Scenes
148 /// Triggered when a new presence is added to the scene 148 /// Triggered when a new presence is added to the scene
149 /// </summary> 149 /// </summary>
150 /// <remarks> 150 /// <remarks>
151 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both 151 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both
152 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> 152 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
153 /// </remarks> 153 /// </remarks>
154 public event OnNewPresenceDelegate OnNewPresence; 154 public event OnNewPresenceDelegate OnNewPresence;
@@ -159,7 +159,7 @@ namespace OpenSim.Region.Framework.Scenes
159 /// Triggered when a presence is removed from the scene 159 /// Triggered when a presence is removed from the scene
160 /// </summary> 160 /// </summary>
161 /// <remarks> 161 /// <remarks>
162 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both 162 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both
163 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> 163 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
164 /// 164 ///
165 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please 165 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please
@@ -743,7 +743,7 @@ namespace OpenSim.Region.Framework.Scenes
743 public event OnIncomingSceneObjectDelegate OnIncomingSceneObject; 743 public event OnIncomingSceneObjectDelegate OnIncomingSceneObject;
744 public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so); 744 public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so);
745 745
746 public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); 746 public delegate void NewInventoryItemUploadComplete(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel);
747 747
748 public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete; 748 public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete;
749 749
@@ -974,6 +974,8 @@ namespace OpenSim.Region.Framework.Scenes
974 public delegate void RegionStarted(Scene scene); 974 public delegate void RegionStarted(Scene scene);
975 public event RegionStarted OnRegionStarted; 975 public event RegionStarted OnRegionStarted;
976 976
977 public delegate void RegionHeartbeatStart(Scene scene);
978 public event RegionHeartbeatStart OnRegionHeartbeatStart;
977 public delegate void RegionHeartbeatEnd(Scene scene); 979 public delegate void RegionHeartbeatEnd(Scene scene);
978 public event RegionHeartbeatEnd OnRegionHeartbeatEnd; 980 public event RegionHeartbeatEnd OnRegionHeartbeatEnd;
979 981
@@ -1024,6 +1026,16 @@ namespace OpenSim.Region.Framework.Scenes
1024 /// </remarks> 1026 /// </remarks>
1025 public event TeleportFail OnTeleportFail; 1027 public event TeleportFail OnTeleportFail;
1026 1028
1029// public delegate void GatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids);
1030//
1031// /// <summary>
1032// /// Triggered when UUIDs referenced by a scene object are being gathered for archiving, hg transfer, etc.
1033// /// </summary>
1034// /// <remarks>
1035// /// The listener should add references to the IDictionary<UUID, AssetType> as appropriate.
1036// /// </remarks>
1037// public event GatherUuids OnGatherUuids;
1038
1027 public class MoneyTransferArgs : EventArgs 1039 public class MoneyTransferArgs : EventArgs
1028 { 1040 {
1029 public UUID sender; 1041 public UUID sender;
@@ -1095,7 +1107,7 @@ namespace OpenSim.Region.Framework.Scenes
1095 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/> 1107 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/>
1096 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/> 1108 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/>
1097 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/> 1109 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/>
1098 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> 1110 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/>
1099 /// </remarks> 1111 /// </remarks>
1100 public event MoneyTransferEvent OnMoneyTransfer; 1112 public event MoneyTransferEvent OnMoneyTransfer;
1101 1113
@@ -2160,7 +2172,7 @@ namespace OpenSim.Region.Framework.Scenes
2160 } 2172 }
2161 } 2173 }
2162 2174
2163 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, UUID AssetID, String AssetName, int userlevel) 2175 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, AssetType type, UUID AssetID, String AssetName, int userlevel)
2164 { 2176 {
2165 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; 2177 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete;
2166 if (handlerNewInventoryItemUpdateComplete != null) 2178 if (handlerNewInventoryItemUpdateComplete != null)
@@ -2169,7 +2181,7 @@ namespace OpenSim.Region.Framework.Scenes
2169 { 2181 {
2170 try 2182 try
2171 { 2183 {
2172 d(agentID, AssetID, AssetName, userlevel); 2184 d(agentID, type, AssetID, AssetName, userlevel);
2173 } 2185 }
2174 catch (Exception e) 2186 catch (Exception e)
2175 { 2187 {
@@ -3096,6 +3108,27 @@ namespace OpenSim.Region.Framework.Scenes
3096 } 3108 }
3097 } 3109 }
3098 3110
3111 public void TriggerRegionHeartbeatStart(Scene scene)
3112 {
3113 RegionHeartbeatStart handler = OnRegionHeartbeatStart;
3114
3115 if (handler != null)
3116 {
3117 foreach (RegionHeartbeatStart d in handler.GetInvocationList())
3118 {
3119 try
3120 {
3121 d(scene);
3122 }
3123 catch (Exception e)
3124 {
3125 m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionHeartbeatStart failed - continuing {0} - {1}",
3126 e.Message, e.StackTrace);
3127 }
3128 }
3129 }
3130 }
3131
3099 public void TriggerRegionHeartbeatEnd(Scene scene) 3132 public void TriggerRegionHeartbeatEnd(Scene scene)
3100 { 3133 {
3101 RegionHeartbeatEnd handler = OnRegionHeartbeatEnd; 3134 RegionHeartbeatEnd handler = OnRegionHeartbeatEnd;
@@ -3251,5 +3284,26 @@ namespace OpenSim.Region.Framework.Scenes
3251 handler(scenePresence); 3284 handler(scenePresence);
3252 } 3285 }
3253 } 3286 }
3287
3288// public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids)
3289// {
3290// GatherUuids handler = OnGatherUuids;
3291//
3292// if (handler != null)
3293// {
3294// foreach (GatherUuids d in handler.GetInvocationList())
3295// {
3296// try
3297// {
3298// d(sop, assetUuids);
3299// }
3300// catch (Exception e)
3301// {
3302// m_log.ErrorFormat("[EVENT MANAGER]: Delegate for TriggerUuidGather failed - continuing {0} - {1}",
3303// e.Message, e.StackTrace);
3304// }
3305// }
3306// }
3307// }
3254 } 3308 }
3255} 3309}
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index 276b61f..4d153da 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -1,6 +1,29 @@
1// Proprietary code of Avination Virtual Limited 1/*
2// (c) 2012 Melanie Thielker 2 * Copyright (c) Contributors, http://opensimulator.org/
3// 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
4 27
5using System; 28using System;
6using System.Timers; 29using System.Timers;
@@ -32,7 +55,6 @@ namespace OpenSim.Region.Framework.Scenes
32 private object m_lockObject = new object(); 55 private object m_lockObject = new object();
33 private object m_timerLock = new object(); 56 private object m_timerLock = new object();
34 private const double m_tickDuration = 50.0; 57 private const double m_tickDuration = 50.0;
35 private Scene m_scene;
36 58
37 public double TickDuration 59 public double TickDuration
38 { 60 {
@@ -46,8 +68,6 @@ namespace OpenSim.Region.Framework.Scenes
46 m_timer.AutoReset = true; 68 m_timer.AutoReset = true;
47 m_timer.Elapsed += OnTimer; 69 m_timer.Elapsed += OnTimer;
48 70
49 m_scene = scene;
50
51 m_timer.Start(); 71 m_timer.Start();
52 } 72 }
53 73
@@ -71,13 +91,13 @@ namespace OpenSim.Region.Framework.Scenes
71 { 91 {
72 m.OnTimer(TickDuration); 92 m.OnTimer(TickDuration);
73 } 93 }
74 catch (Exception inner) 94 catch (Exception)
75 { 95 {
76 // Don't stop processing 96 // Don't stop processing
77 } 97 }
78 } 98 }
79 } 99 }
80 catch (Exception e) 100 catch (Exception)
81 { 101 {
82 // Keep running no matter what 102 // Keep running no matter what
83 } 103 }
@@ -134,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
134 [Serializable] 154 [Serializable]
135 public class KeyframeMotion 155 public class KeyframeMotion
136 { 156 {
137 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 157// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
138 158
139 public enum PlayMode : int 159 public enum PlayMode : int
140 { 160 {
@@ -478,6 +498,7 @@ namespace OpenSim.Region.Framework.Scenes
478 k.Position = pos; 498 k.Position = pos;
479// k.Velocity = Vector3.Zero; 499// k.Velocity = Vector3.Zero;
480 } 500 }
501 k.AngularVelocity = (Vector3)k.Position;
481 502
482 k.StartRotation = rot; 503 k.StartRotation = rot;
483 if (k.Rotation.HasValue) 504 if (k.Rotation.HasValue)
@@ -618,7 +639,7 @@ namespace OpenSim.Region.Framework.Scenes
618 m_group.RootPart.Velocity = Vector3.Zero; 639 m_group.RootPart.Velocity = Vector3.Zero;
619 m_group.RootPart.AngularVelocity = Vector3.Zero; 640 m_group.RootPart.AngularVelocity = Vector3.Zero;
620 641
621 m_nextPosition = (Vector3)m_currentFrame.Position; 642 m_nextPosition = NormalizeVector(m_currentFrame.AngularVelocity);
622 m_group.AbsolutePosition = m_nextPosition; 643 m_group.AbsolutePosition = m_nextPosition;
623 644
624 // we are sending imediate updates, no doing force a extra terseUpdate 645 // we are sending imediate updates, no doing force a extra terseUpdate
@@ -706,7 +727,26 @@ namespace OpenSim.Region.Framework.Scenes
706 m_group.SendGroupRootTerseUpdate(); 727 m_group.SendGroupRootTerseUpdate();
707 } 728 }
708 } 729 }
730 private Vector3 NormalizeVector(Vector3? pPosition)
731 {
732 if (pPosition == null)
733 return Vector3.Zero;
734
735 Vector3 tmp = (Vector3) pPosition;
709 736
737 while (tmp.X > Constants.RegionSize)
738 tmp.X -= Constants.RegionSize;
739 while (tmp.X < 0)
740 tmp.X += Constants.RegionSize;
741 while (tmp.Y > Constants.RegionSize)
742 tmp.Y -= Constants.RegionSize;
743 while (tmp.Y < 0)
744 tmp.Y += Constants.RegionSize;
745
746 return tmp;
747
748
749 }
710 public Byte[] Serialize() 750 public Byte[] Serialize()
711 { 751 {
712 StopTimer(); 752 StopTimer();
diff --git a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
index c11174d..f208afb 100644
--- a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
+++ b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
@@ -46,47 +46,33 @@ using OpenSim.Region.Framework.Scenes;
46 46
47namespace OpenSim.Region.Framework.Scenes 47namespace OpenSim.Region.Framework.Scenes
48{ 48{
49 public class RegionStatsHandler : IStreamedRequestHandler 49 public class RegionStatsHandler : BaseStreamHandler
50 { 50 {
51 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 private string osRXStatsURI = String.Empty;
54 private string osXStatsURI = String.Empty; 53 private string osXStatsURI = String.Empty;
55 //private string osSecret = String.Empty; 54 //private string osSecret = String.Empty;
56 private OpenSim.Framework.RegionInfo regionInfo; 55 private OpenSim.Framework.RegionInfo regionInfo;
57 public string localZone = TimeZone.CurrentTimeZone.StandardName; 56 public string localZone = TimeZone.CurrentTimeZone.StandardName;
58 public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); 57 public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
59 58
60 public string Name { get { return "RegionStats"; } } 59 public RegionStatsHandler(RegionInfo region_info)
61 public string Description { get { return "Region Statistics"; } } 60 : base("GET", "/" + Util.SHA1Hash(region_info.regionSecret), "RegionStats", "Region Statistics")
62
63 public RegionStatsHandler(RegionInfo region_info)
64 { 61 {
65 regionInfo = region_info; 62 regionInfo = region_info;
66 osRXStatsURI = Util.SHA1Hash(regionInfo.regionSecret);
67 osXStatsURI = Util.SHA1Hash(regionInfo.osSecret); 63 osXStatsURI = Util.SHA1Hash(regionInfo.osSecret);
68 } 64 }
69 65
70 public byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 66 protected override byte[] ProcessRequest(
67 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
71 { 68 {
72 return Util.UTF8.GetBytes(Report()); 69 return Util.UTF8.GetBytes(Report());
73 } 70 }
74 71
75 public string ContentType 72 public override string ContentType
76 { 73 {
77 get { return "text/plain"; } 74 get { return "text/plain"; }
78 } 75 }
79
80 public string HttpMethod
81 {
82 get { return "GET"; }
83 }
84
85 public string Path
86 {
87 // This is for the region and is the regionSecret hashed
88 get { return "/" + osRXStatsURI; }
89 }
90 76
91 private string Report() 77 private string Report()
92 { 78 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index d2e41f8..cba75f1 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -31,6 +31,7 @@ using System.Collections;
31using System.Reflection; 31using System.Reflection;
32using System.Text; 32using System.Text;
33using System.Timers; 33using System.Timers;
34using System.Xml;
34using OpenMetaverse; 35using OpenMetaverse;
35using OpenMetaverse.Packets; 36using OpenMetaverse.Packets;
36using log4net; 37using log4net;
@@ -139,7 +140,7 @@ namespace OpenSim.Region.Framework.Scenes
139 { 140 {
140 userlevel = 1; 141 userlevel = 1;
141 } 142 }
142 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); 143 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel);
143 144
144 return true; 145 return true;
145 } 146 }
@@ -178,7 +179,7 @@ namespace OpenSim.Region.Framework.Scenes
178 { 179 {
179 userlevel = 1; 180 userlevel = 1;
180 } 181 }
181 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); 182 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel);
182 183
183 if (originalFolder != UUID.Zero) 184 if (originalFolder != UUID.Zero)
184 { 185 {
@@ -411,19 +412,21 @@ namespace OpenSim.Region.Framework.Scenes
411// itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags, 412// itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags,
412// item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions); 413// item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions);
413 414
415 bool sendUpdate = false;
416
414 if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid 417 if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid
415 { 418 {
416 // Create a set of base permissions that will not include export if the user 419 // Create a set of base permissions that will not include export if the user
417 // is not allowed to change the export flag. 420 // is not allowed to change the export flag.
418 bool denyExportChange = false; 421 bool denyExportChange = false;
419 422
420 m_log.InfoFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions); 423// m_log.DebugFormat("[XXX]: B: {0} O: {1} E: {2}", itemUpd.BasePermissions, itemUpd.CurrentPermissions, itemUpd.EveryOnePermissions);
421 424
422 // If the user is not the creator or doesn't have "E" in both "B" and "O", deny setting export 425 // If the user is not the creator or doesn't have "E" in both "B" and "O", deny setting export
423 if ((item.BasePermissions & (uint)(PermissionMask.All | PermissionMask.Export)) != (uint)(PermissionMask.All | PermissionMask.Export) || (item.CurrentPermissions & (uint)PermissionMask.Export) == 0 || item.CreatorIdAsUuid != item.Owner) 426 if ((item.BasePermissions & (uint)(PermissionMask.All | PermissionMask.Export)) != (uint)(PermissionMask.All | PermissionMask.Export) || (item.CurrentPermissions & (uint)PermissionMask.Export) == 0 || item.CreatorIdAsUuid != item.Owner)
424 denyExportChange = true; 427 denyExportChange = true;
425 428
426 m_log.InfoFormat("[XXX]: Deny Export Update {0}", denyExportChange); 429// m_log.DebugFormat("[XXX]: Deny Export Update {0}", denyExportChange);
427 430
428 // If it is already set, force it set and also force full perm 431 // If it is already set, force it set and also force full perm
429 // else prevent setting it. It can and should never be set unless 432 // else prevent setting it. It can and should never be set unless
@@ -447,7 +450,7 @@ namespace OpenSim.Region.Framework.Scenes
447 // If the new state is exportable, force full perm 450 // If the new state is exportable, force full perm
448 if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0) 451 if ((itemUpd.EveryOnePermissions & (uint)PermissionMask.Export) != 0)
449 { 452 {
450 m_log.InfoFormat("[XXX]: Force full perm"); 453// m_log.DebugFormat("[XXX]: Force full perm");
451 itemUpd.NextPermissions = (uint)(PermissionMask.All); 454 itemUpd.NextPermissions = (uint)(PermissionMask.All);
452 } 455 }
453 } 456 }
@@ -484,8 +487,13 @@ namespace OpenSim.Region.Framework.Scenes
484 item.SalePrice = itemUpd.SalePrice; 487 item.SalePrice = itemUpd.SalePrice;
485 item.SaleType = itemUpd.SaleType; 488 item.SaleType = itemUpd.SaleType;
486 489
490 if (item.InvType == (int)InventoryType.Wearable && (item.Flags & 0xf) == 0 && (itemUpd.Flags & 0xf) != 0)
491 {
492 item.Flags = (uint)(item.Flags & 0xfffffff0) | (itemUpd.Flags & 0xf);
493 sendUpdate = true;
494 }
495
487 InventoryService.UpdateItem(item); 496 InventoryService.UpdateItem(item);
488 remoteClient.SendBulkUpdateInventory(item);
489 } 497 }
490 498
491 if (UUID.Zero != transactionID) 499 if (UUID.Zero != transactionID)
@@ -495,6 +503,17 @@ namespace OpenSim.Region.Framework.Scenes
495 AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item); 503 AgentTransactionsModule.HandleItemUpdateFromTransaction(remoteClient, transactionID, item);
496 } 504 }
497 } 505 }
506 else
507 {
508 // This MAY be problematic, if it is, another solution
509 // needs to be found. If inventory item flags are updated
510 // the viewer's notion of the item needs to be refreshed.
511 //
512 // In other situations we cannot send out a bulk update here, since this will cause editing of clothing to start
513 // failing frequently. Possibly this is a race with a separate transaction that uploads the asset.
514 if (sendUpdate)
515 remoteClient.SendBulkUpdateInventory(item);
516 }
498 } 517 }
499 else 518 else
500 { 519 {
@@ -548,6 +567,9 @@ namespace OpenSim.Region.Framework.Scenes
548 { 567 {
549 //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem"); 568 //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem");
550 569
570 if (!Permissions.CanTransferUserInventory(itemId, senderId, recipient))
571 return null;
572
551 InventoryItemBase item = new InventoryItemBase(itemId, senderId); 573 InventoryItemBase item = new InventoryItemBase(itemId, senderId);
552 item = InventoryService.GetItem(item); 574 item = InventoryService.GetItem(item);
553 575
@@ -642,17 +664,13 @@ namespace OpenSim.Region.Framework.Scenes
642 // a mask 664 // a mask
643 if (item.InvType == (int)InventoryType.Object) 665 if (item.InvType == (int)InventoryType.Object)
644 { 666 {
645 // Create a safe mask for the current perms
646 uint foldedPerms = (item.CurrentPermissions & 7) << 13;
647 foldedPerms |= permsMask;
648
649 bool isRootMod = (item.CurrentPermissions & 667 bool isRootMod = (item.CurrentPermissions &
650 (uint)PermissionMask.Modify) != 0 ? 668 (uint)PermissionMask.Modify) != 0 ?
651 true : false; 669 true : false;
652 670
653 // Mask the owner perms to the folded perms 671 // Mask the owner perms to the folded perms
654 ownerPerms &= foldedPerms; 672 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref ownerPerms);
655 basePerms &= foldedPerms; 673 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref basePerms);
656 674
657 // If the root was mod, let the mask reflect that 675 // If the root was mod, let the mask reflect that
658 // We also need to adjust the base here, because 676 // We also need to adjust the base here, because
@@ -1213,9 +1231,16 @@ namespace OpenSim.Region.Framework.Scenes
1213 { 1231 {
1214 agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); 1232 agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move);
1215 if (taskItem.InvType == (int)InventoryType.Object) 1233 if (taskItem.InvType == (int)InventoryType.Object)
1216 agentItem.CurrentPermissions = agentItem.BasePermissions & (((taskItem.CurrentPermissions & 7) << 13) | (taskItem.CurrentPermissions & (uint)PermissionMask.Move)); 1234 {
1235 uint perms = taskItem.CurrentPermissions;
1236 PermissionsUtil.ApplyFoldedPermissions(taskItem.CurrentPermissions, ref perms);
1237 agentItem.BasePermissions = perms | (uint)PermissionMask.Move;
1238 agentItem.CurrentPermissions = agentItem.BasePermissions;
1239 }
1217 else 1240 else
1241 {
1218 agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions; 1242 agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions;
1243 }
1219 1244
1220 agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; 1245 agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
1221 agentItem.NextPermissions = taskItem.NextPermissions; 1246 agentItem.NextPermissions = taskItem.NextPermissions;
@@ -2124,7 +2149,10 @@ namespace OpenSim.Region.Framework.Scenes
2124 { 2149 {
2125 // If we don't have permission, stop right here 2150 // If we don't have permission, stop right here
2126 if (!permissionToTakeCopy) 2151 if (!permissionToTakeCopy)
2152 {
2153 remoteClient.SendAlertMessage("You don't have permission to take the object");
2127 return; 2154 return;
2155 }
2128 2156
2129 permissionToTake = true; 2157 permissionToTake = true;
2130 // Don't delete 2158 // Don't delete
@@ -2277,6 +2305,85 @@ namespace OpenSim.Region.Framework.Scenes
2277 } 2305 }
2278 2306
2279 /// <summary> 2307 /// <summary>
2308 /// Returns the list of Scene Objects in an asset.
2309 /// </summary>
2310 /// <remarks>
2311 /// Returns one object if the asset is a regular object, and multiple objects for a coalesced object.
2312 /// </remarks>
2313 /// <param name="assetData">Asset data</param>
2314 /// <param name="attachment">Whether the item is an attachment</param>
2315 /// <param name="objlist">The objects included in the asset</param>
2316 /// <param name="veclist">Relative positions of the objects</param>
2317 /// <param name="bbox">Bounding box of all the objects</param>
2318 /// <param name="offsetHeight">Offset in the Z axis from the centre of the bounding box
2319 /// to the centre of the root prim (relevant only when returning a single object)</param>
2320 /// <returns>true = returning a single object; false = multiple objects</returns>
2321 public bool GetObjectsToRez(byte[] assetData, bool attachment, out List<SceneObjectGroup> objlist, out List<Vector3> veclist,
2322 out Vector3 bbox, out float offsetHeight)
2323 {
2324 objlist = new List<SceneObjectGroup>();
2325 veclist = new List<Vector3>();
2326
2327 XmlDocument doc = new XmlDocument();
2328 string xmlData = Utils.BytesToString(assetData);
2329 doc.LoadXml(xmlData);
2330 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
2331
2332 if (e == null || attachment) // Single
2333 {
2334 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
2335
2336 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2337 g.RootPart.AttachOffset = g.AbsolutePosition;
2338 g.RootPart.AttachRotation = g.GroupRotation;
2339 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2340 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2341 g.RootPart.Shape.State = 0;
2342
2343 objlist.Add(g);
2344 veclist.Add(new Vector3(0, 0, 0));
2345 bbox = g.GetAxisAlignedBoundingBox(out offsetHeight);
2346 return true;
2347 }
2348 else
2349 {
2350 XmlElement coll = (XmlElement)e;
2351 float bx = Convert.ToSingle(coll.GetAttribute("x"));
2352 float by = Convert.ToSingle(coll.GetAttribute("y"));
2353 float bz = Convert.ToSingle(coll.GetAttribute("z"));
2354 bbox = new Vector3(bx, by, bz);
2355 offsetHeight = 0;
2356
2357 XmlNodeList groups = e.SelectNodes("SceneObjectGroup");
2358 foreach (XmlNode n in groups)
2359 {
2360 SceneObjectGroup g = SceneObjectSerializer.FromOriginalXmlFormat(n.OuterXml);
2361
2362 g.RootPart.AttachPoint = g.RootPart.Shape.State;
2363 g.RootPart.AttachOffset = g.AbsolutePosition;
2364 g.RootPart.AttachRotation = g.GroupRotation;
2365 if (g.RootPart.Shape.PCode != (byte)PCode.NewTree &&
2366 g.RootPart.Shape.PCode != (byte)PCode.Tree)
2367 g.RootPart.Shape.State = 0;
2368
2369 objlist.Add(g);
2370
2371 XmlElement el = (XmlElement)n;
2372 string rawX = el.GetAttribute("offsetx");
2373 string rawY = el.GetAttribute("offsety");
2374 string rawZ = el.GetAttribute("offsetz");
2375
2376 float x = Convert.ToSingle(rawX);
2377 float y = Convert.ToSingle(rawY);
2378 float z = Convert.ToSingle(rawZ);
2379 veclist.Add(new Vector3(x, y, z));
2380 }
2381 }
2382
2383 return false;
2384 }
2385
2386 /// <summary>
2280 /// Event Handler Rez an object into a scene 2387 /// Event Handler Rez an object into a scene
2281 /// Calls the non-void event handler 2388 /// Calls the non-void event handler
2282 /// </summary> 2389 /// </summary>
@@ -2351,19 +2458,25 @@ namespace OpenSim.Region.Framework.Scenes
2351 /// will be used if it exists.</param> 2458 /// will be used if it exists.</param>
2352 /// <param name="vel">The velocity of the rezzed object.</param> 2459 /// <param name="vel">The velocity of the rezzed object.</param>
2353 /// <param name="param"></param> 2460 /// <param name="param"></param>
2354 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> 2461 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2355 public virtual SceneObjectGroup RezObject( 2462 public virtual List<SceneObjectGroup> RezObject(
2356 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) 2463 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param)
2357 { 2464 {
2358 if (null == item) 2465 if (null == item)
2359 return null; 2466 return null;
2467
2468 List<SceneObjectGroup> objlist;
2469 List<Vector3> veclist;
2360 2470
2361 SceneObjectGroup group = sourcePart.Inventory.GetRezReadySceneObject(item); 2471 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist);
2362 2472 if (!success)
2363 if (null == group)
2364 return null; 2473 return null;
2365 2474
2366 if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos)) 2475 int totalPrims = 0;
2476 foreach (SceneObjectGroup group in objlist)
2477 totalPrims += group.PrimCount;
2478
2479 if (!Permissions.CanRezObject(totalPrims, item.OwnerID, pos))
2367 return null; 2480 return null;
2368 2481
2369 if (!Permissions.BypassPermissions()) 2482 if (!Permissions.BypassPermissions())
@@ -2372,16 +2485,28 @@ namespace OpenSim.Region.Framework.Scenes
2372 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2485 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2373 } 2486 }
2374 2487
2375 group.FromPartID = sourcePart.UUID; 2488 for (int i = 0; i < objlist.Count; i++)
2376 AddNewSceneObject(group, true, pos, rot, vel); 2489 {
2377 2490 SceneObjectGroup group = objlist[i];
2378 // We can only call this after adding the scene object, since the scene object references the scene 2491 Vector3 curpos = pos + veclist[i];
2379 // to find out if scripts should be activated at all. 2492
2380 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); 2493 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2381 2494 {
2382 group.ScheduleGroupForFullUpdate(); 2495 group.RootPart.AttachedPos = group.AbsolutePosition;
2383 2496 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
2384 return group; 2497 }
2498
2499 group.FromPartID = sourcePart.UUID;
2500 AddNewSceneObject(group, true, curpos, rot, vel);
2501
2502 // We can only call this after adding the scene object, since the scene object references the scene
2503 // to find out if scripts should be activated at all.
2504 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2505
2506 group.ScheduleGroupForFullUpdate();
2507 }
2508
2509 return objlist;
2385 } 2510 }
2386 2511
2387 public virtual bool returnObjects(SceneObjectGroup[] returnobjects, 2512 public virtual bool returnObjects(SceneObjectGroup[] returnobjects,
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index ce6415a..46b2d2e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -252,8 +252,6 @@ namespace OpenSim.Region.Framework.Scenes
252 if (part.ParentGroup.RootPart.LocalId != part.LocalId) 252 if (part.ParentGroup.RootPart.LocalId != part.LocalId)
253 return; 253 return;
254 254
255 bool isAttachment = false;
256
257 // This is wrong, wrong, wrong. Selection should not be 255 // This is wrong, wrong, wrong. Selection should not be
258 // handled by group, but by prim. Legacy cruft. 256 // handled by group, but by prim. Legacy cruft.
259 // TODO: Make selection flagging per prim! 257 // TODO: Make selection flagging per prim!
@@ -262,17 +260,14 @@ namespace OpenSim.Region.Framework.Scenes
262 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId)) 260 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
263 part.ParentGroup.IsSelected = false; 261 part.ParentGroup.IsSelected = false;
264 262
265 if (part.ParentGroup.IsAttachment) 263 part.ParentGroup.ScheduleGroupForFullUpdate();
266 isAttachment = true;
267 else
268 part.ParentGroup.ScheduleGroupForFullUpdate();
269 264
270 // If it's not an attachment, and we are allowed to move it, 265 // If it's not an attachment, and we are allowed to move it,
271 // then we might have done so. If we moved across a parcel 266 // then we might have done so. If we moved across a parcel
272 // boundary, we will need to recount prims on the parcels. 267 // boundary, we will need to recount prims on the parcels.
273 // For attachments, that makes no sense. 268 // For attachments, that makes no sense.
274 // 269 //
275 if (!isAttachment) 270 if (!part.ParentGroup.IsAttachment)
276 { 271 {
277 if (Permissions.CanEditObject( 272 if (Permissions.CanEditObject(
278 part.UUID, remoteClient.AgentId) 273 part.UUID, remoteClient.AgentId)
@@ -416,6 +411,7 @@ namespace OpenSim.Region.Framework.Scenes
416 void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args) 411 void ProcessViewerEffect(IClientAPI remoteClient, List<ViewerEffectEventHandlerArg> args)
417 { 412 {
418 // TODO: don't create new blocks if recycling an old packet 413 // TODO: don't create new blocks if recycling an old packet
414 bool discardableEffects = true;
419 ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count]; 415 ViewerEffectPacket.EffectBlock[] effectBlockArray = new ViewerEffectPacket.EffectBlock[args.Count];
420 for (int i = 0; i < args.Count; i++) 416 for (int i = 0; i < args.Count; i++)
421 { 417 {
@@ -427,17 +423,34 @@ namespace OpenSim.Region.Framework.Scenes
427 effect.Type = args[i].Type; 423 effect.Type = args[i].Type;
428 effect.TypeData = args[i].TypeData; 424 effect.TypeData = args[i].TypeData;
429 effectBlockArray[i] = effect; 425 effectBlockArray[i] = effect;
426
427 if ((EffectType)effect.Type != EffectType.LookAt && (EffectType)effect.Type != EffectType.Beam)
428 discardableEffects = false;
429
430 //m_log.DebugFormat("[YYY]: VE {0} {1} {2}", effect.AgentID, effect.Duration, (EffectType)effect.Type);
430 } 431 }
431 432
432 ForEachClient( 433 ForEachScenePresence(sp =>
433 delegate(IClientAPI client)
434 { 434 {
435 if (client.AgentId != remoteClient.AgentId) 435 if (sp.ControllingClient.AgentId != remoteClient.AgentId)
436 client.SendViewerEffect(effectBlockArray); 436 {
437 } 437 if (!discardableEffects ||
438 ); 438 (discardableEffects && ShouldSendDiscardableEffect(remoteClient, sp)))
439 {
440 //m_log.DebugFormat("[YYY]: Sending to {0}", sp.UUID);
441 sp.ControllingClient.SendViewerEffect(effectBlockArray);
442 }
443 //else
444 // m_log.DebugFormat("[YYY]: Not sending to {0}", sp.UUID);
445 }
446 });
439 } 447 }
440 448
449 private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other)
450 {
451 return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10;
452 }
453
441 private class DescendentsRequestData 454 private class DescendentsRequestData
442 { 455 {
443 public IClientAPI RemoteClient; 456 public IClientAPI RemoteClient;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index b189599..55766cf 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -151,7 +151,7 @@ namespace OpenSim.Region.Framework.Scenes
151 public SynchronizeSceneHandler SynchronizeScene; 151 public SynchronizeSceneHandler SynchronizeScene;
152 152
153 /// <summary> 153 /// <summary>
154 /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. 154 /// Used to prevent simultaneous calls to code that adds and removes agents.
155 /// </summary> 155 /// </summary>
156 private object m_removeClientLock = new object(); 156 private object m_removeClientLock = new object();
157 157
@@ -230,6 +230,8 @@ namespace OpenSim.Region.Framework.Scenes
230 public bool m_seeIntoBannedRegion = false; 230 public bool m_seeIntoBannedRegion = false;
231 public int MaxUndoCount = 5; 231 public int MaxUndoCount = 5;
232 232
233 public bool SeeIntoRegion { get; set; }
234
233 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 235 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
234 public bool LoginLock = false; 236 public bool LoginLock = false;
235 237
@@ -396,10 +398,12 @@ namespace OpenSim.Region.Framework.Scenes
396 if (value) 398 if (value)
397 { 399 {
398 if (!m_active) 400 if (!m_active)
399 Start(); 401 Start(false);
400 } 402 }
401 else 403 else
402 { 404 {
405 // This appears assymetric with Start() above but is not - setting m_active = false stops the loops
406 // XXX: Possibly this should be in an explicit Stop() method for symmetry.
403 m_active = false; 407 m_active = false;
404 } 408 }
405 } 409 }
@@ -747,6 +751,7 @@ namespace OpenSim.Region.Framework.Scenes
747 m_config = config; 751 m_config = config;
748 MinFrameTime = 0.089f; 752 MinFrameTime = 0.089f;
749 MinMaintenanceTime = 1; 753 MinMaintenanceTime = 1;
754 SeeIntoRegion = true;
750 755
751 Random random = new Random(); 756 Random random = new Random();
752 757
@@ -859,9 +864,12 @@ namespace OpenSim.Region.Framework.Scenes
859 //Animation states 864 //Animation states
860 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 865 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
861 866
867 SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion);
868
869 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
870
862 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 871 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
863 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 872 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
864
865 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 873 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
866 if (RegionInfo.NonphysPrimMin > 0) 874 if (RegionInfo.NonphysPrimMin > 0)
867 { 875 {
@@ -1332,7 +1340,7 @@ namespace OpenSim.Region.Framework.Scenes
1332 Thread.Sleep(500); 1340 Thread.Sleep(500);
1333 1341
1334 // Stop all client threads. 1342 // Stop all client threads.
1335 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); 1343 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
1336 1344
1337 m_log.Debug("[SCENE]: TriggerSceneShuttingDown"); 1345 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1338 EventManager.TriggerSceneShuttingDown(this); 1346 EventManager.TriggerSceneShuttingDown(this);
@@ -1361,10 +1369,18 @@ namespace OpenSim.Region.Framework.Scenes
1361 } 1369 }
1362 } 1370 }
1363 1371
1372 public override void Start()
1373 {
1374 Start(true);
1375 }
1376
1364 /// <summary> 1377 /// <summary>
1365 /// Start the scene 1378 /// Start the scene
1366 /// </summary> 1379 /// </summary>
1367 public void Start() 1380 /// <param name='startScripts'>
1381 /// Start the scripts within the scene.
1382 /// </param>
1383 public void Start(bool startScripts)
1368 { 1384 {
1369 m_active = true; 1385 m_active = true;
1370 1386
@@ -1401,6 +1417,8 @@ namespace OpenSim.Region.Framework.Scenes
1401 m_heartbeatThread 1417 m_heartbeatThread
1402 = Watchdog.StartThread( 1418 = Watchdog.StartThread(
1403 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false); 1419 Heartbeat, string.Format("Heartbeat ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, false);
1420
1421 StartScripts();
1404 } 1422 }
1405 1423
1406 /// <summary> 1424 /// <summary>
@@ -1557,6 +1575,8 @@ namespace OpenSim.Region.Framework.Scenes
1557 1575
1558 try 1576 try
1559 { 1577 {
1578 EventManager.TriggerRegionHeartbeatStart(this);
1579
1560 // Apply taints in terrain module to terrain in physics scene 1580 // Apply taints in terrain module to terrain in physics scene
1561 if (Frame % m_update_terrain == 0) 1581 if (Frame % m_update_terrain == 0)
1562 { 1582 {
@@ -1996,6 +2016,11 @@ namespace OpenSim.Region.Framework.Scenes
1996 2016
1997 GridRegion region = new GridRegion(RegionInfo); 2017 GridRegion region = new GridRegion(RegionInfo);
1998 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 2018 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
2019 m_log.DebugFormat("{0} RegisterRegionWithGrid. name={1},id={2},loc=<{3},{4}>,size=<{5},{6}>",
2020 LogHeader, m_regionName,
2021 RegionInfo.RegionID,
2022 RegionInfo.RegionLocX, RegionInfo.RegionLocY,
2023 RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
1999 if (error != String.Empty) 2024 if (error != String.Empty)
2000 throw new Exception(error); 2025 throw new Exception(error);
2001 } 2026 }
@@ -2935,14 +2960,15 @@ namespace OpenSim.Region.Framework.Scenes
2935 2960
2936 #region Add/Remove Avatar Methods 2961 #region Add/Remove Avatar Methods
2937 2962
2938 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 2963 public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type)
2939 { 2964 {
2940 ScenePresence sp; 2965 ScenePresence sp;
2941 bool vialogin; 2966 bool vialogin;
2967 bool reallyNew = true;
2942 2968
2943 // Validation occurs in LLUDPServer 2969 // Validation occurs in LLUDPServer
2944 // 2970 //
2945 // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with 2971 // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with
2946 // each other. In practice, this does not currently occur in the code. 2972 // each other. In practice, this does not currently occur in the code.
2947 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); 2973 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
2948 2974
@@ -2950,9 +2976,9 @@ namespace OpenSim.Region.Framework.Scenes
2950 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point 2976 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point
2951 // whilst connecting). 2977 // whilst connecting).
2952 // 2978 //
2953 // It would be easier to lock across all NewUserConnection(), AddNewClient() and 2979 // It would be easier to lock across all NewUserConnection(), AddNewAgent() and
2954 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service 2980 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
2955 // response in some module listening to AddNewClient()) from holding up unrelated agent calls. 2981 // response in some module listening to AddNewAgent()) from holding up unrelated agent calls.
2956 // 2982 //
2957 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all 2983 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
2958 // AddNewClient() operations (though not other ops). 2984 // AddNewClient() operations (though not other ops).
@@ -2969,7 +2995,7 @@ namespace OpenSim.Region.Framework.Scenes
2969 2995
2970 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this 2996 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
2971 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause 2997 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
2972 // other problems, and possible the code calling AddNewClient() should ensure that no client is already 2998 // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already
2973 // connected. 2999 // connected.
2974 if (sp == null) 3000 if (sp == null)
2975 { 3001 {
@@ -2997,16 +3023,24 @@ namespace OpenSim.Region.Framework.Scenes
2997 m_log.WarnFormat( 3023 m_log.WarnFormat(
2998 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 3024 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
2999 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); 3025 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
3026 reallyNew = false;
3000 } 3027 }
3001 3028
3002 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 3029 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
3003 // client is for a root or child agent. 3030 // client is for a root or child agent.
3031 // XXX: This may be better set for a new client before that client is added to the client manager.
3032 // But need to know what happens in the case where a ScenePresence is already present (and if this
3033 // actually occurs).
3004 client.SceneAgent = sp; 3034 client.SceneAgent = sp;
3005 3035
3006 // Cache the user's name 3036 // This is currently also being done earlier in NewUserConnection for real users to see if this
3037 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other
3038 // places. However, we still need to do it here for NPCs.
3007 CacheUserName(sp, aCircuit); 3039 CacheUserName(sp, aCircuit);
3008 3040
3009 EventManager.TriggerOnNewClient(client); 3041 if (reallyNew)
3042 EventManager.TriggerOnNewClient(client);
3043
3010 if (vialogin) 3044 if (vialogin)
3011 EventManager.TriggerOnClientLogin(client); 3045 EventManager.TriggerOnClientLogin(client);
3012 } 3046 }
@@ -3027,7 +3061,7 @@ namespace OpenSim.Region.Framework.Scenes
3027 { 3061 {
3028 string first = aCircuit.firstname, last = aCircuit.lastname; 3062 string first = aCircuit.firstname, last = aCircuit.lastname;
3029 3063
3030 if (sp.PresenceType == PresenceType.Npc) 3064 if (sp != null && sp.PresenceType == PresenceType.Npc)
3031 { 3065 {
3032 UserManagementModule.AddUser(aCircuit.AgentID, first, last); 3066 UserManagementModule.AddUser(aCircuit.AgentID, first, last);
3033 } 3067 }
@@ -3105,7 +3139,8 @@ namespace OpenSim.Region.Framework.Scenes
3105 if (sp != null) 3139 if (sp != null)
3106 { 3140 {
3107 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3141 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3108 sp.ControllingClient.Close(); 3142
3143 CloseAgent(sp.UUID, false);
3109 } 3144 }
3110 3145
3111 // BANG! SLASH! 3146 // BANG! SLASH!
@@ -3244,8 +3279,6 @@ namespace OpenSim.Region.Framework.Scenes
3244 { 3279 {
3245 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest; 3280 //client.OnNameFromUUIDRequest += HandleUUIDNameRequest;
3246 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest; 3281 client.OnMoneyTransferRequest += ProcessMoneyTransferRequest;
3247 client.OnSetStartLocationRequest += SetHomeRezPoint;
3248 client.OnRegionHandleRequest += RegionHandleRequest;
3249 } 3282 }
3250 3283
3251 public virtual void SubscribeToClientNetworkEvents(IClientAPI client) 3284 public virtual void SubscribeToClientNetworkEvents(IClientAPI client)
@@ -3371,8 +3404,6 @@ namespace OpenSim.Region.Framework.Scenes
3371 { 3404 {
3372 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest; 3405 //client.OnNameFromUUIDRequest -= HandleUUIDNameRequest;
3373 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest; 3406 client.OnMoneyTransferRequest -= ProcessMoneyTransferRequest;
3374 client.OnSetStartLocationRequest -= SetHomeRezPoint;
3375 client.OnRegionHandleRequest -= RegionHandleRequest;
3376 } 3407 }
3377 3408
3378 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client) 3409 public virtual void UnSubscribeToClientNetworkEvents(IClientAPI client)
@@ -3498,33 +3529,6 @@ namespace OpenSim.Region.Framework.Scenes
3498 } 3529 }
3499 3530
3500 /// <summary> 3531 /// <summary>
3501 /// Sets the Home Point. The LoginService uses this to know where to put a user when they log-in
3502 /// </summary>
3503 /// <param name="remoteClient"></param>
3504 /// <param name="regionHandle"></param>
3505 /// <param name="position"></param>
3506 /// <param name="lookAt"></param>
3507 /// <param name="flags"></param>
3508 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3509 {
3510 //Add half the avatar's height so that the user doesn't fall through prims
3511 ScenePresence presence;
3512 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3513 {
3514 if (presence.Appearance != null)
3515 {
3516 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3517 }
3518 }
3519
3520 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3521 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3522 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
3523 else
3524 m_dialogModule.SendAlertToUser(remoteClient, "Set Home request Failed.");
3525 }
3526
3527 /// <summary>
3528 /// Get the avatar apperance for the given client. 3532 /// Get the avatar apperance for the given client.
3529 /// </summary> 3533 /// </summary>
3530 /// <param name="client"></param> 3534 /// <param name="client"></param>
@@ -3548,63 +3552,69 @@ namespace OpenSim.Region.Framework.Scenes
3548 } 3552 }
3549 } 3553 }
3550 3554
3551 public override void RemoveClient(UUID agentID, bool closeChildAgents) 3555 /// <summary>
3556 /// Remove the given client from the scene.
3557 /// </summary>
3558 /// <remarks>
3559 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead
3560 /// to properly operate the state machine and avoid race conditions with other close requests (such as directly
3561 /// from viewers).
3562 /// </remarks>
3563 /// <param name='agentID'>ID of agent to close</param>
3564 /// <param name='closeChildAgents'>
3565 /// Close the neighbour child agents associated with this client.
3566 /// </param>
3567 public void RemoveClient(UUID agentID, bool closeChildAgents)
3552 { 3568 {
3553// CheckHeartbeat(); 3569 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3554 bool isChildAgent = false;
3555 AgentCircuitData acd;
3556 3570
3557 lock (m_removeClientLock) 3571 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3572 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3573 // However, will keep for now just in case.
3574 if (acd == null)
3558 { 3575 {
3559 acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3576 m_log.ErrorFormat(
3577 "[SCENE]: No agent circuit found for {0} in {1}, aborting Scene.RemoveClient", agentID, Name);
3560 3578
3561 if (acd == null) 3579 return;
3562 { 3580 }
3563 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); 3581 else
3564 return; 3582 {
3565 } 3583 m_authenticateHandler.RemoveCircuit(agentID);
3566 else
3567 {
3568 // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
3569 // simultaneously.
3570 // We also need to remove by agent ID since NPCs will have no circuit code.
3571 m_authenticateHandler.RemoveCircuit(agentID);
3572 }
3573 } 3584 }
3574 3585
3586 // TODO: Can we now remove this lock?
3575 lock (acd) 3587 lock (acd)
3576 { 3588 {
3589 bool isChildAgent = false;
3590
3577 ScenePresence avatar = GetScenePresence(agentID); 3591 ScenePresence avatar = GetScenePresence(agentID);
3578 3592
3593 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3594 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3595 // However, will keep for now just in case.
3579 if (avatar == null) 3596 if (avatar == null)
3580 { 3597 {
3581 m_log.WarnFormat( 3598 m_log.ErrorFormat(
3582 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); 3599 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3583 3600
3584 return; 3601 return;
3585 } 3602 }
3586 3603
3587 try 3604 try
3588 { 3605 {
3589 isChildAgent = avatar.IsChildAgent; 3606 isChildAgent = avatar.IsChildAgent;
3590 3607
3591 m_log.DebugFormat( 3608 m_log.DebugFormat(
3592 "[SCENE]: Removing {0} agent {1} {2} from {3}", 3609 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3593 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); 3610 isChildAgent ? "child" : "root", avatar.Name, agentID, Name);
3594 3611
3595 // Don't do this to root agents, it's not nice for the viewer 3612 // Don't do this to root agents, it's not nice for the viewer
3596 if (closeChildAgents && isChildAgent) 3613 if (closeChildAgents && isChildAgent)
3597 { 3614 {
3598 // Tell a single agent to disconnect from the region. 3615 // Tell a single agent to disconnect from the region.
3599 IEventQueue eq = RequestModuleInterface<IEventQueue>(); 3616 // Let's do this via UDP
3600 if (eq != null) 3617 avatar.ControllingClient.SendShutdownConnectionNotice();
3601 {
3602 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3603 }
3604 else
3605 {
3606 avatar.ControllingClient.SendShutdownConnectionNotice();
3607 }
3608 } 3618 }
3609 3619
3610 // Only applies to root agents. 3620 // Only applies to root agents.
@@ -3620,16 +3630,13 @@ namespace OpenSim.Region.Framework.Scenes
3620 if (closeChildAgents && CapsModule != null) 3630 if (closeChildAgents && CapsModule != null)
3621 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode); 3631 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
3622 3632
3623// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3624// // this method is doing is HORRIBLE!!!
3625 // Commented pending deletion since this method no longer appears to do anything at all
3626// avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3627
3628 if (closeChildAgents && !isChildAgent) 3633 if (closeChildAgents && !isChildAgent)
3629 { 3634 {
3630 List<ulong> regions = avatar.KnownRegionHandles; 3635 List<ulong> regions = avatar.KnownRegionHandles;
3631 regions.Remove(RegionInfo.RegionHandle); 3636 regions.Remove(RegionInfo.RegionHandle);
3632 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3637
3638 // This ends up being done asynchronously so that a logout isn't held up where there are many present but unresponsive neighbours.
3639 m_sceneGridService.SendCloseChildAgentConnections(agentID, acd.SessionID.ToString(), regions);
3633 } 3640 }
3634 3641
3635 m_eventManager.TriggerClientClosed(agentID, this); 3642 m_eventManager.TriggerClientClosed(agentID, this);
@@ -3646,7 +3653,7 @@ namespace OpenSim.Region.Framework.Scenes
3646 delegate(IClientAPI client) 3653 delegate(IClientAPI client)
3647 { 3654 {
3648 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3655 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3649 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } 3656 try { client.SendKillObject(new List<uint> { avatar.LocalId }); }
3650 catch (NullReferenceException) { } 3657 catch (NullReferenceException) { }
3651 }); 3658 });
3652 } 3659 }
@@ -3727,7 +3734,8 @@ namespace OpenSim.Region.Framework.Scenes
3727 } 3734 }
3728 deleteIDs.Add(localID); 3735 deleteIDs.Add(localID);
3729 } 3736 }
3730 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); }); 3737
3738 ForEachClient(c => c.SendKillObject(deleteIDs));
3731 } 3739 }
3732 3740
3733 #endregion 3741 #endregion
@@ -3763,13 +3771,13 @@ namespace OpenSim.Region.Framework.Scenes
3763 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of 3771 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3764 /// the LLUDP stack). 3772 /// the LLUDP stack).
3765 /// </remarks> 3773 /// </remarks>
3766 /// <param name="agent">CircuitData of the agent who is connecting</param> 3774 /// <param name="acd">CircuitData of the agent who is connecting</param>
3767 /// <param name="reason">Outputs the reason for the false response on this string</param> 3775 /// <param name="reason">Outputs the reason for the false response on this string</param>
3768 /// <param name="requirePresenceLookup">True for normal presence. False for NPC 3776 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
3769 /// or other applications where a full grid/Hypergrid presence may not be required.</param> 3777 /// or other applications where a full grid/Hypergrid presence may not be required.</param>
3770 /// <returns>True if the region accepts this agent. False if it does not. False will 3778 /// <returns>True if the region accepts this agent. False if it does not. False will
3771 /// also return a reason.</returns> 3779 /// also return a reason.</returns>
3772 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason, bool requirePresenceLookup) 3780 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, out string reason, bool requirePresenceLookup)
3773 { 3781 {
3774 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3782 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3775 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3783 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
@@ -3789,15 +3797,15 @@ namespace OpenSim.Region.Framework.Scenes
3789 m_log.DebugFormat( 3797 m_log.DebugFormat(
3790 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})", 3798 "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags ({8}), position {9})",
3791 RegionInfo.RegionName, 3799 RegionInfo.RegionName,
3792 (agent.child ? "child" : "root"), 3800 (acd.child ? "child" : "root"),
3793 agent.firstname, 3801 acd.firstname,
3794 agent.lastname, 3802 acd.lastname,
3795 agent.AgentID, 3803 acd.AgentID,
3796 agent.circuitcode, 3804 acd.circuitcode,
3797 agent.IPAddress, 3805 acd.IPAddress,
3798 agent.Viewer, 3806 acd.Viewer,
3799 ((TPFlags)teleportFlags).ToString(), 3807 ((TPFlags)teleportFlags).ToString(),
3800 agent.startpos 3808 acd.startpos
3801 ); 3809 );
3802 3810
3803 if (!LoginsEnabled) 3811 if (!LoginsEnabled)
@@ -3815,7 +3823,7 @@ namespace OpenSim.Region.Framework.Scenes
3815 { 3823 {
3816 foreach (string viewer in m_AllowedViewers) 3824 foreach (string viewer in m_AllowedViewers)
3817 { 3825 {
3818 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3826 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3819 { 3827 {
3820 ViewerDenied = false; 3828 ViewerDenied = false;
3821 break; 3829 break;
@@ -3832,7 +3840,7 @@ namespace OpenSim.Region.Framework.Scenes
3832 { 3840 {
3833 foreach (string viewer in m_BannedViewers) 3841 foreach (string viewer in m_BannedViewers)
3834 { 3842 {
3835 if (viewer == agent.Viewer.Substring(0, viewer.Length).Trim().ToLower()) 3843 if (viewer == acd.Viewer.Substring(0, viewer.Length).Trim().ToLower())
3836 { 3844 {
3837 ViewerDenied = true; 3845 ViewerDenied = true;
3838 break; 3846 break;
@@ -3844,54 +3852,129 @@ namespace OpenSim.Region.Framework.Scenes
3844 { 3852 {
3845 m_log.DebugFormat( 3853 m_log.DebugFormat(
3846 "[SCENE]: Access denied for {0} {1} using {2}", 3854 "[SCENE]: Access denied for {0} {1} using {2}",
3847 agent.firstname, agent.lastname, agent.Viewer); 3855 acd.firstname, acd.lastname, acd.Viewer);
3848 reason = "Access denied, your viewer is banned by the region owner"; 3856 reason = "Access denied, your viewer is banned by the region owner";
3849 return false; 3857 return false;
3850 } 3858 }
3851 3859
3852 ScenePresence sp = GetScenePresence(agent.AgentID); 3860 ILandObject land;
3861 ScenePresence sp;
3853 3862
3854 // If we have noo presence here or if that presence is a zombie root 3863 lock (m_removeClientLock)
3855 // presence that will be kicled, we need a new CAPS object.
3856 if (sp == null || (sp != null && !sp.IsChildAgent))
3857 { 3864 {
3858 if (CapsModule != null) 3865 sp = GetScenePresence(acd.AgentID);
3866
3867 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3868 // closed.
3869 if (sp != null && sp.IsChildAgent
3870 && (sp.LifecycleState == ScenePresenceState.Running
3871 || sp.LifecycleState == ScenePresenceState.PreRemove))
3859 { 3872 {
3860 lock (agent) 3873 m_log.DebugFormat(
3874 "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}",
3875 sp.Name, sp.LifecycleState, Name);
3876
3877 // In the case where, for example, an A B C D region layout, an avatar may
3878 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
3879 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed.
3880 //
3881 // XXX: In the end, this should not be necessary if child agents are closed without delay on
3882 // teleport, since realistically, the close request should always be processed before any other
3883 // region tried to re-establish a child agent. This is much simpler since the logic below is
3884 // vulnerable to an issue when a viewer quits a region without sending a proper logout but then
3885 // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport
3886 // flag when no teleport had taken place (and hence no close was going to come).
3887// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle))
3888// {
3889// m_log.DebugFormat(
3890// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.",
3891// sp.Name, Name);
3892//
3893// sp.DoNotCloseAfterTeleport = true;
3894// }
3895// else if (EntityTransferModule.IsInTransit(sp.UUID))
3896
3897 sp.LifecycleState = ScenePresenceState.Running;
3898
3899 if (EntityTransferModule.IsInTransit(sp.UUID))
3861 { 3900 {
3862 CapsModule.SetAgentCapsSeeds(agent); 3901 sp.DoNotCloseAfterTeleport = true;
3863 CapsModule.CreateCaps(agent.AgentID, agent.circuitcode); 3902
3903 m_log.DebugFormat(
3904 "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.",
3905 sp.Name, Name);
3864 } 3906 }
3865 } 3907 }
3866 } 3908 }
3867 3909
3910 // Need to poll here in case we are currently deleting an sp. Letting threads run over each other will
3911 // allow unpredictable things to happen.
3868 if (sp != null) 3912 if (sp != null)
3869 { 3913 {
3870 if (!sp.IsChildAgent) 3914 const int polls = 10;
3915 const int pollInterval = 1000;
3916 int pollsLeft = polls;
3917
3918 while (sp.LifecycleState == ScenePresenceState.Removing && pollsLeft-- > 0)
3919 Thread.Sleep(pollInterval);
3920
3921 if (sp.LifecycleState == ScenePresenceState.Removing)
3871 { 3922 {
3872 // We have a zombie from a crashed session.
3873 // Or the same user is trying to be root twice here, won't work.
3874 // Kill it.
3875 m_log.WarnFormat( 3923 m_log.WarnFormat(
3876 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3924 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.",
3877 sp.Name, sp.UUID, RegionInfo.RegionName); 3925 sp.Name, Name, polls * pollInterval / 1000);
3878 3926
3879 sp.ControllingClient.Close(true, true); 3927 return false;
3880 sp = null; 3928 }
3929 else if (polls != pollsLeft)
3930 {
3931 m_log.DebugFormat(
3932 "[SCENE]: NewUserConnection for agent {0} in {1} had to wait {2}s for in-progress removal to complete on an old presence.",
3933 sp.Name, Name, polls * pollInterval / 1000);
3881 } 3934 }
3882 } 3935 }
3883 3936
3884 lock (agent) 3937 // TODO: can we remove this lock?
3938 lock (acd)
3885 { 3939 {
3886 //On login test land permisions 3940 if (sp != null && !sp.IsChildAgent)
3941 {
3942 // We have a root agent. Is it in transit?
3943 if (!EntityTransferModule.IsInTransit(sp.UUID))
3944 {
3945 // We have a zombie from a crashed session.
3946 // Or the same user is trying to be root twice here, won't work.
3947 // Kill it.
3948 m_log.WarnFormat(
3949 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3950 sp.Name, sp.UUID, RegionInfo.RegionName);
3951
3952 if (sp.ControllingClient != null)
3953 CloseAgent(sp.UUID, true);
3954
3955 sp = null;
3956 }
3957 //else
3958 // m_log.WarnFormat("[SCENE]: Existing root scene presence for {0} {1} in {2}, but agent is in trasit", sp.Name, sp.UUID, RegionInfo.RegionName);
3959 }
3960
3961 // Optimistic: add or update the circuit data with the new agent circuit data and teleport flags.
3962 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3963 // If the checks fail, we remove the circuit.
3964 acd.teleportFlags = teleportFlags;
3965 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3966
3967 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
3968
3969 // On login test land permisions
3887 if (vialogin) 3970 if (vialogin)
3888 { 3971 {
3889 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 3972 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3890 if (cache != null) 3973 if (cache != null)
3891 cache.Remove(agent.firstname + " " + agent.lastname); 3974 cache.Remove(acd.firstname + " " + acd.lastname);
3892 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) 3975 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y))
3893 { 3976 {
3894 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); 3977 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3895 return false; 3978 return false;
3896 } 3979 }
3897 } 3980 }
@@ -3902,84 +3985,97 @@ namespace OpenSim.Region.Framework.Scenes
3902 { 3985 {
3903 try 3986 try
3904 { 3987 {
3905 if (!VerifyUserPresence(agent, out reason)) 3988 if (!VerifyUserPresence(acd, out reason))
3989 {
3990 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3906 return false; 3991 return false;
3907 } catch (Exception e) 3992 }
3993 }
3994 catch (Exception e)
3908 { 3995 {
3909 m_log.ErrorFormat( 3996 m_log.ErrorFormat(
3910 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 3997 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
3998
3999 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3911 return false; 4000 return false;
3912 } 4001 }
3913 } 4002 }
3914 4003
3915 try 4004 try
3916 { 4005 {
3917 // Always check estate if this is a login. Always 4006 if (!AuthorizeUser(acd, (vialogin ? false : SeeIntoRegion), out reason))
3918 // check if banned regions are to be blacked out.
3919 if (vialogin || (!m_seeIntoBannedRegion))
3920 { 4007 {
3921 if (!AuthorizeUser(agent, out reason)) 4008 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3922 { 4009 return false;
3923 return false;
3924 }
3925 } 4010 }
3926 } 4011 }
3927 catch (Exception e) 4012 catch (Exception e)
3928 { 4013 {
3929 m_log.ErrorFormat( 4014 m_log.ErrorFormat(
3930 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 4015 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
4016
4017 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
3931 return false; 4018 return false;
3932 } 4019 }
3933 4020
3934 m_log.InfoFormat( 4021 m_log.InfoFormat(
3935 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", 4022 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3936 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, 4023 Name, (acd.child ? "child" : "root"), acd.firstname, acd.lastname,
3937 agent.AgentID, agent.circuitcode); 4024 acd.AgentID, acd.circuitcode);
3938 4025
4026 if (CapsModule != null)
4027 {
4028 CapsModule.SetAgentCapsSeeds(acd);
4029 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4030 }
3939 } 4031 }
3940 else 4032 else
3941 { 4033 {
3942 // Let the SP know how we got here. This has a lot of interesting 4034 // Let the SP know how we got here. This has a lot of interesting
3943 // uses down the line. 4035 // uses down the line.
3944 sp.TeleportFlags = (TPFlags)teleportFlags; 4036 sp.TeleportFlags = (TPFlags)teleportFlags;
3945 4037
3946 if (sp.IsChildAgent) 4038 if (sp.IsChildAgent)
3947 { 4039 {
3948 m_log.DebugFormat( 4040 m_log.DebugFormat(
3949 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4041 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3950 agent.AgentID, RegionInfo.RegionName); 4042 acd.AgentID, RegionInfo.RegionName);
3951 4043
3952 sp.AdjustKnownSeeds(); 4044 sp.AdjustKnownSeeds();
3953 4045
3954 if (CapsModule != null) 4046 if (CapsModule != null)
3955 CapsModule.SetAgentCapsSeeds(agent); 4047 {
4048 CapsModule.SetAgentCapsSeeds(acd);
4049 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4050 }
3956 } 4051 }
3957 } 4052 }
3958 }
3959 4053
3960 // In all cases, add or update the circuit data with the new agent circuit data and teleport flags 4054 // Try caching an incoming user name much earlier on to see if this helps with an issue
3961 agent.teleportFlags = teleportFlags; 4055 // where HG users are occasionally seen by others as "Unknown User" because their UUIDName
3962 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); 4056 // request for the HG avatar appears to trigger before the user name is cached.
4057 CacheUserName(null, acd);
4058 }
3963 4059
3964 if (CapsModule != null) 4060 if (CapsModule != null)
3965 { 4061 {
3966 CapsModule.ActivateCaps(agent.circuitcode); 4062 CapsModule.ActivateCaps(acd.circuitcode);
3967 } 4063 }
3968 4064
3969 if (vialogin) 4065 if (vialogin)
3970 { 4066 {
3971// CleanDroppedAttachments(); 4067// CleanDroppedAttachments();
3972 4068
3973 if (TestBorderCross(agent.startpos, Cardinals.E)) 4069 if (TestBorderCross(acd.startpos, Cardinals.E))
3974 { 4070 {
3975 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); 4071 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.E);
3976 agent.startpos.X = crossedBorder.BorderLine.Z - 1; 4072 acd.startpos.X = crossedBorder.BorderLine.Z - 1;
3977 } 4073 }
3978 4074
3979 if (TestBorderCross(agent.startpos, Cardinals.N)) 4075 if (TestBorderCross(acd.startpos, Cardinals.N))
3980 { 4076 {
3981 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.N); 4077 Border crossedBorder = GetCrossedBorder(acd.startpos, Cardinals.N);
3982 agent.startpos.Y = crossedBorder.BorderLine.Z - 1; 4078 acd.startpos.Y = crossedBorder.BorderLine.Z - 1;
3983 } 4079 }
3984 4080
3985 //Mitigate http://opensimulator.org/mantis/view.php?id=3522 4081 //Mitigate http://opensimulator.org/mantis/view.php?id=3522
@@ -3989,68 +4085,88 @@ namespace OpenSim.Region.Framework.Scenes
3989 { 4085 {
3990 lock (EastBorders) 4086 lock (EastBorders)
3991 { 4087 {
3992 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4088 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
3993 { 4089 {
3994 m_log.Warn("FIX AGENT POSITION"); 4090 m_log.Warn("FIX AGENT POSITION");
3995 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4091 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
3996 if (agent.startpos.Z > 720) 4092 if (acd.startpos.Z > 720)
3997 agent.startpos.Z = 720; 4093 acd.startpos.Z = 720;
3998 } 4094 }
3999 } 4095 }
4000 lock (NorthBorders) 4096 lock (NorthBorders)
4001 { 4097 {
4002 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4098 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4003 { 4099 {
4004 m_log.Warn("FIX Agent POSITION"); 4100 m_log.Warn("FIX Agent POSITION");
4005 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4101 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4006 if (agent.startpos.Z > 720) 4102 if (acd.startpos.Z > 720)
4007 agent.startpos.Z = 720; 4103 acd.startpos.Z = 720;
4008 } 4104 }
4009 } 4105 }
4010 } else 4106 } else
4011 { 4107 {
4012 if (agent.startpos.X > EastBorders[0].BorderLine.Z) 4108 if (acd.startpos.X > EastBorders[0].BorderLine.Z)
4013 { 4109 {
4014 m_log.Warn("FIX AGENT POSITION"); 4110 m_log.Warn("FIX AGENT POSITION");
4015 agent.startpos.X = EastBorders[0].BorderLine.Z * 0.5f; 4111 acd.startpos.X = EastBorders[0].BorderLine.Z * 0.5f;
4016 if (agent.startpos.Z > 720) 4112 if (acd.startpos.Z > 720)
4017 agent.startpos.Z = 720; 4113 acd.startpos.Z = 720;
4018 } 4114 }
4019 if (agent.startpos.Y > NorthBorders[0].BorderLine.Z) 4115 if (acd.startpos.Y > NorthBorders[0].BorderLine.Z)
4020 { 4116 {
4021 m_log.Warn("FIX Agent POSITION"); 4117 m_log.Warn("FIX Agent POSITION");
4022 agent.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f; 4118 acd.startpos.Y = NorthBorders[0].BorderLine.Z * 0.5f;
4023 if (agent.startpos.Z > 720) 4119 if (acd.startpos.Z > 720)
4024 agent.startpos.Z = 720; 4120 acd.startpos.Z = 720;
4025 } 4121 }
4026 } 4122 }
4027 4123
4124// m_log.DebugFormat(
4125// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
4126// RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4127
4028 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags 4128 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags
4029 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && 4129 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero &&
4030 RegionInfo.EstateSettings.AllowDirectTeleport == false && 4130 RegionInfo.EstateSettings.AllowDirectTeleport == false &&
4031 !viahome && !godlike) 4131 !viahome && !godlike)
4032 { 4132 {
4033 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); 4133 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject);
4034 // Can have multiple SpawnPoints 4134
4035 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); 4135 if (telehub != null)
4036 if (spawnpoints.Count > 1)
4037 { 4136 {
4038 // We have multiple SpawnPoints, Route the agent to a random or sequential one 4137 // Can have multiple SpawnPoints
4039 if (SpawnPointRouting == "random") 4138 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints();
4040 agent.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( 4139 if (spawnpoints.Count > 1)
4041 telehub.AbsolutePosition, 4140 {
4042 telehub.GroupRotation 4141 // We have multiple SpawnPoints, Route the agent to a random or sequential one
4043 ); 4142 if (SpawnPointRouting == "random")
4143 acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
4144 telehub.AbsolutePosition,
4145 telehub.GroupRotation
4146 );
4147 else
4148 acd.startpos = spawnpoints[SpawnPoint()].GetLocation(
4149 telehub.AbsolutePosition,
4150 telehub.GroupRotation
4151 );
4152 }
4153 else if (spawnpoints.Count == 1)
4154 {
4155 // We have a single SpawnPoint and will route the agent to it
4156 acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
4157 }
4044 else 4158 else
4045 agent.startpos = spawnpoints[SpawnPoint()].GetLocation( 4159 {
4046 telehub.AbsolutePosition, 4160 m_log.DebugFormat(
4047 telehub.GroupRotation 4161 "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.",
4048 ); 4162 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4163 }
4049 } 4164 }
4050 else 4165 else
4051 { 4166 {
4052 // We have a single SpawnPoint and will route the agent to it 4167 m_log.DebugFormat(
4053 agent.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 4168 "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.",
4169 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4054 } 4170 }
4055 4171
4056 return true; 4172 return true;
@@ -4063,7 +4179,7 @@ namespace OpenSim.Region.Framework.Scenes
4063 { 4179 {
4064 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4180 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
4065 { 4181 {
4066 agent.startpos = land.LandData.UserLocation; 4182 acd.startpos = land.LandData.UserLocation;
4067 } 4183 }
4068 } 4184 }
4069 */// This is now handled properly in ScenePresence.MakeRootAgent 4185 */// This is now handled properly in ScenePresence.MakeRootAgent
@@ -4158,7 +4274,7 @@ namespace OpenSim.Region.Framework.Scenes
4158 /// <param name="reason">outputs the reason to this string</param> 4274 /// <param name="reason">outputs the reason to this string</param>
4159 /// <returns>True if the region accepts this agent. False if it does not. False will 4275 /// <returns>True if the region accepts this agent. False if it does not. False will
4160 /// also return a reason.</returns> 4276 /// also return a reason.</returns>
4161 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 4277 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason)
4162 { 4278 {
4163 reason = String.Empty; 4279 reason = String.Empty;
4164 4280
@@ -4177,67 +4293,75 @@ namespace OpenSim.Region.Framework.Scenes
4177 } 4293 }
4178 } 4294 }
4179 4295
4180 if (RegionInfo.EstateSettings != null) 4296 // We only test the things below when we want to cut off
4297 // child agents from being present in the scene for which their root
4298 // agent isn't allowed. Otherwise, we allow child agents. The test for
4299 // the root is done elsewhere (QueryAccess)
4300 if (!bypassAccessControl)
4181 { 4301 {
4182 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, 0)) 4302 if (RegionInfo.EstateSettings != null)
4183 { 4303 {
4184 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 4304 int flags = GetUserFlags(agent.AgentID);
4185 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4305 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
4186 reason = String.Format("Denied access to region {0}: You have been banned from that region.", 4306 {
4187 RegionInfo.RegionName); 4307 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4188 return false; 4308 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4309 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
4310 RegionInfo.RegionName);
4311 return false;
4312 }
4189 } 4313 }
4190 } 4314 else
4191 else
4192 {
4193 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
4194 }
4195
4196 List<UUID> agentGroups = new List<UUID>();
4197
4198 if (m_groupsModule != null)
4199 {
4200 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4201
4202 if (GroupMembership != null)
4203 { 4315 {
4204 for (int i = 0; i < GroupMembership.Length; i++) 4316 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
4205 agentGroups.Add(GroupMembership[i].GroupID);
4206 } 4317 }
4207 else 4318
4319 List<UUID> agentGroups = new List<UUID>();
4320
4321 if (m_groupsModule != null)
4208 { 4322 {
4209 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); 4323 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4324
4325 if (GroupMembership != null)
4326 {
4327 for (int i = 0; i < GroupMembership.Length; i++)
4328 agentGroups.Add(GroupMembership[i].GroupID);
4329 }
4330 else
4331 {
4332 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!");
4333 }
4210 } 4334 }
4211 }
4212 4335
4213 bool groupAccess = false; 4336 bool groupAccess = false;
4214 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; 4337 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups;
4215 4338
4216 if (estateGroups != null) 4339 if (estateGroups != null)
4217 {
4218 foreach (UUID group in estateGroups)
4219 { 4340 {
4220 if (agentGroups.Contains(group)) 4341 foreach (UUID group in estateGroups)
4221 { 4342 {
4222 groupAccess = true; 4343 if (agentGroups.Contains(group))
4223 break; 4344 {
4345 groupAccess = true;
4346 break;
4347 }
4224 } 4348 }
4225 } 4349 }
4226 } 4350 else
4227 else 4351 {
4228 { 4352 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
4229 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 4353 }
4230 }
4231 4354
4232 if (!RegionInfo.EstateSettings.PublicAccess && 4355 if (!RegionInfo.EstateSettings.PublicAccess &&
4233 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && 4356 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) &&
4234 !groupAccess) 4357 !groupAccess)
4235 { 4358 {
4236 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 4359 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate",
4237 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4360 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4238 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", 4361 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
4239 RegionInfo.RegionName); 4362 RegionInfo.RegionName);
4240 return false; 4363 return false;
4364 }
4241 } 4365 }
4242 4366
4243 // TODO: estate/region settings are not properly hooked up 4367 // TODO: estate/region settings are not properly hooked up
@@ -4362,13 +4486,11 @@ namespace OpenSim.Region.Framework.Scenes
4362 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. 4486 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent.
4363 /// Appearance, animations, position, etc.</param> 4487 /// Appearance, animations, position, etc.</param>
4364 /// <returns>true if we handled it.</returns> 4488 /// <returns>true if we handled it.</returns>
4365 public virtual bool IncomingChildAgentDataUpdate(AgentData cAgentData) 4489 public virtual bool IncomingUpdateChildAgent(AgentData cAgentData)
4366 { 4490 {
4367 m_log.DebugFormat( 4491 m_log.DebugFormat(
4368 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4492 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4369 4493
4370 // XPTO: if this agent is not allowed here as root, always return false
4371
4372 // We have to wait until the viewer contacts this region after receiving EAC. 4494 // We have to wait until the viewer contacts this region after receiving EAC.
4373 // That calls AddNewClient, which finally creates the ScenePresence 4495 // That calls AddNewClient, which finally creates the ScenePresence
4374 int flags = GetUserFlags(cAgentData.AgentID); 4496 int flags = GetUserFlags(cAgentData.AgentID);
@@ -4382,7 +4504,7 @@ namespace OpenSim.Region.Framework.Scenes
4382 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4504 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
4383 if (nearestParcel == null) 4505 if (nearestParcel == null)
4384 { 4506 {
4385 m_log.DebugFormat( 4507 m_log.InfoFormat(
4386 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", 4508 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel",
4387 cAgentData.AgentID, RegionInfo.RegionName); 4509 cAgentData.AgentID, RegionInfo.RegionName);
4388 4510
@@ -4390,13 +4512,44 @@ namespace OpenSim.Region.Framework.Scenes
4390 } 4512 }
4391 4513
4392 // We have to wait until the viewer contacts this region 4514 // We have to wait until the viewer contacts this region
4393 // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send 4515 // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol)
4394 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. 4516 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
4395 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4517 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4518 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4396 4519
4397 if (childAgentUpdate != null) 4520 if (sp != null)
4398 { 4521 {
4399 childAgentUpdate.ChildAgentDataUpdate(cAgentData); 4522 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4523 {
4524 m_log.WarnFormat(
4525 "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).",
4526 sp.UUID, cAgentData.SessionID);
4527
4528 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
4529 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
4530 }
4531
4532 sp.UpdateChildAgent(cAgentData);
4533
4534 int ntimes = 20;
4535 if (cAgentData.SenderWantsToWaitForRoot)
4536 {
4537 while (sp.IsChildAgent && ntimes-- > 0)
4538 Thread.Sleep(1000);
4539
4540 if (sp.IsChildAgent)
4541 m_log.WarnFormat(
4542 "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}",
4543 sp.Name, sp.UUID, Name);
4544 else
4545 m_log.InfoFormat(
4546 "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits",
4547 sp.Name, sp.UUID, Name, 20 - ntimes);
4548
4549 if (sp.IsChildAgent)
4550 return false;
4551 }
4552
4400 return true; 4553 return true;
4401 } 4554 }
4402 4555
@@ -4409,12 +4562,17 @@ namespace OpenSim.Region.Framework.Scenes
4409 /// </summary> 4562 /// </summary>
4410 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> 4563 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param>
4411 /// <returns>true if we handled it.</returns> 4564 /// <returns>true if we handled it.</returns>
4412 public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData) 4565 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData)
4413 { 4566 {
4414 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); 4567 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName);
4415 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4568 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
4416 if (childAgentUpdate != null) 4569 if (childAgentUpdate != null)
4417 { 4570 {
4571// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
4572// // Only warn for now
4573// m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?",
4574// childAgentUpdate.UUID, cAgentData.SessionID);
4575
4418 // I can't imagine *yet* why we would get an update if the agent is a root agent.. 4576 // I can't imagine *yet* why we would get an update if the agent is a root agent..
4419 // however to avoid a race condition crossing borders.. 4577 // however to avoid a race condition crossing borders..
4420 if (childAgentUpdate.IsChildAgent) 4578 if (childAgentUpdate.IsChildAgent)
@@ -4424,7 +4582,7 @@ namespace OpenSim.Region.Framework.Scenes
4424 uint tRegionX = RegionInfo.RegionLocX; 4582 uint tRegionX = RegionInfo.RegionLocX;
4425 uint tRegionY = RegionInfo.RegionLocY; 4583 uint tRegionY = RegionInfo.RegionLocY;
4426 //Send Data to ScenePresence 4584 //Send Data to ScenePresence
4427 childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); 4585 childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
4428 // Not Implemented: 4586 // Not Implemented:
4429 //TODO: Do we need to pass the message on to one of our neighbors? 4587 //TODO: Do we need to pass the message on to one of our neighbors?
4430 } 4588 }
@@ -4451,35 +4609,99 @@ namespace OpenSim.Region.Framework.Scenes
4451 m_log.WarnFormat( 4609 m_log.WarnFormat(
4452 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout", 4610 "[SCENE PRESENCE]: Did not find presence with id {0} in {1} before timeout",
4453 agentID, RegionInfo.RegionName); 4611 agentID, RegionInfo.RegionName);
4454// else
4455// m_log.DebugFormat(
4456// "[SCENE PRESENCE]: Found presence {0} {1} {2} in {3} after {4} waits",
4457// sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", RegionInfo.RegionName, 10 - ntimes);
4458 4612
4459 return sp; 4613 return sp;
4460 } 4614 }
4461 4615
4462 public virtual bool IncomingRetrieveRootAgent(UUID id, out IAgentData agent) 4616 /// <summary>
4617 /// Authenticated close (via network)
4618 /// </summary>
4619 /// <param name="agentID"></param>
4620 /// <param name="force"></param>
4621 /// <param name="auth_token"></param>
4622 /// <returns></returns>
4623 public bool CloseAgent(UUID agentID, bool force, string auth_token)
4463 { 4624 {
4464 agent = null; 4625 //m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token);
4465 ScenePresence sp = GetScenePresence(id); 4626
4466 if ((sp != null) && (!sp.IsChildAgent)) 4627 // Check that the auth_token is valid
4628 AgentCircuitData acd = AuthenticateHandler.GetAgentCircuitData(agentID);
4629
4630 if (acd == null)
4467 { 4631 {
4468 sp.IsChildAgent = true; 4632 m_log.DebugFormat(
4469 return sp.CopyAgent(out agent); 4633 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.",
4634 agentID, Name);
4635
4636 return false;
4637 }
4638
4639 if (acd.SessionID.ToString() == auth_token)
4640 {
4641 return CloseAgent(agentID, force);
4642 }
4643 else
4644 {
4645 m_log.WarnFormat(
4646 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}",
4647 agentID, auth_token, Name);
4470 } 4648 }
4471 4649
4472 return false; 4650 return false;
4473 } 4651 }
4474 4652
4475 public bool IncomingCloseAgent(UUID agentID) 4653// public bool IncomingCloseAgent(UUID agentID)
4476 { 4654// {
4477 return IncomingCloseAgent(agentID, false); 4655// return IncomingCloseAgent(agentID, false);
4478 } 4656// }
4479 4657
4480 public bool IncomingCloseChildAgent(UUID agentID) 4658// public bool IncomingCloseChildAgent(UUID agentID)
4659// {
4660// return IncomingCloseAgent(agentID, true);
4661// }
4662
4663 /// <summary>
4664 /// Tell a single client to prepare to close.
4665 /// </summary>
4666 /// <remarks>
4667 /// This should only be called if we may close the client but there will be some delay in so doing. Meant for
4668 /// internal use - other callers should almost certainly called CloseClient().
4669 /// </remarks>
4670 /// <param name="sp"></param>
4671 /// <returns>true if pre-close state notification was successful. false if the agent
4672 /// was not in a state where it could transition to pre-close.</returns>
4673 public bool IncomingPreCloseClient(ScenePresence sp)
4481 { 4674 {
4482 return IncomingCloseAgent(agentID, true); 4675 lock (m_removeClientLock)
4676 {
4677 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4678 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4679 // want to obey this close since C may have renewed the child agent lease on B.
4680 if (sp.DoNotCloseAfterTeleport)
4681 {
4682 m_log.DebugFormat(
4683 "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4684 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4685
4686 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4687 sp.DoNotCloseAfterTeleport = false;
4688
4689 return false;
4690 }
4691
4692 if (sp.LifecycleState != ScenePresenceState.Running)
4693 {
4694 m_log.DebugFormat(
4695 "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}",
4696 sp.Name, Name, sp.LifecycleState);
4697
4698 return false;
4699 }
4700
4701 sp.LifecycleState = ScenePresenceState.PreRemove;
4702
4703 return true;
4704 }
4483 } 4705 }
4484 4706
4485 /// <summary> 4707 /// <summary>
@@ -4490,18 +4712,57 @@ namespace OpenSim.Region.Framework.Scenes
4490 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to 4712 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
4491 /// force unless you are absolutely sure that the agent is dead and a normal close is not working. 4713 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4492 /// </param> 4714 /// </param>
4493 public bool IncomingCloseAgent(UUID agentID, bool force) 4715 public override bool CloseAgent(UUID agentID, bool force)
4494 { 4716 {
4495 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4717 ScenePresence sp;
4496 4718
4497 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4719 lock (m_removeClientLock)
4498 if (presence != null) 4720 {
4721 sp = GetScenePresence(agentID);
4722
4723 if (sp == null)
4724 {
4725 m_log.DebugFormat(
4726 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4727 agentID, Name);
4728
4729 return false;
4730 }
4731
4732 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
4733 {
4734 m_log.DebugFormat(
4735 "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}",
4736 sp.Name, Name, sp.LifecycleState);
4737
4738 return false;
4739 }
4740
4741 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4742 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4743 // want to obey this close since C may have renewed the child agent lease on B.
4744 if (sp.DoNotCloseAfterTeleport)
4745 {
4746 m_log.DebugFormat(
4747 "[SCENE]: Not closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4748 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4749
4750 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4751 sp.DoNotCloseAfterTeleport = false;
4752
4753 return false;
4754 }
4755
4756 sp.LifecycleState = ScenePresenceState.Removing;
4757 }
4758
4759 if (sp != null)
4499 { 4760 {
4500 presence.ControllingClient.Close(force, force); 4761 sp.ControllingClient.Close(force, force);
4501 return true; 4762 return true;
4502 } 4763 }
4503 4764
4504 // Agent not here 4765 // Agent not here
4505 return false; 4766 return false;
4506 } 4767 }
4507 4768
@@ -5091,21 +5352,6 @@ namespace OpenSim.Region.Framework.Scenes
5091 5352
5092 #endregion 5353 #endregion
5093 5354
5094 public void RegionHandleRequest(IClientAPI client, UUID regionID)
5095 {
5096 ulong handle = 0;
5097 if (regionID == RegionInfo.RegionID)
5098 handle = RegionInfo.RegionHandle;
5099 else
5100 {
5101 GridRegion r = GridService.GetRegionByUUID(UUID.Zero, regionID);
5102 if (r != null)
5103 handle = r.RegionHandle;
5104 }
5105
5106 if (handle != 0)
5107 client.SendRegionHandle(regionID, handle);
5108 }
5109 5355
5110// Commented pending deletion since this method no longer appears to do anything at all 5356// Commented pending deletion since this method no longer appears to do anything at all
5111// public bool NeedSceneCacheClear(UUID agentID) 5357// public bool NeedSceneCacheClear(UUID agentID)
@@ -5657,12 +5903,12 @@ Environment.Exit(1);
5657 List<SceneObjectGroup> objects, 5903 List<SceneObjectGroup> objects,
5658 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 5904 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
5659 { 5905 {
5660 minX = 256; 5906 minX = float.MaxValue;
5661 maxX = -256; 5907 maxX = float.MinValue;
5662 minY = 256; 5908 minY = float.MaxValue;
5663 maxY = -256; 5909 maxY = float.MinValue;
5664 minZ = 8192; 5910 minZ = float.MaxValue;
5665 maxZ = -256; 5911 maxZ = float.MinValue;
5666 5912
5667 List<Vector3> offsets = new List<Vector3>(); 5913 List<Vector3> offsets = new List<Vector3>();
5668 5914
@@ -5802,17 +6048,6 @@ Environment.Exit(1);
5802 { 6048 {
5803 reason = "You are banned from the region"; 6049 reason = "You are banned from the region";
5804 6050
5805 if (EntityTransferModule.IsInTransit(agentID))
5806 {
5807 reason = "Agent is still in transit from this region";
5808
5809 m_log.WarnFormat(
5810 "[SCENE]: Denying agent {0} entry into {1} since region still has them registered as in transit",
5811 agentID, RegionInfo.RegionName);
5812
5813 return false;
5814 }
5815
5816 if (Permissions.IsGod(agentID)) 6051 if (Permissions.IsGod(agentID))
5817 { 6052 {
5818 reason = String.Empty; 6053 reason = String.Empty;
@@ -5862,9 +6097,9 @@ Environment.Exit(1);
5862 6097
5863 try 6098 try
5864 { 6099 {
5865 if (!AuthorizeUser(aCircuit, out reason)) 6100 if (!AuthorizeUser(aCircuit, false, out reason))
5866 { 6101 {
5867 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); 6102 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5868 return false; 6103 return false;
5869 } 6104 }
5870 } 6105 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 74c9582..08e26c5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -42,7 +42,8 @@ namespace OpenSim.Region.Framework.Scenes
42{ 42{
43 public abstract class SceneBase : IScene 43 public abstract class SceneBase : IScene
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 protected static readonly string LogHeader = "[SCENE]";
46 47
47 #region Events 48 #region Events
48 49
@@ -217,8 +218,9 @@ namespace OpenSim.Region.Framework.Scenes
217 218
218 #region Add/Remove Agent/Avatar 219 #region Add/Remove Agent/Avatar
219 220
220 public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type); 221 public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type);
221 public abstract void RemoveClient(UUID agentID, bool closeChildAgents); 222
223 public abstract bool CloseAgent(UUID agentID, bool force);
222 224
223 public bool TryGetScenePresence(UUID agentID, out object scenePresence) 225 public bool TryGetScenePresence(UUID agentID, out object scenePresence)
224 { 226 {
@@ -562,6 +564,10 @@ namespace OpenSim.Region.Framework.Scenes
562 get { return false; } 564 get { return false; }
563 } 565 }
564 566
567 public virtual void Start()
568 {
569 }
570
565 public void Restart() 571 public void Restart()
566 { 572 {
567 // This has to be here to fire the event 573 // This has to be here to fire the event
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 775a4c2..52f46f2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Region.Framework.Scenes
200 /// This Closes child agents on neighboring regions 200 /// This Closes child agents on neighboring regions
201 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 201 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
202 /// </summary> 202 /// </summary>
203 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle) 203 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token)
204 { 204 {
205 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 205 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
206 206
@@ -209,23 +209,25 @@ namespace OpenSim.Region.Framework.Scenes
209 Utils.LongToUInts(regionHandle, out x, out y); 209 Utils.LongToUInts(regionHandle, out x, out y);
210 210
211 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 211 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
212 m_scene.SimulationService.CloseChildAgent(destination, agentID);
213 }
214 212
215 private void SendCloseChildAgentCompleted(IAsyncResult iar) 213 m_log.DebugFormat(
216 { 214 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName);
217 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState; 215
218 icon.EndInvoke(iar); 216 m_scene.SimulationService.CloseAgent(destination, agentID, auth_token);
219 } 217 }
220 218
221 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 219 /// <summary>
220 /// Closes a child agents in a collection of regions. Does so asynchronously
221 /// so that the caller doesn't wait.
222 /// </summary>
223 /// <param name="agentID"></param>
224 /// <param name="regionslst"></param>
225 public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst)
222 { 226 {
223 foreach (ulong handle in regionslst) 227 foreach (ulong handle in regionslst)
224 { 228 {
225 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync; 229 ulong handleCopy = handle;
226 d.BeginInvoke(agentID, handle, 230 Util.FireAndForget((o) => { SendCloseChildAgent(agentID, handleCopy, auth_code); });
227 SendCloseChildAgentCompleted,
228 d);
229 } 231 }
230 } 232 }
231 233
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e599e90..b0f8991 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -631,40 +631,16 @@ namespace OpenSim.Region.Framework.Scenes
631 protected internal ScenePresence CreateAndAddChildScenePresence( 631 protected internal ScenePresence CreateAndAddChildScenePresence(
632 IClientAPI client, AvatarAppearance appearance, PresenceType type) 632 IClientAPI client, AvatarAppearance appearance, PresenceType type)
633 { 633 {
634 ScenePresence newAvatar = null;
635
636 // ScenePresence always defaults to child agent 634 // ScenePresence always defaults to child agent
637 newAvatar = new ScenePresence(client, m_parentScene, appearance, type); 635 ScenePresence presence = new ScenePresence(client, m_parentScene, appearance, type);
638
639 AddScenePresence(newAvatar);
640
641 return newAvatar;
642 }
643
644 /// <summary>
645 /// Add a presence to the scene
646 /// </summary>
647 /// <param name="presence"></param>
648 protected internal void AddScenePresence(ScenePresence presence)
649 {
650 // Always a child when added to the scene
651 bool child = presence.IsChildAgent;
652
653 if (child)
654 {
655 m_numChildAgents++;
656 }
657 else
658 {
659 m_numRootAgents++;
660 presence.AddToPhysicalScene(false);
661 }
662 636
663 Entities[presence.UUID] = presence; 637 Entities[presence.UUID] = presence;
664 638
665 m_scenePresencesLock.EnterWriteLock(); 639 m_scenePresencesLock.EnterWriteLock();
666 try 640 try
667 { 641 {
642 m_numChildAgents++;
643
668 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 644 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
669 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 645 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
670 646
@@ -675,7 +651,7 @@ namespace OpenSim.Region.Framework.Scenes
675 } 651 }
676 else 652 else
677 { 653 {
678 // Remember the old presene reference from the dictionary 654 // Remember the old presence reference from the dictionary
679 ScenePresence oldref = newmap[presence.UUID]; 655 ScenePresence oldref = newmap[presence.UUID];
680 // Replace the presence reference in the dictionary with the new value 656 // Replace the presence reference in the dictionary with the new value
681 newmap[presence.UUID] = presence; 657 newmap[presence.UUID] = presence;
@@ -691,6 +667,8 @@ namespace OpenSim.Region.Framework.Scenes
691 { 667 {
692 m_scenePresencesLock.ExitWriteLock(); 668 m_scenePresencesLock.ExitWriteLock();
693 } 669 }
670
671 return presence;
694 } 672 }
695 673
696 /// <summary> 674 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index c70342f..c5c083a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -420,29 +420,6 @@ namespace OpenSim.Region.Framework.Scenes
420 return false; 420 return false;
421 } 421 }
422 422
423 /// <summary>
424 /// Set the debug packet level on each current scene. This level governs which packets are printed out to the
425 /// console.
426 /// </summary>
427 /// <param name="newDebug"></param>
428 /// <param name="name">Name of avatar to debug</param>
429 public void SetDebugPacketLevelOnCurrentScene(int newDebug, string name)
430 {
431 ForEachSelectedScene(scene =>
432 scene.ForEachScenePresence(sp =>
433 {
434 if (name == null || sp.Name == name)
435 {
436 m_log.DebugFormat(
437 "Packet debug for {0} ({1}) set to {2}",
438 sp.Name, sp.IsChildAgent ? "child" : "root", newDebug);
439
440 sp.ControllingClient.DebugPacketLevel = newDebug;
441 }
442 })
443 );
444 }
445
446 public List<ScenePresence> GetCurrentSceneAvatars() 423 public List<ScenePresence> GetCurrentSceneAvatars()
447 { 424 {
448 List<ScenePresence> avatars = new List<ScenePresence>(); 425 List<ScenePresence> avatars = new List<ScenePresence>();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index f8624e7..8c50a81 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -67,6 +67,12 @@ namespace OpenSim.Region.Framework.Scenes
67 { 67 {
68 int scriptsStarted = 0; 68 int scriptsStarted = 0;
69 69
70 if (m_scene == null)
71 {
72 m_log.DebugFormat("[PRIM INVENTORY]: m_scene is null. Unable to create script instances");
73 return 0;
74 }
75
70 // Don't start scripts if they're turned off in the region! 76 // Don't start scripts if they're turned off in the region!
71 if (!m_scene.RegionInfo.RegionSettings.DisableScripts) 77 if (!m_scene.RegionInfo.RegionSettings.DisableScripts)
72 { 78 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 86f60bb..cfa862e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -111,6 +111,9 @@ namespace OpenSim.Region.Framework.Scenes
111 STATUS_ROTATE_Z = 0x008, 111 STATUS_ROTATE_Z = 0x008,
112 } 112 }
113 113
114 // This flag has the same purpose as InventoryItemFlags.ObjectSlamPerm
115 public static readonly uint SLAM = 16;
116
114 // private PrimCountTaintedDelegate handlerPrimCountTainted = null; 117 // private PrimCountTaintedDelegate handlerPrimCountTainted = null;
115 118
116 /// <summary> 119 /// <summary>
@@ -506,9 +509,7 @@ namespace OpenSim.Region.Framework.Scenes
506 { 509 {
507 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); 510 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
508 } 511 }
509 512
510
511
512 private struct avtocrossInfo 513 private struct avtocrossInfo
513 { 514 {
514 public ScenePresence av; 515 public ScenePresence av;
@@ -660,12 +661,6 @@ namespace OpenSim.Region.Framework.Scenes
660 } 661 }
661 } 662 }
662 663
663/* don't see the need but worse don't see where is restored to false if things stay in
664 foreach (SceneObjectPart part in m_parts.GetArray())
665 {
666 part.IgnoreUndoUpdate = true;
667 }
668 */
669 if (RootPart.GetStatusSandbox()) 664 if (RootPart.GetStatusSandbox())
670 { 665 {
671 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 666 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -751,7 +746,6 @@ namespace OpenSim.Region.Framework.Scenes
751 } 746 }
752 747
753 agent.ParentUUID = UUID.Zero; 748 agent.ParentUUID = UUID.Zero;
754
755// agent.Reset(); 749// agent.Reset();
756// else // Not successful 750// else // Not successful
757// agent.RestoreInCurrentScene(); 751// agent.RestoreInCurrentScene();
@@ -1667,7 +1661,8 @@ namespace OpenSim.Region.Framework.Scenes
1667 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); 1661 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1668 if (avatar == null) 1662 if (avatar == null)
1669 return; 1663 return;
1670 1664 m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State;
1665 m_rootPart.AttachedPos = m_rootPart.OffsetPosition;
1671 avatar.RemoveAttachment(this); 1666 avatar.RemoveAttachment(this);
1672 1667
1673 Vector3 detachedpos = new Vector3(127f,127f,127f); 1668 Vector3 detachedpos = new Vector3(127f,127f,127f);
@@ -1868,11 +1863,11 @@ namespace OpenSim.Region.Framework.Scenes
1868 /// <summary> 1863 /// <summary>
1869 /// Delete this group from its scene. 1864 /// Delete this group from its scene.
1870 /// </summary> 1865 /// </summary>
1871 /// 1866 /// <remarks>
1872 /// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood 1867 /// This only handles the in-world consequences of deletion (e.g. any avatars sitting on it are forcibly stood
1873 /// up and all avatars receive notification of its removal. Removal of the scene object from database backup 1868 /// up and all avatars receive notification of its removal. Removal of the scene object from database backup
1874 /// must be handled by the caller. 1869 /// must be handled by the caller.
1875 /// 1870 /// </remarks>
1876 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1871 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1877 public void DeleteGroupFromScene(bool silent) 1872 public void DeleteGroupFromScene(bool silent)
1878 { 1873 {
@@ -1901,7 +1896,7 @@ namespace OpenSim.Region.Framework.Scenes
1901 if (!IsAttachment 1896 if (!IsAttachment
1902 || AttachedAvatar == avatar.ControllingClient.AgentId 1897 || AttachedAvatar == avatar.ControllingClient.AgentId
1903 || !HasPrivateAttachmentPoint) 1898 || !HasPrivateAttachmentPoint)
1904 avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint> { part.LocalId }); 1899 avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId });
1905 } 1900 }
1906 } 1901 }
1907 }); 1902 });
@@ -2109,6 +2104,7 @@ namespace OpenSim.Region.Framework.Scenes
2109 2104
2110 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0) 2105 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2111 { 2106 {
2107 RootPart.Shape.LastAttachPoint = RootPart.Shape.State;
2112 RootPart.Shape.State = 0; 2108 RootPart.Shape.State = 0;
2113 ScheduleGroupForFullUpdate(); 2109 ScheduleGroupForFullUpdate();
2114 } 2110 }
@@ -2210,7 +2206,7 @@ namespace OpenSim.Region.Framework.Scenes
2210 if (!userExposed) 2206 if (!userExposed)
2211 dupe.IsAttachment = true; 2207 dupe.IsAttachment = true;
2212 2208
2213 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 2209 dupe.m_sittingAvatars = new List<UUID>();
2214 2210
2215 if (!userExposed) 2211 if (!userExposed)
2216 { 2212 {
@@ -3813,20 +3809,20 @@ namespace OpenSim.Region.Framework.Scenes
3813 /// <summary> 3809 /// <summary>
3814 /// Update just the root prim position in a linkset 3810 /// Update just the root prim position in a linkset
3815 /// </summary> 3811 /// </summary>
3816 /// <param name="pos"></param> 3812 /// <param name="newPos"></param>
3817 public void UpdateRootPosition(Vector3 pos) 3813 public void UpdateRootPosition(Vector3 newPos)
3818 { 3814 {
3819 // needs to be called with phys building true 3815 // needs to be called with phys building true
3820 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3816 Vector3 oldPos;
3821 Vector3 oldPos = 3817
3822 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3818 if (IsAttachment)
3823 AbsolutePosition.Y + m_rootPart.OffsetPosition.Y, 3819 oldPos = m_rootPart.AttachedPos + m_rootPart.OffsetPosition; // OffsetPosition should always be 0 in an attachments's root prim
3824 AbsolutePosition.Z + m_rootPart.OffsetPosition.Z); 3820 else
3821 oldPos = AbsolutePosition + m_rootPart.OffsetPosition;
3822
3825 Vector3 diff = oldPos - newPos; 3823 Vector3 diff = oldPos - newPos;
3826 Vector3 axDiff = new Vector3(diff.X, diff.Y, diff.Z);
3827 Quaternion partRotation = m_rootPart.RotationOffset; 3824 Quaternion partRotation = m_rootPart.RotationOffset;
3828 axDiff *= Quaternion.Inverse(partRotation); 3825 diff *= Quaternion.Inverse(partRotation);
3829 diff = axDiff;
3830 3826
3831 SceneObjectPart[] parts = m_parts.GetArray(); 3827 SceneObjectPart[] parts = m_parts.GetArray();
3832 for (int i = 0; i < parts.Length; i++) 3828 for (int i = 0; i < parts.Length; i++)
@@ -3837,6 +3833,9 @@ namespace OpenSim.Region.Framework.Scenes
3837 } 3833 }
3838 3834
3839 AbsolutePosition = newPos; 3835 AbsolutePosition = newPos;
3836
3837 if (IsAttachment)
3838 m_rootPart.AttachedPos = newPos;
3840 3839
3841 HasGroupChanged = true; 3840 HasGroupChanged = true;
3842 if (m_rootPart.Undoing) 3841 if (m_rootPart.Undoing)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 261e958..ce9baaa 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -231,6 +231,13 @@ namespace OpenSim.Region.Framework.Scenes
231 231
232 public double SoundRadius; 232 public double SoundRadius;
233 233
234 /// <summary>
235 /// Should sounds played from this prim be queued?
236 /// </summary>
237 /// <remarks>
238 /// This should only be changed by sound modules. It is up to sound modules as to how they interpret this setting.
239 /// </remarks>
240 public bool SoundQueueing { get; set; }
234 241
235 public uint TimeStampFull; 242 public uint TimeStampFull;
236 243
@@ -383,8 +390,6 @@ namespace OpenSim.Region.Framework.Scenes
383 390
384 private SOPVehicle m_vehicleParams = null; 391 private SOPVehicle m_vehicleParams = null;
385 392
386 private KeyframeMotion m_keyframeMotion = null;
387
388 public KeyframeMotion KeyframeMotion 393 public KeyframeMotion KeyframeMotion
389 { 394 {
390 get; set; 395 get; set;
@@ -506,7 +511,7 @@ namespace OpenSim.Region.Framework.Scenes
506 { 511 {
507 get 512 get
508 { 513 {
509 if (CreatorData != null && CreatorData != string.Empty) 514 if (!string.IsNullOrEmpty(CreatorData))
510 return CreatorID.ToString() + ';' + CreatorData; 515 return CreatorID.ToString() + ';' + CreatorData;
511 else 516 else
512 return CreatorID.ToString(); 517 return CreatorID.ToString();
@@ -536,7 +541,11 @@ namespace OpenSim.Region.Framework.Scenes
536 CreatorID = uuid; 541 CreatorID = uuid;
537 } 542 }
538 if (parts.Length >= 2) 543 if (parts.Length >= 2)
544 {
539 CreatorData = parts[1]; 545 CreatorData = parts[1];
546 if (!CreatorData.EndsWith("/"))
547 CreatorData += "/";
548 }
540 if (parts.Length >= 3) 549 if (parts.Length >= 3)
541 name = parts[2]; 550 name = parts[2];
542 551
@@ -815,7 +824,8 @@ namespace OpenSim.Region.Framework.Scenes
815 } 824 }
816 825
817 // Tell the physics engines that this prim changed. 826 // Tell the physics engines that this prim changed.
818 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 827 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
828 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
819 } 829 }
820 catch (Exception e) 830 catch (Exception e)
821 { 831 {
@@ -933,7 +943,7 @@ namespace OpenSim.Region.Framework.Scenes
933 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString()); 943 //m_log.Info("[PART]: RO2:" + actor.Orientation.ToString());
934 } 944 }
935 945
936 if (ParentGroup != null) 946 if (ParentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
937 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 947 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
938 //} 948 //}
939 } 949 }
@@ -1218,23 +1228,14 @@ namespace OpenSim.Region.Framework.Scenes
1218 // the mappings more consistant. 1228 // the mappings more consistant.
1219 public Vector3 SitTargetPositionLL 1229 public Vector3 SitTargetPositionLL
1220 { 1230 {
1221 get { return new Vector3(m_sitTargetPosition.X, m_sitTargetPosition.Y,m_sitTargetPosition.Z); } 1231 get { return m_sitTargetPosition; }
1222 set { m_sitTargetPosition = value; } 1232 set { m_sitTargetPosition = value; }
1223 } 1233 }
1224 1234
1225 public Quaternion SitTargetOrientationLL 1235 public Quaternion SitTargetOrientationLL
1226 { 1236 {
1227 get 1237 get { return m_sitTargetOrientation; }
1228 { 1238 set { m_sitTargetOrientation = value; }
1229 return new Quaternion(
1230 m_sitTargetOrientation.X,
1231 m_sitTargetOrientation.Y,
1232 m_sitTargetOrientation.Z,
1233 m_sitTargetOrientation.W
1234 );
1235 }
1236
1237 set { m_sitTargetOrientation = new Quaternion(value.X, value.Y, value.Z, value.W); }
1238 } 1239 }
1239 1240
1240 public bool Stopped 1241 public bool Stopped
@@ -2959,6 +2960,26 @@ namespace OpenSim.Region.Framework.Scenes
2959 //ParentGroup.RootPart.m_groupPosition = newpos; 2960 //ParentGroup.RootPart.m_groupPosition = newpos;
2960 } 2961 }
2961 2962
2963 if (pa != null && ParentID != 0 && ParentGroup != null)
2964 {
2965 // Special case where a child object is requesting property updates.
2966 // This happens when linksets are modified to use flexible links rather than
2967 // the default links.
2968 // The simulator code presumes that child parts are only modified by scripts
2969 // so the logic for changing position/rotation/etc does not take into
2970 // account the physical object actually moving.
2971 // This code updates the offset position and rotation of the child and then
2972 // lets the update code push the update to the viewer.
2973 // Since physics engines do not normally generate this event for linkset children,
2974 // this code will not be active unless you have a specially configured
2975 // physics engine.
2976 Quaternion invRootRotation = Quaternion.Normalize(Quaternion.Inverse(ParentGroup.RootPart.RotationOffset));
2977 m_offsetPosition = pa.Position - m_groupPosition;
2978 RotationOffset = pa.Orientation * invRootRotation;
2979 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}",
2980 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
2981 }
2982
2962 ScheduleTerseUpdate(); 2983 ScheduleTerseUpdate();
2963 } 2984 }
2964 2985
@@ -3137,7 +3158,8 @@ namespace OpenSim.Region.Framework.Scenes
3137 return; 3158 return;
3138 3159
3139 // This was pulled from SceneViewer. Attachments always receive full updates. 3160 // This was pulled from SceneViewer. Attachments always receive full updates.
3140 // I could not verify if this is a requirement but this maintains existing behavior 3161 // This is needed because otherwise if only the root prim changes position, then
3162 // it looks as if the entire object has moved (including the other prims).
3141 if (ParentGroup.IsAttachment) 3163 if (ParentGroup.IsAttachment)
3142 { 3164 {
3143 ScheduleFullUpdate(); 3165 ScheduleFullUpdate();
@@ -4350,30 +4372,31 @@ namespace OpenSim.Region.Framework.Scenes
4350 } 4372 }
4351 } 4373 }
4352 4374
4353 public void UpdateGroupPosition(Vector3 pos) 4375 public void UpdateGroupPosition(Vector3 newPos)
4354 { 4376 {
4355 if ((pos.X != GroupPosition.X) || 4377 Vector3 oldPos = GroupPosition;
4356 (pos.Y != GroupPosition.Y) || 4378
4357 (pos.Z != GroupPosition.Z)) 4379 if ((newPos.X != oldPos.X) ||
4380 (newPos.Y != oldPos.Y) ||
4381 (newPos.Z != oldPos.Z))
4358 { 4382 {
4359 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
4360 GroupPosition = newPos; 4383 GroupPosition = newPos;
4361 ScheduleTerseUpdate(); 4384 ScheduleTerseUpdate();
4362 } 4385 }
4363 } 4386 }
4364 4387
4365 /// <summary> 4388 /// <summary>
4366 /// 4389 /// Update this part's offset position.
4367 /// </summary> 4390 /// </summary>
4368 /// <param name="pos"></param> 4391 /// <param name="pos"></param>
4369 public void UpdateOffSet(Vector3 pos) 4392 public void UpdateOffSet(Vector3 newPos)
4370 { 4393 {
4371 if ((pos.X != OffsetPosition.X) || 4394 Vector3 oldPos = OffsetPosition;
4372 (pos.Y != OffsetPosition.Y) ||
4373 (pos.Z != OffsetPosition.Z))
4374 {
4375 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
4376 4395
4396 if ((newPos.X != oldPos.X) ||
4397 (newPos.Y != oldPos.Y) ||
4398 (newPos.Z != oldPos.Z))
4399 {
4377 if (ParentGroup.RootPart.GetStatusSandbox()) 4400 if (ParentGroup.RootPart.GetStatusSandbox())
4378 { 4401 {
4379 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10) 4402 if (Util.GetDistanceTo(ParentGroup.RootPart.StatusSandboxPos, newPos) > 10)
@@ -4520,7 +4543,7 @@ namespace OpenSim.Region.Framework.Scenes
4520 // For now, we use the NINJA naming scheme for identifying joints. 4543 // For now, we use the NINJA naming scheme for identifying joints.
4521 // In the future, we can support other joint specification schemes such as a 4544 // In the future, we can support other joint specification schemes such as a
4522 // custom checkbox in the viewer GUI. 4545 // custom checkbox in the viewer GUI.
4523 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4546 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4524 { 4547 {
4525 return IsHingeJoint() || IsBallJoint(); 4548 return IsHingeJoint() || IsBallJoint();
4526 } 4549 }
@@ -4642,6 +4665,11 @@ namespace OpenSim.Region.Framework.Scenes
4642 } 4665 }
4643 } 4666 }
4644*/ 4667*/
4668 if (pa != null)
4669 {
4670 pa.SetMaterial(Material);
4671 DoPhysicsPropertyUpdate(UsePhysics, true);
4672 }
4645 } 4673 }
4646 else // it already has a physical representation 4674 else // it already has a physical representation
4647 { 4675 {
@@ -5014,6 +5042,14 @@ namespace OpenSim.Region.Framework.Scenes
5014 oldTex.DefaultTexture = fallbackOldFace; 5042 oldTex.DefaultTexture = fallbackOldFace;
5015 } 5043 }
5016 5044
5045 // Materials capable viewers can send a ObjectImage packet
5046 // when nothing in TE has changed. MaterialID should be updated
5047 // by the RenderMaterials CAP handler, so updating it here may cause a
5048 // race condtion. Therefore, if no non-materials TE fields have changed,
5049 // we should ignore any changes and not update Shape.TextureEntry
5050
5051 bool otherFieldsChanged = false;
5052
5017 for (int i = 0 ; i < GetNumberOfSides(); i++) 5053 for (int i = 0 ; i < GetNumberOfSides(); i++)
5018 { 5054 {
5019 5055
@@ -5040,18 +5076,36 @@ namespace OpenSim.Region.Framework.Scenes
5040 // Max change, skip the rest of testing 5076 // Max change, skip the rest of testing
5041 if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) 5077 if (changeFlags == (Changed.TEXTURE | Changed.COLOR))
5042 break; 5078 break;
5079
5080 if (!otherFieldsChanged)
5081 {
5082 if (oldFace.Bump != newFace.Bump) otherFieldsChanged = true;
5083 if (oldFace.Fullbright != newFace.Fullbright) otherFieldsChanged = true;
5084 if (oldFace.Glow != newFace.Glow) otherFieldsChanged = true;
5085 if (oldFace.MediaFlags != newFace.MediaFlags) otherFieldsChanged = true;
5086 if (oldFace.OffsetU != newFace.OffsetU) otherFieldsChanged = true;
5087 if (oldFace.OffsetV != newFace.OffsetV) otherFieldsChanged = true;
5088 if (oldFace.RepeatU != newFace.RepeatU) otherFieldsChanged = true;
5089 if (oldFace.RepeatV != newFace.RepeatV) otherFieldsChanged = true;
5090 if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true;
5091 if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true;
5092 if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true;
5093 }
5043 } 5094 }
5044 5095
5045 m_shape.TextureEntry = newTex.GetBytes(); 5096 if (changeFlags != 0 || otherFieldsChanged)
5046 if (changeFlags != 0) 5097 {
5047 TriggerScriptChangedEvent(changeFlags); 5098 m_shape.TextureEntry = newTex.GetBytes();
5048 UpdateFlag = UpdateRequired.FULL; 5099 if (changeFlags != 0)
5049 ParentGroup.HasGroupChanged = true; 5100 TriggerScriptChangedEvent(changeFlags);
5101 UpdateFlag = UpdateRequired.FULL;
5102 ParentGroup.HasGroupChanged = true;
5050 5103
5051 //This is madness.. 5104 //This is madness..
5052 //ParentGroup.ScheduleGroupForFullUpdate(); 5105 //ParentGroup.ScheduleGroupForFullUpdate();
5053 //This is sparta 5106 //This is sparta
5054 ScheduleFullUpdate(); 5107 ScheduleFullUpdate();
5108 }
5055 } 5109 }
5056 5110
5057 5111
@@ -5239,6 +5293,64 @@ namespace OpenSim.Region.Framework.Scenes
5239 { 5293 {
5240 ParentGroup.AddScriptLPS(count); 5294 ParentGroup.AddScriptLPS(count);
5241 } 5295 }
5296
5297 /// <summary>
5298 /// Sets a prim's owner and permissions when it's rezzed.
5299 /// </summary>
5300 /// <param name="item">The inventory item from which the item was rezzed</param>
5301 /// <param name="userInventory">True: the item is being rezzed from the user's inventory. False: from a prim's inventory.</param>
5302 /// <param name="scene">The scene the prim is being rezzed into</param>
5303 public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene)
5304 {
5305 if ((OwnerID != item.Owner) || ((item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0))
5306 {
5307 if (scene.Permissions.PropagatePermissions())
5308 {
5309 if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0)
5310 {
5311 // Apply the item's permissions to the object
5312 //LogPermissions("Before applying item permissions");
5313 if (userInventory)
5314 {
5315 EveryoneMask = item.EveryOnePermissions;
5316 NextOwnerMask = item.NextPermissions;
5317 }
5318 else
5319 {
5320 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
5321 EveryoneMask = item.EveryOnePermissions;
5322 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
5323 NextOwnerMask = item.NextPermissions;
5324 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
5325 GroupMask = item.GroupPermissions;
5326 }
5327 //LogPermissions("After applying item permissions");
5328 }
5329 }
5330
5331 GroupMask = 0; // DO NOT propagate here
5332 }
5333
5334 if (OwnerID != item.Owner)
5335 {
5336 //LogPermissions("Before ApplyNextOwnerPermissions");
5337 ApplyNextOwnerPermissions();
5338 //LogPermissions("After ApplyNextOwnerPermissions");
5339
5340 LastOwnerID = OwnerID;
5341 OwnerID = item.Owner;
5342 Inventory.ChangeInventoryOwner(item.Owner);
5343 }
5344 }
5345
5346 /// <summary>
5347 /// Logs the prim's permissions. Useful when debugging permission problems.
5348 /// </summary>
5349 /// <param name="message"></param>
5350 private void LogPermissions(String message)
5351 {
5352 PermissionsUtil.LogPermissions(Name, message, BaseMask, OwnerMask, NextOwnerMask);
5353 }
5242 5354
5243 public void ApplyNextOwnerPermissions() 5355 public void ApplyNextOwnerPermissions()
5244 { 5356 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index d04d87b..8893cc0 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -696,7 +696,8 @@ namespace OpenSim.Region.Framework.Scenes
696 /// </param> 696 /// </param>
697 public void StopScriptInstance(TaskInventoryItem item) 697 public void StopScriptInstance(TaskInventoryItem item)
698 { 698 {
699 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID); 699 if (m_part.ParentGroup.Scene != null)
700 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(m_part.LocalId, item.ItemID);
700 701
701 // At the moment, even stopped scripts are counted as active, which is probably wrong. 702 // At the moment, even stopped scripts are counted as active, which is probably wrong.
702// m_part.ParentGroup.AddActiveScriptCount(-1); 703// m_part.ParentGroup.AddActiveScriptCount(-1);
@@ -880,8 +881,8 @@ namespace OpenSim.Region.Framework.Scenes
880 881
881 return items; 882 return items;
882 } 883 }
883 884
884 public SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item) 885 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist)
885 { 886 {
886 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 887 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
887 888
@@ -890,70 +891,58 @@ namespace OpenSim.Region.Framework.Scenes
890 m_log.WarnFormat( 891 m_log.WarnFormat(
891 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", 892 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}",
892 item.AssetID, item.Name, m_part.Name); 893 item.AssetID, item.Name, m_part.Name);
893 return null; 894 objlist = null;
895 veclist = null;
896 return false;
894 } 897 }
895 898
896 string xmlData = Utils.BytesToString(rezAsset.Data); 899 Vector3 bbox;
897 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 900 float offsetHeight;
898 901
899 group.RootPart.AttachPoint = group.RootPart.Shape.State; 902 bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
900 group.RootPart.AttachOffset = group.AbsolutePosition;
901 group.RootPart.AttachRotation = group.GroupRotation;
902 903
903 group.ResetIDs(); 904 for (int i = 0; i < objlist.Count; i++)
904 905 {
905 SceneObjectPart rootPart = group.GetPart(group.UUID); 906 SceneObjectGroup group = objlist[i];
906 907
907 // Since renaming the item in the inventory does not affect the name stored 908 group.RootPart.AttachPoint = group.RootPart.Shape.State;
908 // in the serialization, transfer the correct name from the inventory to the 909 group.RootPart.AttachOffset = group.AbsolutePosition;
909 // object itself before we rez. 910 group.RootPart.AttachRotation = group.GroupRotation;
910 rootPart.Name = item.Name;
911 rootPart.Description = item.Description;
912 911
913 SceneObjectPart[] partList = group.Parts; 912 group.ResetIDs();
914 913
915 group.SetGroup(m_part.GroupID, null); 914 SceneObjectPart rootPart = group.GetPart(group.UUID);
916 915
917 // TODO: Remove magic number badness 916 // Since renaming the item in the inventory does not affect the name stored
918 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number 917 // in the serialization, transfer the correct name from the inventory to the
919 { 918 // object itself before we rez.
920 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions()) 919 // Only do these for the first object if we are rezzing a coalescence.
920 if (i == 0)
921 { 921 {
922 foreach (SceneObjectPart part in partList) 922 rootPart.Name = item.Name;
923 { 923 rootPart.Description = item.Description;
924 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
925 part.EveryoneMask = item.EveryonePermissions;
926 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
927 part.NextOwnerMask = item.NextPermissions;
928 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
929 part.GroupMask = item.GroupPermissions;
930 }
931
932 group.ApplyNextOwnerPermissions();
933 } 924 }
934 }
935 925
936 foreach (SceneObjectPart part in partList) 926 group.SetGroup(m_part.GroupID, null);
937 { 927
938 // TODO: Remove magic number badness 928 foreach (SceneObjectPart part in group.Parts)
939 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
940 { 929 {
941 part.LastOwnerID = part.OwnerID; 930 // Convert between InventoryItem classes. You can never have too many similar but slightly different classes :)
942 part.OwnerID = item.OwnerID; 931 InventoryItemBase dest = new InventoryItemBase(item.ItemID, item.OwnerID);
943 part.Inventory.ChangeInventoryOwner(item.OwnerID); 932 dest.BasePermissions = item.BasePermissions;
933 dest.CurrentPermissions = item.CurrentPermissions;
934 dest.EveryOnePermissions = item.EveryonePermissions;
935 dest.GroupPermissions = item.GroupPermissions;
936 dest.NextPermissions = item.NextPermissions;
937 dest.Flags = item.Flags;
938
939 part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene);
944 } 940 }
945 941
946 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0) 942 rootPart.TrimPermissions();
947 part.EveryoneMask = item.EveryonePermissions;
948 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
949 part.NextOwnerMask = item.NextPermissions;
950 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
951 part.GroupMask = item.GroupPermissions;
952 } 943 }
953 944
954 rootPart.TrimPermissions(); 945 return true;
955
956 return group;
957 } 946 }
958 947
959 /// <summary> 948 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 7004d23..f57d4fe 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -29,7 +29,9 @@ using System;
29using System.Xml; 29using System.Xml;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using System.Threading;
32using System.Timers; 33using System.Timers;
34using Timer = System.Timers.Timer;
33using OpenMetaverse; 35using OpenMetaverse;
34using log4net; 36using log4net;
35using Nini.Config; 37using Nini.Config;
@@ -73,21 +75,50 @@ namespace OpenSim.Region.Framework.Scenes
73 75
74 public class ScenePresence : EntityBase, IScenePresence 76 public class ScenePresence : EntityBase, IScenePresence
75 { 77 {
78 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
79
76// ~ScenePresence() 80// ~ScenePresence()
77// { 81// {
78// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); 82// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
79// } 83// }
80 84
81 private void TriggerScenePresenceUpdated() 85 public void TriggerScenePresenceUpdated()
82 { 86 {
83 if (m_scene != null) 87 if (m_scene != null)
84 m_scene.EventManager.TriggerScenePresenceUpdated(this); 88 m_scene.EventManager.TriggerScenePresenceUpdated(this);
85 } 89 }
86 90
87 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
88
89 public PresenceType PresenceType { get; private set; } 91 public PresenceType PresenceType { get; private set; }
90 92
93 private ScenePresenceStateMachine m_stateMachine;
94
95 /// <summary>
96 /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine
97 /// for more details.
98 /// </summary>
99 public ScenePresenceState LifecycleState
100 {
101 get
102 {
103 return m_stateMachine.GetState();
104 }
105
106 set
107 {
108 m_stateMachine.SetState(value);
109 }
110 }
111
112 /// <summary>
113 /// This exists to prevent race conditions between two CompleteMovement threads if the simulator is slow and
114 /// the viewer fires these in quick succession.
115 /// </summary>
116 /// <remarks>
117 /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement
118 /// regulation done there.
119 /// </remarks>
120 private object m_completeMovementLock = new object();
121
91// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 122// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
92 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); 123 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
93 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); 124 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
@@ -142,6 +173,8 @@ namespace OpenSim.Region.Framework.Scenes
142 private Vector3 m_lastVelocity; 173 private Vector3 m_lastVelocity;
143 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); 174 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f);
144 175
176 private bool m_followCamAuto = false;
177
145 178
146 private Vector3? m_forceToApply; 179 private Vector3? m_forceToApply;
147 private int m_userFlags; 180 private int m_userFlags;
@@ -200,7 +233,7 @@ namespace OpenSim.Region.Framework.Scenes
200 private float m_sitAvatarHeight = 2.0f; 233 private float m_sitAvatarHeight = 2.0f;
201 234
202 private Vector3 m_lastChildAgentUpdatePosition; 235 private Vector3 m_lastChildAgentUpdatePosition;
203 private Vector3 m_lastChildAgentUpdateCamPosition; 236// private Vector3 m_lastChildAgentUpdateCamPosition;
204 237
205 private const int LAND_VELOCITYMAG_MAX = 12; 238 private const int LAND_VELOCITYMAG_MAX = 12;
206 239
@@ -290,9 +323,37 @@ namespace OpenSim.Region.Framework.Scenes
290 /// </summary> 323 /// </summary>
291 private Vector3 posLastSignificantMove; 324 private Vector3 posLastSignificantMove;
292 325
293 // For teleports and crossings callbacks 326 #region For teleports and crossings callbacks
294 string m_callbackURI; 327
295 UUID m_originRegionID; 328 /// <summary>
329 /// In the V1 teleport protocol, the destination simulator sends ReleaseAgent to this address.
330 /// </summary>
331 private string m_callbackURI;
332
333 /// <summary>
334 /// Records the region from which this presence originated, if not from login.
335 /// </summary>
336 /// <remarks>
337 /// Also acts as a signal in the teleport V2 process to release UpdateAgent after a viewer has triggered
338 /// CompleteMovement and made the previous child agent a root agent.
339 /// </remarks>
340 private UUID m_originRegionID;
341
342 /// <summary>
343 /// This object is used as a lock before accessing m_originRegionID to make sure that every thread is seeing
344 /// the very latest value and not using some cached version. Cannot make m_originRegionID itself volatite as
345 /// it is a value type.
346 /// </summary>
347 private object m_originRegionIDAccessLock = new object();
348
349 /// <summary>
350 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
351 /// teleport is reusing the connection.
352 /// </summary>
353 /// <remarks>May be refactored or move somewhere else soon.</remarks>
354 public bool DoNotCloseAfterTeleport { get; set; }
355
356 #endregion
296 357
297 /// <value> 358 /// <value>
298 /// Script engines present in the scene 359 /// Script engines present in the scene
@@ -309,15 +370,12 @@ namespace OpenSim.Region.Framework.Scenes
309 /// <summary> 370 /// <summary>
310 /// Record user movement inputs. 371 /// Record user movement inputs.
311 /// </summary> 372 /// </summary>
312 public byte MovementFlag { get; private set; } 373 public uint MovementFlag { get; private set; }
313 374
314 private bool m_updateflag; 375 /// <summary>
315 376 /// Is the agent stop control flag currently active?
316 public bool Updated 377 /// </summary>
317 { 378 public bool AgentControlStopActive { get; private set; }
318 set { m_updateflag = value; }
319 get { return m_updateflag; }
320 }
321 379
322 private bool m_invulnerable = true; 380 private bool m_invulnerable = true;
323 381
@@ -462,6 +520,7 @@ namespace OpenSim.Region.Framework.Scenes
462 } 520 }
463 else 521 else
464 { 522 {
523// m_log.DebugFormat("[SCENE PRESENCE]: Fetching abs pos where PhysicsActor == null and parent part {0} for {1}", Name, Scene.Name);
465 // Obtain the correct position of a seated avatar. 524 // Obtain the correct position of a seated avatar.
466 // In addition to providing the correct position while 525 // In addition to providing the correct position while
467 // the avatar is seated, this value will also 526 // the avatar is seated, this value will also
@@ -485,7 +544,7 @@ namespace OpenSim.Region.Framework.Scenes
485 } 544 }
486 set 545 set
487 { 546 {
488// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} in {1} to {2}", Name, Scene.Name, value); 547// m_log.DebugFormat("[SCENE PRESENCE]: Setting position of {0} to {1} in {2}", Name, value, Scene.Name);
489// Util.PrintCallStack(); 548// Util.PrintCallStack();
490 549
491 if (PhysicsActor != null) 550 if (PhysicsActor != null)
@@ -502,10 +561,7 @@ namespace OpenSim.Region.Framework.Scenes
502 561
503 // Don't update while sitting. The PhysicsActor above is null whilst sitting. 562 // Don't update while sitting. The PhysicsActor above is null whilst sitting.
504 if (ParentID == 0) 563 if (ParentID == 0)
505 {
506 m_pos = value; 564 m_pos = value;
507// ParentPosition = Vector3.Zero;
508 }
509 565
510 //m_log.DebugFormat( 566 //m_log.DebugFormat(
511 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}", 567 // "[ENTITY BASE]: In {0} set AbsolutePosition of {1} to {2}",
@@ -768,6 +824,14 @@ namespace OpenSim.Region.Framework.Scenes
768 set { m_speedModifier = value; } 824 set { m_speedModifier = value; }
769 } 825 }
770 826
827 /// <summary>
828 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running
829 /// </summary>
830 /// <remarks>
831 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers.
832 /// </remarks>
833 private float AgentControlStopSlowWhilstMoving = 0.5f;
834
771 private bool m_forceFly; 835 private bool m_forceFly;
772 836
773 public bool ForceFly 837 public bool ForceFly
@@ -795,7 +859,7 @@ namespace OpenSim.Region.Framework.Scenes
795 859
796 public ScenePresence( 860 public ScenePresence(
797 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 861 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
798 { 862 {
799 AttachmentsSyncLock = new Object(); 863 AttachmentsSyncLock = new Object();
800 AllowMovement = true; 864 AllowMovement = true;
801 IsChildAgent = true; 865 IsChildAgent = true;
@@ -841,6 +905,8 @@ namespace OpenSim.Region.Framework.Scenes
841 SetDirectionVectors(); 905 SetDirectionVectors();
842 906
843 Appearance = appearance; 907 Appearance = appearance;
908
909 m_stateMachine = new ScenePresenceStateMachine(this);
844 } 910 }
845 911
846 private void RegionHeartbeatEnd(Scene scene) 912 private void RegionHeartbeatEnd(Scene scene)
@@ -874,6 +940,7 @@ namespace OpenSim.Region.Framework.Scenes
874 { 940 {
875 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 941 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
876 ControllingClient.OnAgentUpdate += HandleAgentUpdate; 942 ControllingClient.OnAgentUpdate += HandleAgentUpdate;
943 ControllingClient.OnAgentCameraUpdate += HandleAgentCamerasUpdate;
877 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit; 944 ControllingClient.OnAgentRequestSit += HandleAgentRequestSit;
878 ControllingClient.OnAgentSit += HandleAgentSit; 945 ControllingClient.OnAgentSit += HandleAgentSit;
879 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 946 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
@@ -927,6 +994,7 @@ namespace OpenSim.Region.Framework.Scenes
927 /// <summary> 994 /// <summary>
928 /// Turns a child agent into a root agent. 995 /// Turns a child agent into a root agent.
929 /// </summary> 996 /// </summary>
997 /// <remarks>
930 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the 998 /// Child agents are logged into neighbouring sims largely to observe changes. Root agents exist when the
931 /// avatar is actual in the sim. They can perform all actions. 999 /// avatar is actual in the sim. They can perform all actions.
932 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim, 1000 /// This change is made whenever an avatar enters a region, whether by crossing over from a neighbouring sim,
@@ -934,48 +1002,56 @@ namespace OpenSim.Region.Framework.Scenes
934 /// 1002 ///
935 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 1003 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
936 /// delays that crossing. 1004 /// delays that crossing.
937 /// </summary> 1005 /// </remarks>
938 public void MakeRootAgent(Vector3 pos, bool isFlying) 1006 private bool MakeRootAgent(Vector3 pos, bool isFlying)
939 { 1007 {
940 m_log.DebugFormat( 1008 lock (m_completeMovementLock)
941 "[SCENE]: Upgrading child to root agent for {0} in {1}",
942 Name, m_scene.RegionInfo.RegionName);
943
944 if (ParentUUID != UUID.Zero)
945 { 1009 {
946 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); 1010 if (!IsChildAgent)
947 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); 1011 return false;
948 if (part == null) 1012
1013 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1014
1015 // m_log.InfoFormat(
1016 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1017 // Name, m_scene.RegionInfo.RegionName);
1018
1019 if (ParentUUID != UUID.Zero)
949 { 1020 {
950 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); 1021 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
1022 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
1023 if (part == null)
1024 {
1025 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1026 }
1027 else
1028 {
1029 part.ParentGroup.AddAvatar(UUID);
1030 if (part.SitTargetPosition != Vector3.Zero)
1031 part.SitTargetAvatar = UUID;
1032 // ParentPosition = part.GetWorldPosition();
1033 ParentID = part.LocalId;
1034 ParentPart = part;
1035 m_pos = PrevSitOffset;
1036 // pos = ParentPosition;
1037 pos = part.GetWorldPosition();
1038 }
1039 ParentUUID = UUID.Zero;
1040
1041 // Animator.TrySetMovementAnimation("SIT");
951 } 1042 }
952 else 1043 else
953 { 1044 {
954 part.ParentGroup.AddAvatar(UUID); 1045 IsLoggingIn = false;
955 if (part.SitTargetPosition != Vector3.Zero)
956 part.SitTargetAvatar = UUID;
957// ParentPosition = part.GetWorldPosition();
958 ParentID = part.LocalId;
959 ParentPart = part;
960 m_pos = PrevSitOffset;
961// pos = ParentPosition;
962 pos = part.GetWorldPosition();
963 } 1046 }
964 ParentUUID = UUID.Zero;
965 1047
966 IsChildAgent = false; 1048 IsChildAgent = false;
967
968// Animator.TrySetMovementAnimation("SIT");
969 } 1049 }
970 else
971 {
972 IsChildAgent = false;
973 IsLoggingIn = false;
974 }
975
976 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
977 1050
978 IsChildAgent = false; 1051 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
1052 // set and prevent the close of the connection on a subsequent re-teleport.
1053 // Should not be needed if we are not trying to tell this region to close
1054// DoNotCloseAfterTeleport = false;
979 1055
980 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1056 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
981 if (gm != null) 1057 if (gm != null)
@@ -1116,22 +1192,36 @@ namespace OpenSim.Region.Framework.Scenes
1116 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently 1192 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1117 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are 1193 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1118 // not transporting the required data. 1194 // not transporting the required data.
1119 lock (m_attachments) 1195 //
1196 // We need to restart scripts here so that they receive the correct changed events (CHANGED_TELEPORT
1197 // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently
1198 // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are
1199 // not transporting the required data.
1200 //
1201 // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of
1202 // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here
1203 // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status.
1204 //
1205 // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts().
1206 // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing
1207 // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the
1208 // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine.
1209 //
1210 // One cannot simply iterate over attachments in a fire and forget thread because this would no longer
1211 // be locked, allowing race conditions if other code changes the attachments list.
1212 List<SceneObjectGroup> attachments = GetAttachments();
1213
1214 if (attachments.Count > 0)
1120 { 1215 {
1121 if (HasAttachments()) 1216 m_log.DebugFormat(
1122 { 1217 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1123 m_log.DebugFormat(
1124 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1125 1218
1126 // Resume scripts 1219 // Resume scripts
1127 Util.FireAndForget(delegate(object x) { 1220 foreach (SceneObjectGroup sog in attachments)
1128 foreach (SceneObjectGroup sog in m_attachments) 1221 {
1129 { 1222 sog.ScheduleGroupForFullUpdate();
1130 sog.ScheduleGroupForFullUpdate(); 1223 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1131 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 1224 sog.ResumeScripts();
1132 sog.ResumeScripts();
1133 }
1134 });
1135 } 1225 }
1136 } 1226 }
1137 } 1227 }
@@ -1153,7 +1243,7 @@ namespace OpenSim.Region.Framework.Scenes
1153 1243
1154 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1244 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1155 1245
1156 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd; 1246 return true;
1157 } 1247 }
1158 1248
1159 public int GetStateSource() 1249 public int GetStateSource()
@@ -1306,7 +1396,26 @@ namespace OpenSim.Region.Framework.Scenes
1306 1396
1307 public void StopFlying() 1397 public void StopFlying()
1308 { 1398 {
1309 ControllingClient.StopFlying(this); 1399 Vector3 pos = AbsolutePosition;
1400 if (Appearance.AvatarHeight != 127.0f)
1401 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
1402 else
1403 pos += new Vector3(0f, 0f, (1.56f / 6f));
1404
1405 AbsolutePosition = pos;
1406
1407 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
1408 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
1409 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
1410 // certain amount.. because the LLClient wouldn't land in that situation anyway.
1411
1412 // why are we still testing for this really old height value default???
1413 if (Appearance.AvatarHeight != 127.0f)
1414 CollisionPlane = new Vector4(0, 0, 0, pos.Z - Appearance.AvatarHeight / 6f);
1415 else
1416 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1417
1418 ControllingClient.SendAgentTerseUpdate(this);
1310 } 1419 }
1311 1420
1312 /// <summary> 1421 /// <summary>
@@ -1480,6 +1589,37 @@ namespace OpenSim.Region.Framework.Scenes
1480 1589
1481 } 1590 }
1482 1591
1592 private bool WaitForUpdateAgent(IClientAPI client)
1593 {
1594 // Before the source region executes UpdateAgent
1595 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
1596 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
1597 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1598 int count = 50;
1599 UUID originID;
1600
1601 lock (m_originRegionIDAccessLock)
1602 originID = m_originRegionID;
1603
1604 while (originID.Equals(UUID.Zero) && count-- > 0)
1605 {
1606 lock (m_originRegionIDAccessLock)
1607 originID = m_originRegionID;
1608
1609 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
1610 Thread.Sleep(200);
1611 }
1612
1613 if (originID.Equals(UUID.Zero))
1614 {
1615 // Movement into region will fail
1616 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
1617 return false;
1618 }
1619
1620 return true;
1621 }
1622
1483 /// <summary> 1623 /// <summary>
1484 /// Complete Avatar's movement into the region. 1624 /// Complete Avatar's movement into the region.
1485 /// </summary> 1625 /// </summary>
@@ -1493,9 +1633,18 @@ namespace OpenSim.Region.Framework.Scenes
1493 { 1633 {
1494// DateTime startTime = DateTime.Now; 1634// DateTime startTime = DateTime.Now;
1495 1635
1496 m_log.DebugFormat( 1636 m_log.InfoFormat(
1497 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 1637 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1498 client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); 1638 client.Name, Scene.Name, AbsolutePosition);
1639
1640 // Make sure it's not a login agent. We don't want to wait for updates during login
1641 if (PresenceType != PresenceType.Npc && (m_teleportFlags & TeleportFlags.ViaLogin) == 0)
1642 {
1643 // Let's wait until UpdateAgent (called by departing region) is done
1644 if (!WaitForUpdateAgent(client))
1645 // The sending region never sent the UpdateAgent data, we have to refuse
1646 return;
1647 }
1499 1648
1500 Vector3 look = Velocity; 1649 Vector3 look = Velocity;
1501 1650
@@ -1517,12 +1666,25 @@ namespace OpenSim.Region.Framework.Scenes
1517 } 1666 }
1518 1667
1519 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1668 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1520 MakeRootAgent(AbsolutePosition, flying); 1669 if (!MakeRootAgent(AbsolutePosition, flying))
1670 {
1671 m_log.DebugFormat(
1672 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1673 Name, Scene.Name);
1674
1675 return;
1676 }
1677
1678 // Tell the client that we're totally ready
1521 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); 1679 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1522 1680
1681 // Remember in HandleUseCircuitCode, we delayed this to here
1682 if (m_teleportFlags > 0)
1683 SendInitialDataToMe();
1684
1523// m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); 1685// m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
1524 1686
1525 if ((m_callbackURI != null) && !m_callbackURI.Equals("")) 1687 if (!string.IsNullOrEmpty(m_callbackURI))
1526 { 1688 {
1527 // We cannot sleep here since this would hold up the inbound packet processing thread, as 1689 // We cannot sleep here since this would hold up the inbound packet processing thread, as
1528 // CompleteMovement() is executed synchronously. However, it might be better to delay the release 1690 // CompleteMovement() is executed synchronously. However, it might be better to delay the release
@@ -1535,7 +1697,12 @@ namespace OpenSim.Region.Framework.Scenes
1535 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", 1697 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1536 client.Name, client.AgentId, m_callbackURI); 1698 client.Name, client.AgentId, m_callbackURI);
1537 1699
1538 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 1700 UUID originID;
1701
1702 lock (m_originRegionIDAccessLock)
1703 originID = m_originRegionID;
1704
1705 Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
1539 m_callbackURI = null; 1706 m_callbackURI = null;
1540 } 1707 }
1541// else 1708// else
@@ -1550,7 +1717,6 @@ namespace OpenSim.Region.Framework.Scenes
1550 // Create child agents in neighbouring regions 1717 // Create child agents in neighbouring regions
1551 if (openChildAgents && !IsChildAgent) 1718 if (openChildAgents && !IsChildAgent)
1552 { 1719 {
1553
1554 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 1720 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
1555 if (m_agentTransfer != null) 1721 if (m_agentTransfer != null)
1556 m_agentTransfer.EnableChildAgents(this); 1722 m_agentTransfer.EnableChildAgents(this);
@@ -1573,6 +1739,7 @@ namespace OpenSim.Region.Framework.Scenes
1573// m_log.DebugFormat( 1739// m_log.DebugFormat(
1574// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", 1740// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
1575// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); 1741// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
1742
1576 } 1743 }
1577 1744
1578 /// <summary> 1745 /// <summary>
@@ -1653,9 +1820,9 @@ namespace OpenSim.Region.Framework.Scenes
1653 /// </summary> 1820 /// </summary>
1654 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 1821 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1655 { 1822 {
1656// m_log.DebugFormat( 1823 //m_log.DebugFormat(
1657// "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", 1824 // "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}",
1658// Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); 1825 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
1659 1826
1660 if (IsChildAgent) 1827 if (IsChildAgent)
1661 { 1828 {
@@ -1663,10 +1830,6 @@ namespace OpenSim.Region.Framework.Scenes
1663 return; 1830 return;
1664 } 1831 }
1665 1832
1666 ++m_movementUpdateCount;
1667 if (m_movementUpdateCount < 1)
1668 m_movementUpdateCount = 1;
1669
1670 #region Sanity Checking 1833 #region Sanity Checking
1671 1834
1672 // This is irritating. Really. 1835 // This is irritating. Really.
@@ -1697,21 +1860,6 @@ namespace OpenSim.Region.Framework.Scenes
1697 1860
1698 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; 1861 AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
1699 1862
1700 // Camera location in world. We'll need to raytrace
1701 // from this location from time to time.
1702 CameraPosition = agentData.CameraCenter;
1703 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
1704 {
1705 ReprioritizeUpdates();
1706 m_lastCameraPosition = CameraPosition;
1707 }
1708
1709 // Use these three vectors to figure out what the agent is looking at
1710 // Convert it to a Matrix and/or Quaternion
1711 CameraAtAxis = agentData.CameraAtAxis;
1712 CameraLeftAxis = agentData.CameraLeftAxis;
1713 CameraUpAxis = agentData.CameraUpAxis;
1714
1715 // The Agent's Draw distance setting 1863 // The Agent's Draw distance setting
1716 // When we get to the point of re-computing neighbors everytime this 1864 // When we get to the point of re-computing neighbors everytime this
1717 // changes, then start using the agent's drawdistance rather than the 1865 // changes, then start using the agent's drawdistance rather than the
@@ -1783,9 +1931,16 @@ namespace OpenSim.Region.Framework.Scenes
1783 // Here's where you get them. 1931 // Here's where you get them.
1784 m_AgentControlFlags = flags; 1932 m_AgentControlFlags = flags;
1785 m_headrotation = agentData.HeadRotation; 1933 m_headrotation = agentData.HeadRotation;
1934 byte oldState = State;
1786 State = agentData.State; 1935 State = agentData.State;
1787 1936
1937 // We need to send this back to the client in order to stop the edit beams
1938 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
1939 ControllingClient.SendAgentTerseUpdate(this);
1940
1788 PhysicsActor actor = PhysicsActor; 1941 PhysicsActor actor = PhysicsActor;
1942
1943 // This will be the case if the agent is sitting on the groudn or on an object.
1789 if (actor == null) 1944 if (actor == null)
1790 { 1945 {
1791 SendControlsToScripts(flagsForScripts); 1946 SendControlsToScripts(flagsForScripts);
@@ -1794,12 +1949,13 @@ namespace OpenSim.Region.Framework.Scenes
1794 1949
1795 if (AllowMovement && !SitGround) 1950 if (AllowMovement && !SitGround)
1796 { 1951 {
1797 Quaternion bodyRotation = agentData.BodyRotation; 1952// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);
1953
1798 bool update_rotation = false; 1954 bool update_rotation = false;
1799 1955
1800 if (bodyRotation != Rotation) 1956 if (agentData.BodyRotation != Rotation)
1801 { 1957 {
1802 Rotation = bodyRotation; 1958 Rotation = agentData.BodyRotation;
1803 update_rotation = true; 1959 update_rotation = true;
1804 } 1960 }
1805 1961
@@ -1845,10 +2001,7 @@ namespace OpenSim.Region.Framework.Scenes
1845 else 2001 else
1846 dirVectors = Dir_Vectors; 2002 dirVectors = Dir_Vectors;
1847 2003
1848 // The fact that MovementFlag is a byte needs to be fixed
1849 // it really should be a uint
1850 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. 2004 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
1851 uint nudgehack = 250;
1852 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 2005 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1853 { 2006 {
1854 if (((uint)flags & (uint)DCF) != 0) 2007 if (((uint)flags & (uint)DCF) != 0)
@@ -1865,29 +2018,19 @@ namespace OpenSim.Region.Framework.Scenes
1865 // Why did I get this? 2018 // Why did I get this?
1866 } 2019 }
1867 2020
1868 if ((MovementFlag & (byte)(uint)DCF) == 0) 2021 if (((MovementFlag & (uint)DCF) == 0) & !AgentControlStopActive)
1869 { 2022 {
1870 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
1871 DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
1872 {
1873 MovementFlag |= (byte)nudgehack;
1874 }
1875
1876 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); 2023 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
1877 MovementFlag += (byte)(uint)DCF; 2024 MovementFlag += (uint)DCF;
1878 update_movementflag = true; 2025 update_movementflag = true;
1879 } 2026 }
1880 } 2027 }
1881 else 2028 else
1882 { 2029 {
1883 if ((MovementFlag & (byte)(uint)DCF) != 0 || 2030 if ((MovementFlag & (uint)DCF) != 0)
1884 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE ||
1885 DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT_NUDGE)
1886 && ((MovementFlag & (byte)nudgehack) == nudgehack))
1887 ) // This or is for Nudge forward
1888 { 2031 {
1889 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); 2032 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
1890 MovementFlag -= ((byte)(uint)DCF); 2033 MovementFlag -= (uint)DCF;
1891 update_movementflag = true; 2034 update_movementflag = true;
1892 2035
1893 /* 2036 /*
@@ -1907,6 +2050,13 @@ namespace OpenSim.Region.Framework.Scenes
1907 i++; 2050 i++;
1908 } 2051 }
1909 2052
2053 // Detect AGENT_CONTROL_STOP state changes
2054 if (AgentControlStopActive != ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STOP) != 0))
2055 {
2056 AgentControlStopActive = !AgentControlStopActive;
2057 update_movementflag = true;
2058 }
2059
1910 if (MovingToTarget) 2060 if (MovingToTarget)
1911 { 2061 {
1912 // If the user has pressed a key then we want to cancel any move to target. 2062 // If the user has pressed a key then we want to cancel any move to target.
@@ -1932,53 +2082,79 @@ namespace OpenSim.Region.Framework.Scenes
1932 // Only do this if we're flying 2082 // Only do this if we're flying
1933 if (Flying && !ForceFly) 2083 if (Flying && !ForceFly)
1934 { 2084 {
1935 // Landing detection code 2085 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
1936 2086 if (AgentControlStopActive)
1937 // Are the landing controls requirements filled?
1938 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1939 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1940
1941 //m_log.Debug("[CONTROL]: " +flags);
1942 // Applies a satisfying roll effect to the avatar when flying.
1943 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
1944 {
1945 ApplyFlyingRoll(
1946 FLY_ROLL_RADIANS_PER_UPDATE,
1947 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
1948 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
1949 }
1950 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
1951 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
1952 { 2087 {
1953 ApplyFlyingRoll( 2088 agent_control_v3 = Vector3.Zero;
1954 -FLY_ROLL_RADIANS_PER_UPDATE,
1955 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
1956 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
1957 } 2089 }
1958 else 2090 else
1959 { 2091 {
1960 if (m_AngularVelocity.Z != 0) 2092 // Landing detection code
1961 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
1962 }
1963 2093
1964 if (Flying && IsColliding && controlland) 2094 // Are the landing controls requirements filled?
1965 { 2095 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1966 // nesting this check because LengthSquared() is expensive and we don't 2096 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1967 // want to do it every step when flying. 2097
1968 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) 2098 //m_log.Debug("[CONTROL]: " +flags);
1969 StopFlying(); 2099 // Applies a satisfying roll effect to the avatar when flying.
2100 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
2101 {
2102 ApplyFlyingRoll(
2103 FLY_ROLL_RADIANS_PER_UPDATE,
2104 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2105 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2106 }
2107 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
2108 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2109 {
2110 ApplyFlyingRoll(
2111 -FLY_ROLL_RADIANS_PER_UPDATE,
2112 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2113 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2114 }
2115 else
2116 {
2117 if (m_AngularVelocity.Z != 0)
2118 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
2119 }
2120
2121 if (Flying && IsColliding && controlland)
2122 {
2123 // nesting this check because LengthSquared() is expensive and we don't
2124 // want to do it every step when flying.
2125 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2126 StopFlying();
2127 }
1970 } 2128 }
1971 } 2129 }
1972 2130
2131// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
2132
1973 // If the agent update does move the avatar, then calculate the force ready for the velocity update, 2133 // If the agent update does move the avatar, then calculate the force ready for the velocity update,
1974 // which occurs later in the main scene loop 2134 // which occurs later in the main scene loop
1975 if (update_movementflag || (update_rotation && DCFlagKeyPressed)) 2135 // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they
2136 // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update
2137 // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the
2138 // avatar location in place).
2139 if (update_movementflag
2140 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
1976 { 2141 {
1977// m_log.DebugFormat( 2142// if (update_movementflag || !AgentControlStopActive || MovementFlag != 0)
1978// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", 2143// {
1979// m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); 2144// m_log.DebugFormat(
2145// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, mf = {4}, ur = {5}",
2146// m_scene.RegionInfo.RegionName, agent_control_v3, Name,
2147// update_movementflag, MovementFlag, update_rotation);
1980 2148
1981 AddNewMovement(agent_control_v3); 2149 float speedModifier;
2150
2151 if (AgentControlStopActive)
2152 speedModifier = AgentControlStopSlowWhilstMoving;
2153 else
2154 speedModifier = 1;
2155
2156 AddNewMovement(agent_control_v3, speedModifier);
2157// }
1982 } 2158 }
1983// else 2159// else
1984// { 2160// {
@@ -1991,15 +2167,86 @@ namespace OpenSim.Region.Framework.Scenes
1991// } 2167// }
1992 2168
1993 if (update_movementflag && ParentID == 0) 2169 if (update_movementflag && ParentID == 0)
2170 {
2171// m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name);
1994 Animator.UpdateMovementAnimations(); 2172 Animator.UpdateMovementAnimations();
2173 }
1995 2174
1996 SendControlsToScripts(flagsForScripts); 2175 SendControlsToScripts(flagsForScripts);
1997 } 2176 }
1998 2177
2178 // We need to send this back to the client in order to see the edit beams
2179 if ((State & (uint)AgentState.Editing) != 0)
2180 ControllingClient.SendAgentTerseUpdate(this);
2181
1999 m_scene.EventManager.TriggerOnClientMovement(this); 2182 m_scene.EventManager.TriggerOnClientMovement(this);
2000 TriggerScenePresenceUpdated();
2001 } 2183 }
2002 2184
2185
2186 /// <summary>
2187 /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering.
2188 /// </summary>
2189 private void HandleAgentCamerasUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
2190 {
2191 //m_log.DebugFormat(
2192 // "[SCENE PRESENCE]: In {0} received agent camera update from {1}, flags {2}",
2193 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
2194
2195 if (IsChildAgent)
2196 {
2197 // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
2198 return;
2199 }
2200
2201 ++m_movementUpdateCount;
2202 if (m_movementUpdateCount < 1)
2203 m_movementUpdateCount = 1;
2204
2205// AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
2206
2207 // Camera location in world. We'll need to raytrace
2208 // from this location from time to time.
2209 CameraPosition = agentData.CameraCenter;
2210 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
2211 {
2212 ReprioritizeUpdates();
2213 m_lastCameraPosition = CameraPosition;
2214 }
2215
2216 // Use these three vectors to figure out what the agent is looking at
2217 // Convert it to a Matrix and/or Quaternion
2218 CameraAtAxis = agentData.CameraAtAxis;
2219 CameraLeftAxis = agentData.CameraLeftAxis;
2220 CameraUpAxis = agentData.CameraUpAxis;
2221
2222 // The Agent's Draw distance setting
2223 // When we get to the point of re-computing neighbors everytime this
2224 // changes, then start using the agent's drawdistance rather than the
2225 // region's draw distance.
2226 // DrawDistance = agentData.Far;
2227 DrawDistance = Scene.DefaultDrawDistance;
2228
2229 // Check if Client has camera in 'follow cam' or 'build' mode.
2230 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
2231
2232 m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f)
2233 && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
2234
2235
2236 //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
2237 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
2238 if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
2239 {
2240 if (m_followCamAuto)
2241 {
2242 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
2243 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
2244 }
2245 }
2246
2247 TriggerScenePresenceUpdated();
2248 }
2249
2003 /// <summary> 2250 /// <summary>
2004 /// Calculate an update to move the presence to the set target. 2251 /// Calculate an update to move the presence to the set target.
2005 /// </summary> 2252 /// </summary>
@@ -2252,17 +2499,13 @@ namespace OpenSim.Region.Framework.Scenes
2252 { 2499 {
2253// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 2500// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
2254 2501
2502 bool satOnObject = IsSatOnObject;
2503 SceneObjectPart part = ParentPart;
2255 SitGround = false; 2504 SitGround = false;
2256 2505
2257/* move this down so avatar gets physical in the new position and not where it is siting 2506 if (satOnObject)
2258 if (PhysicsActor == null)
2259 AddToPhysicalScene(false);
2260 */
2261
2262 if (ParentID != 0)
2263 { 2507 {
2264 PrevSitOffset = m_pos; // Save sit offset 2508 PrevSitOffset = m_pos; // Save sit offset
2265 SceneObjectPart part = ParentPart;
2266 UnRegisterSeatControls(part.ParentGroup.UUID); 2509 UnRegisterSeatControls(part.ParentGroup.UUID);
2267 2510
2268 TaskInventoryDictionary taskIDict = part.TaskInventory; 2511 TaskInventoryDictionary taskIDict = part.TaskInventory;
@@ -2281,34 +2524,71 @@ namespace OpenSim.Region.Framework.Scenes
2281 } 2524 }
2282 2525
2283 part.ParentGroup.DeleteAvatar(UUID); 2526 part.ParentGroup.DeleteAvatar(UUID);
2284// ParentPosition = part.GetWorldPosition(); 2527 Vector3 sitPartWorldPosition = part.GetWorldPosition();
2285 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 2528 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2286 2529
2287// m_pos += ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight);
2288// ParentPosition = Vector3.Zero;
2289 m_pos = part.AbsolutePosition + (m_pos * part.GetWorldRotation()) + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight);
2290 if (part.SitTargetAvatar == UUID)
2291 m_bodyRot = part.GetWorldRotation() * part.SitTargetOrientation;
2292
2293 ParentID = 0; 2530 ParentID = 0;
2294 ParentPart = null; 2531 ParentPart = null;
2295 2532
2296 if (PhysicsActor == null) 2533 Quaternion standRotation;
2297 AddToPhysicalScene(false);
2298 2534
2535 if (part.SitTargetAvatar == UUID)
2536 {
2537 standRotation = part.GetWorldRotation();
2538
2539 if (!part.IsRoot)
2540 standRotation = standRotation * part.SitTargetOrientation;
2541// standRotation = part.RotationOffset * part.SitTargetOrientation;
2542// else
2543// standRotation = part.SitTargetOrientation;
2544
2545 }
2546 else
2547 {
2548 standRotation = Rotation;
2549 }
2550
2551 //Vector3 standPos = ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight);
2552 //Vector3 standPos = ParentPosition;
2553
2554// Vector3 standPositionAdjustment
2555// = part.SitTargetPosition + new Vector3(0.5f, 0f, m_sitAvatarHeight / 2f);
2556 Vector3 adjustmentForSitPosition = part.SitTargetPosition * part.GetWorldRotation();
2557
2558 // XXX: This is based on the physics capsule sizes. Need to find a better way to read this rather than
2559 // hardcoding here.
2560 Vector3 adjustmentForSitPose = new Vector3(0.74f, 0f, 0f) * standRotation;
2561
2562 Vector3 standPos = sitPartWorldPosition + adjustmentForSitPosition + adjustmentForSitPose;
2563
2564// m_log.DebugFormat(
2565// "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}",
2566// standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name);
2567
2568 Rotation = standRotation;
2569 AbsolutePosition = standPos;
2570 }
2571
2572 // We need to wait until we have calculated proper stand positions before sitting up the physical
2573 // avatar to avoid race conditions.
2574 if (PhysicsActor == null)
2575 AddToPhysicalScene(false);
2576
2577 if (satOnObject)
2578 {
2299 SendAvatarDataToAllAgents(); 2579 SendAvatarDataToAllAgents();
2300 m_requestedSitTargetID = 0; 2580 m_requestedSitTargetID = 0;
2301 2581
2302 part.RemoveSittingAvatar(UUID); 2582 part.RemoveSittingAvatar(UUID);
2303 2583
2304 if (part != null) 2584 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2305 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2306 } 2585 }
2307 2586
2308 else if (PhysicsActor == null) 2587 else if (PhysicsActor == null)
2309 AddToPhysicalScene(false); 2588 AddToPhysicalScene(false);
2310 2589
2311 Animator.TrySetMovementAnimation("STAND"); 2590 Animator.TrySetMovementAnimation("STAND");
2591 TriggerScenePresenceUpdated();
2312 } 2592 }
2313 2593
2314 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) 2594 private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
@@ -2359,7 +2639,6 @@ namespace OpenSim.Region.Framework.Scenes
2359 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; 2639 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
2360 2640
2361 bool canSit = false; 2641 bool canSit = false;
2362 Vector3 pos = part.AbsolutePosition + offset;
2363 2642
2364 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) 2643 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
2365 { 2644 {
@@ -2369,6 +2648,17 @@ namespace OpenSim.Region.Framework.Scenes
2369 2648
2370 offset = part.SitTargetPosition; 2649 offset = part.SitTargetPosition;
2371 sitOrientation = part.SitTargetOrientation; 2650 sitOrientation = part.SitTargetOrientation;
2651
2652 if (!part.IsRoot)
2653 {
2654 // m_log.DebugFormat("Old sit orient {0}", sitOrientation);
2655 sitOrientation = part.RotationOffset * sitOrientation;
2656 // m_log.DebugFormat("New sit orient {0}", sitOrientation);
2657// m_log.DebugFormat("Old sit offset {0}", offset);
2658 offset = offset * part.RotationOffset;
2659// m_log.DebugFormat("New sit offset {0}", offset);
2660 }
2661
2372 canSit = true; 2662 canSit = true;
2373 } 2663 }
2374 else 2664 else
@@ -2376,9 +2666,10 @@ namespace OpenSim.Region.Framework.Scenes
2376 if (PhysicsSit(part,offset)) // physics engine 2666 if (PhysicsSit(part,offset)) // physics engine
2377 return; 2667 return;
2378 2668
2669 Vector3 pos = part.AbsolutePosition + offset;
2670
2379 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) 2671 if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10)
2380 { 2672 {
2381
2382 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); 2673 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
2383 canSit = true; 2674 canSit = true;
2384 } 2675 }
@@ -2404,10 +2695,14 @@ namespace OpenSim.Region.Framework.Scenes
2404 cameraEyeOffset = part.GetCameraEyeOffset(); 2695 cameraEyeOffset = part.GetCameraEyeOffset();
2405 forceMouselook = part.GetForceMouselook(); 2696 forceMouselook = part.GetForceMouselook();
2406 2697
2698 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
2699 // being sat upon.
2700 offset += part.OffsetPosition;
2701
2407 ControllingClient.SendSitResponse( 2702 ControllingClient.SendSitResponse(
2408 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2703 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2409 2704
2410 m_requestedSitTargetUUID = targetID; 2705 m_requestedSitTargetUUID = part.UUID;
2411 2706
2412 HandleAgentSit(ControllingClient, UUID); 2707 HandleAgentSit(ControllingClient, UUID);
2413 2708
@@ -2435,7 +2730,7 @@ namespace OpenSim.Region.Framework.Scenes
2435 if (part != null) 2730 if (part != null)
2436 { 2731 {
2437 m_requestedSitTargetID = part.LocalId; 2732 m_requestedSitTargetID = part.LocalId;
2438 m_requestedSitTargetUUID = targetID; 2733 m_requestedSitTargetUUID = part.UUID;
2439 2734
2440 } 2735 }
2441 else 2736 else
@@ -2554,6 +2849,9 @@ namespace OpenSim.Region.Framework.Scenes
2554 2849
2555 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 2850 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
2556 { 2851 {
2852 if (IsChildAgent)
2853 return;
2854
2557 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 2855 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2558 2856
2559 if (part != null) 2857 if (part != null)
@@ -2603,24 +2901,40 @@ namespace OpenSim.Region.Framework.Scenes
2603 Vector3 up = new Vector3((float)x, (float)y, (float)z); 2901 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2604 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; 2902 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2605 2903
2606 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; 2904 Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
2905 Quaternion newRot;
2906
2907 if (part.IsRoot)
2908 {
2909 newRot = sitTargetOrient;
2910 }
2911 else
2912 {
2913 newPos = newPos * part.RotationOffset;
2914 newRot = part.RotationOffset * sitTargetOrient;
2915 }
2916
2917 newPos += part.OffsetPosition;
2918
2919 m_pos = newPos;
2920 Rotation = newRot;
2607 2921
2608// m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset;
2609 Rotation = sitTargetOrient;
2610// ParentPosition = part.AbsolutePosition; 2922// ParentPosition = part.AbsolutePosition;
2611 part.ParentGroup.AddAvatar(UUID);
2612 } 2923 }
2613 else 2924 else
2614 { 2925 {
2615 m_pos -= part.AbsolutePosition; 2926 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
2927 // being sat upon.
2928 m_pos -= part.GroupPosition;
2929
2616// ParentPosition = part.AbsolutePosition; 2930// ParentPosition = part.AbsolutePosition;
2617 part.ParentGroup.AddAvatar(UUID);
2618 2931
2619// m_log.DebugFormat( 2932// m_log.DebugFormat(
2620// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2933// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
2621// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); 2934// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
2622 } 2935 }
2623 2936
2937 part.ParentGroup.AddAvatar(UUID);
2624 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 2938 ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2625 ParentID = m_requestedSitTargetID; 2939 ParentID = m_requestedSitTargetID;
2626 m_AngularVelocity = Vector3.Zero; 2940 m_AngularVelocity = Vector3.Zero;
@@ -2634,14 +2948,19 @@ namespace OpenSim.Region.Framework.Scenes
2634 } 2948 }
2635 Animator.TrySetMovementAnimation(sitAnimation); 2949 Animator.TrySetMovementAnimation(sitAnimation);
2636 SendAvatarDataToAllAgents(); 2950 SendAvatarDataToAllAgents();
2951 TriggerScenePresenceUpdated();
2637 } 2952 }
2638 } 2953 }
2639 2954
2640 public void HandleAgentSitOnGround() 2955 public void HandleAgentSitOnGround()
2641 { 2956 {
2957 if (IsChildAgent)
2958 return;
2959
2642// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. 2960// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
2643 m_AngularVelocity = Vector3.Zero; 2961 m_AngularVelocity = Vector3.Zero;
2644 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 2962 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
2963 TriggerScenePresenceUpdated();
2645 SitGround = true; 2964 SitGround = true;
2646 RemoveFromPhysicalScene(); 2965 RemoveFromPhysicalScene();
2647 } 2966 }
@@ -2658,11 +2977,13 @@ namespace OpenSim.Region.Framework.Scenes
2658 public void HandleStartAnim(IClientAPI remoteClient, UUID animID) 2977 public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
2659 { 2978 {
2660 Animator.AddAnimation(animID, UUID.Zero); 2979 Animator.AddAnimation(animID, UUID.Zero);
2980 TriggerScenePresenceUpdated();
2661 } 2981 }
2662 2982
2663 public void HandleStopAnim(IClientAPI remoteClient, UUID animID) 2983 public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
2664 { 2984 {
2665 Animator.RemoveAnimation(animID, false); 2985 Animator.RemoveAnimation(animID, false);
2986 TriggerScenePresenceUpdated();
2666 } 2987 }
2667 2988
2668 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack) 2989 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
@@ -2676,10 +2997,13 @@ namespace OpenSim.Region.Framework.Scenes
2676 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 2997 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
2677 /// </summary> 2998 /// </summary>
2678 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2999 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2679 public void AddNewMovement(Vector3 vec) 3000 /// <param name="thisAddSpeedModifier">
3001 /// Optional additional speed modifier for this particular add. Default is 1</param>
3002 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1)
2680 { 3003 {
2681// m_log.DebugFormat( 3004// m_log.DebugFormat(
2682// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1} for {2}", vec, Rotation, Name); 3005// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
3006// vec, Rotation, thisAddSpeedModifier, Name);
2683 3007
2684 Vector3 direc = vec * Rotation; 3008 Vector3 direc = vec * Rotation;
2685 direc.Normalize(); 3009 direc.Normalize();
@@ -2697,7 +3021,7 @@ namespace OpenSim.Region.Framework.Scenes
2697 if ((vec.Z == 0f) && !Flying) 3021 if ((vec.Z == 0f) && !Flying)
2698 direc.Z = 0f; // Prevent camera WASD up. 3022 direc.Z = 0f; // Prevent camera WASD up.
2699 3023
2700 direc *= 0.03f * 128f * SpeedModifier; 3024 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier;
2701 3025
2702// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); 3026// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
2703 3027
@@ -2843,6 +3167,7 @@ namespace OpenSim.Region.Framework.Scenes
2843 lastTerseUpdateToAllClientsTick = currentTick; 3167 lastTerseUpdateToAllClientsTick = currentTick;
2844 lastPositionSentToAllClients = OffsetPosition; 3168 lastPositionSentToAllClients = OffsetPosition;
2845 3169
3170// Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name);
2846 m_scene.ForEachClient(SendTerseUpdateToClient); 3171 m_scene.ForEachClient(SendTerseUpdateToClient);
2847 } 3172 }
2848 TriggerScenePresenceUpdated(); 3173 TriggerScenePresenceUpdated();
@@ -2880,11 +3205,12 @@ namespace OpenSim.Region.Framework.Scenes
2880 SendOtherAgentsAppearanceToMe(); 3205 SendOtherAgentsAppearanceToMe();
2881 3206
2882 EntityBase[] entities = Scene.Entities.GetEntities(); 3207 EntityBase[] entities = Scene.Entities.GetEntities();
2883 foreach(EntityBase e in entities) 3208 foreach (EntityBase e in entities)
2884 { 3209 {
2885 if (e != null && e is SceneObjectGroup) 3210 if (e != null && e is SceneObjectGroup)
2886 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 3211 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
2887 } 3212 }
3213
2888 }); 3214 });
2889 } 3215 }
2890 3216
@@ -2919,12 +3245,14 @@ namespace OpenSim.Region.Framework.Scenes
2919 // again here... this comes after the cached appearance check because the avatars 3245 // again here... this comes after the cached appearance check because the avatars
2920 // appearance goes into the avatar update packet 3246 // appearance goes into the avatar update packet
2921 SendAvatarDataToAllAgents(); 3247 SendAvatarDataToAllAgents();
3248
3249 // This invocation always shows up in the viewer logs as an error. Is it needed?
2922 SendAppearanceToAgent(this); 3250 SendAppearanceToAgent(this);
2923 3251
2924 // If we are using the the cached appearance then send it out to everyone 3252 // If we are using the the cached appearance then send it out to everyone
2925 if (cachedappearance) 3253 if (cachedappearance)
2926 { 3254 {
2927 m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); 3255 m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name);
2928 3256
2929 // If the avatars baked textures are all in the cache, then we have a 3257 // If the avatars baked textures are all in the cache, then we have a
2930 // complete appearance... send it out, if not, then we'll send it when 3258 // complete appearance... send it out, if not, then we'll send it when
@@ -3079,11 +3407,10 @@ namespace OpenSim.Region.Framework.Scenes
3079 } 3407 }
3080 3408
3081 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m 3409 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
3082 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || 3410 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
3083 Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
3084 { 3411 {
3085 m_lastChildAgentUpdatePosition = AbsolutePosition; 3412 m_lastChildAgentUpdatePosition = AbsolutePosition;
3086 m_lastChildAgentUpdateCamPosition = CameraPosition; 3413// m_lastChildAgentUpdateCamPosition = CameraPosition;
3087 3414
3088 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 3415 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
3089 cadu.ActiveGroupID = UUID.Zero.Guid; 3416 cadu.ActiveGroupID = UUID.Zero.Guid;
@@ -3110,7 +3437,7 @@ namespace OpenSim.Region.Framework.Scenes
3110 cadu.Velocity = Velocity; 3437 cadu.Velocity = Velocity;
3111 3438
3112 AgentPosition agentpos = new AgentPosition(); 3439 AgentPosition agentpos = new AgentPosition();
3113 agentpos.CopyFrom(cadu); 3440 agentpos.CopyFrom(cadu, ControllingClient.SessionId);
3114 3441
3115 // Let's get this out of the update loop 3442 // Let's get this out of the update loop
3116 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); }); 3443 Util.FireAndForget(delegate { m_scene.SendOutChildAgentUpdates(agentpos, this); });
@@ -3294,11 +3621,6 @@ namespace OpenSim.Region.Framework.Scenes
3294 } 3621 }
3295 } 3622 }
3296 3623
3297 public void RestoreInCurrentScene()
3298 {
3299 AddToPhysicalScene(false); // not exactly false
3300 }
3301
3302 public void Reset() 3624 public void Reset()
3303 { 3625 {
3304// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); 3626// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
@@ -3348,10 +3670,12 @@ namespace OpenSim.Region.Framework.Scenes
3348 if (byebyeRegions.Count > 0) 3670 if (byebyeRegions.Count > 0)
3349 { 3671 {
3350 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); 3672 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
3351 Util.FireAndForget(delegate 3673
3352 { 3674 AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID);
3353 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, byebyeRegions); 3675 string auth = string.Empty;
3354 }); 3676 if (acd != null)
3677 auth = acd.SessionID.ToString();
3678 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
3355 } 3679 }
3356 3680
3357 foreach (ulong handle in byebyeRegions) 3681 foreach (ulong handle in byebyeRegions)
@@ -3392,7 +3716,7 @@ namespace OpenSim.Region.Framework.Scenes
3392 3716
3393 #region Child Agent Updates 3717 #region Child Agent Updates
3394 3718
3395 public void ChildAgentDataUpdate(AgentData cAgentData) 3719 public void UpdateChildAgent(AgentData cAgentData)
3396 { 3720 {
3397// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); 3721// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
3398 if (!IsChildAgent) 3722 if (!IsChildAgent)
@@ -3402,15 +3726,17 @@ namespace OpenSim.Region.Framework.Scenes
3402 } 3726 }
3403 3727
3404 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 3728 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
3729
3405 private void RaiseUpdateThrottles() 3730 private void RaiseUpdateThrottles()
3406 { 3731 {
3407 m_scene.EventManager.TriggerThrottleUpdate(this); 3732 m_scene.EventManager.TriggerThrottleUpdate(this);
3408 } 3733 }
3734
3409 /// <summary> 3735 /// <summary>
3410 /// This updates important decision making data about a child agent 3736 /// This updates important decision making data about a child agent
3411 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region 3737 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
3412 /// </summary> 3738 /// </summary>
3413 public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) 3739 public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
3414 { 3740 {
3415 if (!IsChildAgent) 3741 if (!IsChildAgent)
3416 return; 3742 return;
@@ -3452,6 +3778,7 @@ namespace OpenSim.Region.Framework.Scenes
3452 3778
3453 cAgent.AgentID = UUID; 3779 cAgent.AgentID = UUID;
3454 cAgent.RegionID = Scene.RegionInfo.RegionID; 3780 cAgent.RegionID = Scene.RegionInfo.RegionID;
3781 cAgent.SessionID = ControllingClient.SessionId;
3455 3782
3456 cAgent.Position = AbsolutePosition; 3783 cAgent.Position = AbsolutePosition;
3457 cAgent.Velocity = m_velocity; 3784 cAgent.Velocity = m_velocity;
@@ -3517,7 +3844,8 @@ namespace OpenSim.Region.Framework.Scenes
3517 3844
3518 private void CopyFrom(AgentData cAgent) 3845 private void CopyFrom(AgentData cAgent)
3519 { 3846 {
3520 m_originRegionID = cAgent.RegionID; 3847 lock (m_originRegionIDAccessLock)
3848 m_originRegionID = cAgent.RegionID;
3521 3849
3522 m_callbackURI = cAgent.CallbackURI; 3850 m_callbackURI = cAgent.CallbackURI;
3523// m_log.DebugFormat( 3851// m_log.DebugFormat(
@@ -3611,8 +3939,6 @@ namespace OpenSim.Region.Framework.Scenes
3611 { 3939 {
3612 Vector3 force = m_forceToApply.Value; 3940 Vector3 force = m_forceToApply.Value;
3613 3941
3614 Updated = true;
3615
3616 Velocity = force; 3942 Velocity = force;
3617 3943
3618 m_forceToApply = null; 3944 m_forceToApply = null;
@@ -3694,7 +4020,8 @@ namespace OpenSim.Region.Framework.Scenes
3694 4020
3695// if (m_updateCount > 0) 4021// if (m_updateCount > 0)
3696// { 4022// {
3697 Animator.UpdateMovementAnimations(); 4023 if (Animator.UpdateMovementAnimations())
4024 TriggerScenePresenceUpdated();
3698// m_updateCount--; 4025// m_updateCount--;
3699// } 4026// }
3700 4027
@@ -3858,6 +4185,7 @@ namespace OpenSim.Region.Framework.Scenes
3858// Animator.Close(); 4185// Animator.Close();
3859 Animator = null; 4186 Animator = null;
3860 4187
4188 LifecycleState = ScenePresenceState.Removed;
3861 } 4189 }
3862 4190
3863 public void AddAttachment(SceneObjectGroup gobj) 4191 public void AddAttachment(SceneObjectGroup gobj)
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
new file mode 100644
index 0000000..cae7fe5
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
@@ -0,0 +1,113 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29
30namespace OpenSim.Region.Framework.Scenes
31{
32 /// <summary>
33 /// The possible states that a scene presence can be in. This is currently orthagonal to whether a scene presence
34 /// is root or child.
35 /// </summary>
36 /// <remarks>
37 /// This is a state machine.
38 ///
39 /// [Entry] => Running
40 /// Running => PreRemove, Removing
41 /// PreRemove => Running, Removing
42 /// Removing => Removed
43 ///
44 /// All other methods should only see the scene presence in running state - this is the normal operational state
45 /// Removed state occurs when the presence has been removed. This is the end state with no exit.
46 /// </remarks>
47 public enum ScenePresenceState
48 {
49 Running, // Normal operation state. The scene presence is available.
50 PreRemove, // The presence is due to be removed but can still be returning to running.
51 Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient.
52 Removed, // The presence has been removed from the scene and is effectively dead.
53 // There is no exit from this state.
54 }
55
56 internal class ScenePresenceStateMachine
57 {
58 private ScenePresence m_sp;
59 private ScenePresenceState m_state;
60
61 internal ScenePresenceStateMachine(ScenePresence sp)
62 {
63 m_sp = sp;
64 m_state = ScenePresenceState.Running;
65 }
66
67 internal ScenePresenceState GetState()
68 {
69 return m_state;
70 }
71
72 /// <summary>
73 /// Updates the state of an agent that is already in transit.
74 /// </summary>
75 /// <param name='id'></param>
76 /// <param name='newState'></param>
77 /// <returns></returns>
78 /// <exception cref='Exception'>Illegal transitions will throw an Exception</exception>
79 internal void SetState(ScenePresenceState newState)
80 {
81 bool transitionOkay = false;
82
83 lock (this)
84 {
85 if (newState == m_state)
86 return;
87 else if (newState == ScenePresenceState.Running && m_state == ScenePresenceState.PreRemove)
88 transitionOkay = true;
89 else if (newState == ScenePresenceState.PreRemove && m_state == ScenePresenceState.Running)
90 transitionOkay = true;
91 else if (newState == ScenePresenceState.Removing)
92 {
93 if (m_state == ScenePresenceState.Running || m_state == ScenePresenceState.PreRemove)
94 transitionOkay = true;
95 }
96 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing)
97 transitionOkay = true;
98 }
99
100 if (!transitionOkay)
101 {
102 throw new Exception(
103 string.Format(
104 "Scene presence {0} is not allowed to move from state {1} to new state {2} in {3}",
105 m_sp.Name, m_state, newState, m_sp.Scene.Name));
106 }
107 else
108 {
109 m_state = newState;
110 }
111 }
112 }
113} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index ce4fb40..5372360 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -365,6 +365,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
365 m_SOPXmlProcessors.Add("CollisionSound", ProcessCollisionSound); 365 m_SOPXmlProcessors.Add("CollisionSound", ProcessCollisionSound);
366 m_SOPXmlProcessors.Add("CollisionSoundVolume", ProcessCollisionSoundVolume); 366 m_SOPXmlProcessors.Add("CollisionSoundVolume", ProcessCollisionSoundVolume);
367 m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl); 367 m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl);
368 m_SOPXmlProcessors.Add("AttachedPos", ProcessAttachedPos);
368 m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs); 369 m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs);
369 m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation); 370 m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation);
370 m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem); 371 m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem);
@@ -443,6 +444,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
443 m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd); 444 m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd);
444 m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow); 445 m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow);
445 m_ShapeXmlProcessors.Add("Scale", ProcessShpScale); 446 m_ShapeXmlProcessors.Add("Scale", ProcessShpScale);
447 m_ShapeXmlProcessors.Add("LastAttachPoint", ProcessShpLastAttach);
446 m_ShapeXmlProcessors.Add("State", ProcessShpState); 448 m_ShapeXmlProcessors.Add("State", ProcessShpState);
447 m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape); 449 m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape);
448 m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape); 450 m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape);
@@ -798,6 +800,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
798 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty); 800 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty);
799 } 801 }
800 802
803 private static void ProcessAttachedPos(SceneObjectPart obj, XmlTextReader reader)
804 {
805 obj.AttachedPos = Util.ReadVector(reader, "AttachedPos");
806 }
807
801 private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader) 808 private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader)
802 { 809 {
803 obj.DynAttrs.ReadXml(reader); 810 obj.DynAttrs.ReadXml(reader);
@@ -1099,6 +1106,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1099 shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty); 1106 shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty);
1100 } 1107 }
1101 1108
1109 private static void ProcessShpLastAttach(PrimitiveBaseShape shp, XmlTextReader reader)
1110 {
1111 shp.LastAttachPoint = (byte)reader.ReadElementContentAsInt("LastAttachPoint", String.Empty);
1112 }
1113
1102 private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader) 1114 private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader)
1103 { 1115 {
1104 shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape"); 1116 shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape");
@@ -1267,7 +1279,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1267 1279
1268 WriteUUID(writer, "CreatorID", sop.CreatorID, options); 1280 WriteUUID(writer, "CreatorID", sop.CreatorID, options);
1269 1281
1270 if (sop.CreatorData != null && sop.CreatorData != string.Empty) 1282 if (!string.IsNullOrEmpty(sop.CreatorData))
1271 writer.WriteElementString("CreatorData", sop.CreatorData); 1283 writer.WriteElementString("CreatorData", sop.CreatorData);
1272 else if (options.ContainsKey("home")) 1284 else if (options.ContainsKey("home"))
1273 { 1285 {
@@ -1345,8 +1357,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1345 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); 1357 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString());
1346 if (sop.MediaUrl != null) 1358 if (sop.MediaUrl != null)
1347 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); 1359 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString());
1360 WriteVector(writer, "AttachedPos", sop.AttachedPos);
1348 1361
1349 if (sop.DynAttrs.Count > 0) 1362 if (sop.DynAttrs.CountNamespaces > 0)
1350 { 1363 {
1351 writer.WriteStartElement("DynAttrs"); 1364 writer.WriteStartElement("DynAttrs");
1352 sop.DynAttrs.WriteXml(writer); 1365 sop.DynAttrs.WriteXml(writer);
@@ -1451,7 +1464,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1451 1464
1452 WriteUUID(writer, "CreatorID", item.CreatorID, options); 1465 WriteUUID(writer, "CreatorID", item.CreatorID, options);
1453 1466
1454 if (item.CreatorData != null && item.CreatorData != string.Empty) 1467 if (!string.IsNullOrEmpty(item.CreatorData))
1455 writer.WriteElementString("CreatorData", item.CreatorData); 1468 writer.WriteElementString("CreatorData", item.CreatorData);
1456 else if (options.ContainsKey("home")) 1469 else if (options.ContainsKey("home"))
1457 { 1470 {
@@ -1539,6 +1552,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1539 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString()); 1552 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString());
1540 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString()); 1553 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString());
1541 writer.WriteElementString("State", shp.State.ToString()); 1554 writer.WriteElementString("State", shp.State.ToString());
1555 writer.WriteElementString("LastAttachPoint", shp.LastAttachPoint.ToString());
1542 1556
1543 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options); 1557 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options);
1544 WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options); 1558 WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options);
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 5398ab9..bf32251 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -290,6 +290,9 @@ namespace OpenSim.Region.Framework.Scenes
290 290
291 private void statsHeartBeat(object sender, EventArgs e) 291 private void statsHeartBeat(object sender, EventArgs e)
292 { 292 {
293 if (!m_scene.Active)
294 return;
295
293 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[23]; 296 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[23];
294 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); 297 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
295 298
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
index 9557cd0..95b30d5 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
@@ -33,7 +33,9 @@ using NUnit.Framework;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Communications; 35using OpenSim.Framework.Communications;
36using OpenSim.Region.CoreModules.Framework.EntityTransfer;
36using OpenSim.Region.CoreModules.Framework.InventoryAccess; 37using OpenSim.Region.CoreModules.Framework.InventoryAccess;
38using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
37using OpenSim.Region.CoreModules.World.Permissions; 39using OpenSim.Region.CoreModules.World.Permissions;
38using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
@@ -52,6 +54,24 @@ namespace OpenSim.Region.Framework.Scenes.Tests
52 [TestFixture] 54 [TestFixture]
53 public class SceneObjectDeRezTests : OpenSimTestCase 55 public class SceneObjectDeRezTests : OpenSimTestCase
54 { 56 {
57 [TestFixtureSetUp]
58 public void FixtureInit()
59 {
60 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
61 // This facility was added after the original async delete tests were written, so it may be possible now
62 // to not bother explicitly disabling their async (since everything will be running sync).
63 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
64 }
65
66 [TestFixtureTearDown]
67 public void TearDown()
68 {
69 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
70 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
71 // tests really shouldn't).
72 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
73 }
74
55 /// <summary> 75 /// <summary>
56 /// Test deleting an object from a scene. 76 /// Test deleting an object from a scene.
57 /// </summary> 77 /// </summary>
@@ -59,7 +79,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
59 public void TestDeRezSceneObject() 79 public void TestDeRezSceneObject()
60 { 80 {
61 TestHelpers.InMethod(); 81 TestHelpers.InMethod();
62// log4net.Config.XmlConfigurator.Configure();
63 82
64 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 83 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
65 84
@@ -73,32 +92,77 @@ namespace OpenSim.Region.Framework.Scenes.Tests
73 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 92 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
74 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; 93 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
75 sogd.Enabled = false; 94 sogd.Enabled = false;
76 95
77 SceneObjectPart part 96 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", userId);
78 = new SceneObjectPart(userId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); 97 uint soLocalId = so.LocalId;
79 part.Name = "obj1";
80 scene.AddNewSceneObject(new SceneObjectGroup(part), false);
81 98
82 List<uint> localIds = new List<uint>(); 99 List<uint> localIds = new List<uint>();
83 localIds.Add(part.LocalId); 100 localIds.Add(so.LocalId);
84 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero); 101 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero);
85 102
86 // Check that object isn't deleted until we crank the sogd handle. 103 // Check that object isn't deleted until we crank the sogd handle.
87 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 104 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
88 Assert.That(retrievedPart, Is.Not.Null); 105 Assert.That(retrievedPart, Is.Not.Null);
89 Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False); 106 Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False);
90 107
91 sogd.InventoryDeQueueAndDelete(); 108 sogd.InventoryDeQueueAndDelete();
92 109
93 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(part.LocalId); 110 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
94 Assert.That(retrievedPart2, Is.Null); 111 Assert.That(retrievedPart2, Is.Null);
112 }
113
114 /// <summary>
115 /// Test that child and root agents correctly receive KillObject notifications.
116 /// </summary>
117 [Test]
118 public void TestDeRezSceneObjectToAgents()
119 {
120 TestHelpers.InMethod();
121// TestHelpers.EnableLogging();
122
123 SceneHelpers sh = new SceneHelpers();
124 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
125 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999);
126
127 // We need this so that the creation of the root client for userB in sceneB can trigger the creation of a child client in sceneA
128 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
129 EntityTransferModule etmB = new EntityTransferModule();
130 IConfigSource config = new IniConfigSource();
131 IConfig modulesConfig = config.AddConfig("Modules");
132 modulesConfig.Set("EntityTransferModule", etmB.Name);
133 modulesConfig.Set("SimulationServices", lscm.Name);
134 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
135 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
136
137 // We need this for derez
138 //SceneHelpers.SetupSceneModules(sceneA, new PermissionsModule());
139
140 UserAccount uaA = UserAccountHelpers.CreateUserWithInventory(sceneA, "Andy", "AAA", 0x1, "");
141 UserAccount uaB = UserAccountHelpers.CreateUserWithInventory(sceneA, "Brian", "BBB", 0x2, "");
142
143 TestClient clientA = (TestClient)SceneHelpers.AddScenePresence(sceneA, uaA).ControllingClient;
144
145 // This is the more long-winded route we have to take to get a child client created for userB in sceneA
146 // rather than just calling AddScenePresence() as for userA
147 AgentCircuitData acd = SceneHelpers.GenerateAgentData(uaB);
148 TestClient clientB = new TestClient(acd, sceneB);
149 List<TestClient> childClientsB = new List<TestClient>();
150 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(clientB, childClientsB);
151
152 SceneHelpers.AddScenePresence(sceneB, clientB, acd);
153
154 SceneObjectGroup so = SceneHelpers.AddSceneObject(sceneA);
155 uint soLocalId = so.LocalId;
156
157 sceneA.DeleteSceneObject(so, false);
95 } 158 }
96 159
97 /// <summary> 160 /// <summary>
98 /// Test deleting an object from a scene where the deleter is not the owner 161 /// Test deleting an object from a scene where the deleter is not the owner
99 /// </summary> 162 /// </summary>
100 /// 163 /// <remarks>
101 /// This test assumes that the deleter is not a god. 164 /// This test assumes that the deleter is not a god.
165 /// </remarks>
102 [Test] 166 [Test]
103 public void TestDeRezSceneObjectNotOwner() 167 public void TestDeRezSceneObjectNotOwner()
104 { 168 {
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index bbfbbfc..1ff1329 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -111,6 +111,45 @@ namespace OpenSim.Region.Framework.Scenes.Tests
111 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1)); 111 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1));
112 } 112 }
113 113
114 /// <summary>
115 /// Test that duplicate complete movement calls are ignored.
116 /// </summary>
117 /// <remarks>
118 /// If duplicate calls are not ignored then there is a risk of race conditions or other unexpected effects.
119 /// </remarks>
120 [Test]
121 public void TestDupeCompleteMovementCalls()
122 {
123 TestHelpers.InMethod();
124// TestHelpers.EnableLogging();
125
126 UUID spUuid = TestHelpers.ParseTail(0x1);
127
128 TestScene scene = new SceneHelpers().SetupScene();
129
130 int makeRootAgentEvents = 0;
131 scene.EventManager.OnMakeRootAgent += spi => makeRootAgentEvents++;
132
133 ScenePresence sp = SceneHelpers.AddScenePresence(scene, spUuid);
134
135 Assert.That(makeRootAgentEvents, Is.EqualTo(1));
136
137 // Normally these would be invoked by a CompleteMovement message coming in to the UDP stack. But for
138 // convenience, here we will invoke it manually.
139 sp.CompleteMovement(sp.ControllingClient, true);
140
141 Assert.That(makeRootAgentEvents, Is.EqualTo(1));
142
143 // Check rest of exepcted parameters.
144 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null);
145 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
146
147 Assert.That(sp.IsChildAgent, Is.False);
148 Assert.That(sp.UUID, Is.EqualTo(spUuid));
149
150 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1));
151 }
152
114 [Test] 153 [Test]
115 public void TestCreateDuplicateRootScenePresence() 154 public void TestCreateDuplicateRootScenePresence()
116 { 155 {
@@ -119,7 +158,20 @@ namespace OpenSim.Region.Framework.Scenes.Tests
119 158
120 UUID spUuid = TestHelpers.ParseTail(0x1); 159 UUID spUuid = TestHelpers.ParseTail(0x1);
121 160
161 // The etm is only invoked by this test to check whether an agent is still in transit if there is a dupe
162 EntityTransferModule etm = new EntityTransferModule();
163
164 IConfigSource config = new IniConfigSource();
165 IConfig modulesConfig = config.AddConfig("Modules");
166 modulesConfig.Set("EntityTransferModule", etm.Name);
167 IConfig entityTransferConfig = config.AddConfig("EntityTransfer");
168
169 // In order to run a single threaded regression test we do not want the entity transfer module waiting
170 // for a callback from the destination scene before removing its avatar data.
171 entityTransferConfig.Set("wait_for_callback", false);
172
122 TestScene scene = new SceneHelpers().SetupScene(); 173 TestScene scene = new SceneHelpers().SetupScene();
174 SceneHelpers.SetupSceneModules(scene, config, etm);
123 SceneHelpers.AddScenePresence(scene, spUuid); 175 SceneHelpers.AddScenePresence(scene, spUuid);
124 SceneHelpers.AddScenePresence(scene, spUuid); 176 SceneHelpers.AddScenePresence(scene, spUuid);
125 177
@@ -133,7 +185,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
133 } 185 }
134 186
135 [Test] 187 [Test]
136 public void TestCloseAgent() 188 public void TestCloseClient()
137 { 189 {
138 TestHelpers.InMethod(); 190 TestHelpers.InMethod();
139// TestHelpers.EnableLogging(); 191// TestHelpers.EnableLogging();
@@ -141,7 +193,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
141 TestScene scene = new SceneHelpers().SetupScene(); 193 TestScene scene = new SceneHelpers().SetupScene();
142 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 194 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
143 195
144 scene.IncomingCloseAgent(sp.UUID, false); 196 scene.CloseAgent(sp.UUID, false);
145 197
146 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); 198 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
147 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); 199 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null);
@@ -187,7 +239,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
187 // *** This is the second stage, where the client established a child agent/scene presence using the 239 // *** This is the second stage, where the client established a child agent/scene presence using the
188 // circuit code given to the scene in stage 1 *** 240 // circuit code given to the scene in stage 1 ***
189 TestClient client = new TestClient(acd, scene); 241 TestClient client = new TestClient(acd, scene);
190 scene.AddNewClient(client, PresenceType.User); 242 scene.AddNewAgent(client, PresenceType.User);
191 243
192 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null); 244 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null);
193 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); 245 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
@@ -236,58 +288,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests
236// Assert.That(childPresence, Is.Not.Null); 288// Assert.That(childPresence, Is.Not.Null);
237// Assert.That(childPresence.IsChildAgent, Is.True); 289// Assert.That(childPresence.IsChildAgent, Is.True);
238 } 290 }
239
240// /// <summary>
241// /// Test adding a root agent to a scene. Doesn't yet actually complete crossing the agent into the scene.
242// /// </summary>
243// [Test]
244// public void T010_TestAddRootAgent()
245// {
246// TestHelpers.InMethod();
247//
248// string firstName = "testfirstname";
249//
250// AgentCircuitData agent = new AgentCircuitData();
251// agent.AgentID = agent1;
252// agent.firstname = firstName;
253// agent.lastname = "testlastname";
254// agent.SessionID = UUID.Random();
255// agent.SecureSessionID = UUID.Random();
256// agent.circuitcode = 123;
257// agent.BaseFolder = UUID.Zero;
258// agent.InventoryFolder = UUID.Zero;
259// agent.startpos = Vector3.Zero;
260// agent.CapsPath = GetRandomCapsObjectPath();
261// agent.ChildrenCapSeeds = new Dictionary<ulong, string>();
262// agent.child = true;
263//
264// scene.PresenceService.LoginAgent(agent.AgentID.ToString(), agent.SessionID, agent.SecureSessionID);
265//
266// string reason;
267// scene.NewUserConnection(agent, (uint)TeleportFlags.ViaLogin, out reason);
268// testclient = new TestClient(agent, scene);
269// scene.AddNewClient(testclient);
270//
271// ScenePresence presence = scene.GetScenePresence(agent1);
272//
273// Assert.That(presence, Is.Not.Null, "presence is null");
274// Assert.That(presence.Firstname, Is.EqualTo(firstName), "First name not same");
275// acd1 = agent;
276// }
277//
278// /// <summary>
279// /// Test removing an uncrossed root agent from a scene.
280// /// </summary>
281// [Test]
282// public void T011_TestRemoveRootAgent()
283// {
284// TestHelpers.InMethod();
285//
286// scene.RemoveClient(agent1);
287//
288// ScenePresence presence = scene.GetScenePresence(agent1);
289//
290// Assert.That(presence, Is.Null, "presence is not null");
291// }
292 } 291 }
293} \ No newline at end of file 292} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
new file mode 100644
index 0000000..9fa0a71
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
@@ -0,0 +1,90 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text;
32using System.Threading;
33using System.Timers;
34using Timer = System.Timers.Timer;
35using Nini.Config;
36using NUnit.Framework;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Communications;
40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.ClientStack.Linden;
43using OpenSim.Region.CoreModules.Framework;
44using OpenSim.Region.CoreModules.Framework.EntityTransfer;
45using OpenSim.Region.CoreModules.World.Serialiser;
46using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
47using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Framework.Interfaces;
49using OpenSim.Tests.Common;
50using OpenSim.Tests.Common.Mock;
51using GridRegion = OpenSim.Services.Interfaces.GridRegion;
52
53namespace OpenSim.Region.Framework.Scenes.Tests
54{
55 [TestFixture]
56 public class ScenePresenceCapabilityTests : OpenSimTestCase
57 {
58 [Test]
59 public void TestChildAgentSingleRegionCapabilities()
60 {
61 TestHelpers.InMethod();
62// TestHelpers.EnableLogging();
63
64 UUID spUuid = TestHelpers.ParseTail(0x1);
65
66 // XXX: This is not great since the use of statics will mean that this has to be manually cleaned up for
67 // any subsequent test.
68 // XXX: May replace with a mock IHttpServer later.
69 BaseHttpServer httpServer = new BaseHttpServer(99999);
70 MainServer.AddHttpServer(httpServer);
71 MainServer.Instance = httpServer;
72
73 CapabilitiesModule capsMod = new CapabilitiesModule();
74 TestScene scene = new SceneHelpers().SetupScene();
75 SceneHelpers.SetupSceneModules(scene, capsMod);
76
77 ScenePresence sp = SceneHelpers.AddChildScenePresence(scene, spUuid);
78 //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Not.Null);
79
80 // TODO: Need to add tests for other ICapabiltiesModule methods.
81
82// scene.IncomingCloseAgent(sp.UUID, false);
83// //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
84 scene.CloseAgent(sp.UUID, false);
85// Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
86
87 // TODO: Need to add tests for other ICapabiltiesModule methods.
88 }
89 }
90}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
index 8775949..b806a97 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
@@ -38,6 +38,7 @@ using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.CoreModules.Framework; 38using OpenSim.Region.CoreModules.Framework;
39using OpenSim.Region.CoreModules.Framework.EntityTransfer; 39using OpenSim.Region.CoreModules.Framework.EntityTransfer;
40using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; 40using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
41using OpenSim.Region.CoreModules.World.Permissions;
41using OpenSim.Tests.Common; 42using OpenSim.Tests.Common;
42using OpenSim.Tests.Common.Mock; 43using OpenSim.Tests.Common.Mock;
43 44
@@ -95,11 +96,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
95 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); 96 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
96 97
97 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 98 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
98 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); 99 TestClient tc = new TestClient(acd, sceneA);
99 List<TestClient> destinationTestClients = new List<TestClient>(); 100 List<TestClient> destinationTestClients = new List<TestClient>();
100 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); 101 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
101 102
102 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); 103 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
103 originalSp.AbsolutePosition = new Vector3(128, 32, 10); 104 originalSp.AbsolutePosition = new Vector3(128, 32, 10);
104 105
105// originalSp.Flying = true; 106// originalSp.Flying = true;
@@ -112,6 +113,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
112 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero); 113 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero);
113 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2))); 114 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2)));
114 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS; 115 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
116 moveArgs.SessionID = acd.SessionID;
115 117
116 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs); 118 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs);
117 119
@@ -158,5 +160,90 @@ namespace OpenSim.Region.Framework.Scenes.Tests
158 Assert.That(agentMovementCompleteReceived, Is.EqualTo(1)); 160 Assert.That(agentMovementCompleteReceived, Is.EqualTo(1));
159 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False); 161 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False);
160 } 162 }
163
164 /// <summary>
165 /// Test a cross attempt where the user can see into the neighbour but does not have permission to become
166 /// root there.
167 /// </summary>
168 [Test]
169 public void TestCrossOnSameSimulatorNoRootDestPerm()
170 {
171 TestHelpers.InMethod();
172// TestHelpers.EnableLogging();
173
174 UUID userId = TestHelpers.ParseTail(0x1);
175
176 EntityTransferModule etmA = new EntityTransferModule();
177 EntityTransferModule etmB = new EntityTransferModule();
178 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
179
180 IConfigSource config = new IniConfigSource();
181 IConfig modulesConfig = config.AddConfig("Modules");
182 modulesConfig.Set("EntityTransferModule", etmA.Name);
183 modulesConfig.Set("SimulationServices", lscm.Name);
184
185 SceneHelpers sh = new SceneHelpers();
186 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
187 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999);
188
189 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
190 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
191
192 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
193 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
194 // IsAdministrator if no permissions module is present is true.
195// SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new PermissionsModule(), etmB);
196
197 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
198 TestClient tc = new TestClient(acd, sceneA);
199 List<TestClient> destinationTestClients = new List<TestClient>();
200 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
201
202 // Make sure sceneB will not accept this avatar.
203 sceneB.RegionInfo.EstateSettings.PublicAccess = false;
204
205 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
206 originalSp.AbsolutePosition = new Vector3(128, 32, 10);
207
208 AgentUpdateArgs moveArgs = new AgentUpdateArgs();
209 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero);
210 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2)));
211 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
212 moveArgs.SessionID = acd.SessionID;
213
214 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs);
215
216 sceneA.Update(1);
217
218// Console.WriteLine("Second pos {0}", originalSp.AbsolutePosition);
219
220 // FIXME: This is a sufficient number of updates to for the presence to reach the northern border.
221 // But really we want to do this in a more robust way.
222 for (int i = 0; i < 100; i++)
223 {
224 sceneA.Update(1);
225// Console.WriteLine("Pos {0}", originalSp.AbsolutePosition);
226 }
227
228 // sceneA agent should still be root
229 ScenePresence spAfterCrossSceneA = sceneA.GetScenePresence(originalSp.UUID);
230 Assert.That(spAfterCrossSceneA.IsChildAgent, Is.False);
231
232 ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID);
233
234 // sceneB agent should also still be root
235 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
236
237 // sceneB should ignore unauthorized attempt to upgrade agent to root
238 TestClient sceneBTc = ((TestClient)spAfterCrossSceneB.ControllingClient);
239
240 int agentMovementCompleteReceived = 0;
241 sceneBTc.OnReceivedMoveAgentIntoRegion += (ri, pos, look) => agentMovementCompleteReceived++;
242
243 sceneBTc.CompleteMovement();
244
245 Assert.That(agentMovementCompleteReceived, Is.EqualTo(0));
246 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
247 }
161 } 248 }
162} \ No newline at end of file 249}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
index acaeb90..0911f00 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
@@ -111,15 +111,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
111 111
112 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; 112 SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart;
113 113
114 // We need to preserve this here because phys actor is removed by the sit.
115 Vector3 spPhysActorSize = m_sp.PhysicsActor.Size;
114 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); 116 m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero);
115 117
116 // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the
117 // default avatar.
118 // Curiously, Vector3.ToString() will not display the last two places of the float. For example,
119 // printing out npc.AbsolutePosition will give <0, 0, 0.8454993> not <0, 0, 0.845499337>
120 Assert.That( 118 Assert.That(
121 m_sp.AbsolutePosition, 119 m_sp.AbsolutePosition,
122 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, 0.845499337f))); 120 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, spPhysActorSize.Z / 2)));
123 121
124 m_sp.StandUp(); 122 m_sp.StandUp();
125 123
@@ -147,9 +145,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
147 145
148 Assert.That(part.SitTargetAvatar, Is.EqualTo(m_sp.UUID)); 146 Assert.That(part.SitTargetAvatar, Is.EqualTo(m_sp.UUID));
149 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId)); 147 Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId));
150 Assert.That( 148// Assert.That(
151 m_sp.AbsolutePosition, 149// m_sp.AbsolutePosition,
152 Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); 150// Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT));
153 Assert.That(m_sp.PhysicsActor, Is.Null); 151 Assert.That(m_sp.PhysicsActor, Is.Null);
154 152
155 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1)); 153 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1));
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index 8d94d29..fff542b 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.IO; 30using System.IO;
31using System.Net; 31using System.Net;
32using System.Text; 32using System.Text;
33using System.Threading;
33using Nini.Config; 34using Nini.Config;
34using NUnit.Framework; 35using NUnit.Framework;
35using OpenMetaverse; 36using OpenMetaverse;
@@ -107,7 +108,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
107 } 108 }
108 109
109 [Test] 110 [Test]
110 public void TestSameSimulatorIsolatedRegions() 111 public void TestSameSimulatorIsolatedRegionsV1()
111 { 112 {
112 TestHelpers.InMethod(); 113 TestHelpers.InMethod();
113// TestHelpers.EnableLogging(); 114// TestHelpers.EnableLogging();
@@ -136,14 +137,18 @@ namespace OpenSim.Region.Framework.Scenes.Tests
136 SceneHelpers.SetupSceneModules(sceneB, config, etmB); 137 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
137 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 138 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
138 139
140 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour
141 lscm.ServiceVersion = "SIMULATION/0.1";
142
139 Vector3 teleportPosition = new Vector3(10, 11, 12); 143 Vector3 teleportPosition = new Vector3(10, 11, 12);
140 Vector3 teleportLookAt = new Vector3(20, 21, 22); 144 Vector3 teleportLookAt = new Vector3(20, 21, 22);
141 145
142 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 146 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
143 sp.AbsolutePosition = new Vector3(30, 31, 32); 147 sp.AbsolutePosition = new Vector3(30, 31, 32);
144 148
145 List<TestClient> destinationTestClients = new List<TestClient>(); 149 List<TestClient> destinationTestClients = new List<TestClient>();
146 EntityTransferHelpers.SetUpInformClientOfNeighbour((TestClient)sp.ControllingClient, destinationTestClients); 150 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(
151 (TestClient)sp.ControllingClient, destinationTestClients);
147 152
148 sceneA.RequestTeleportLocation( 153 sceneA.RequestTeleportLocation(
149 sp.ControllingClient, 154 sp.ControllingClient,
@@ -176,6 +181,67 @@ namespace OpenSim.Region.Framework.Scenes.Tests
176// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt)); 181// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
177 } 182 }
178 183
184 [Test]
185 public void TestSameSimulatorIsolatedRegionsV2()
186 {
187 TestHelpers.InMethod();
188// TestHelpers.EnableLogging();
189
190 UUID userId = TestHelpers.ParseTail(0x1);
191
192 EntityTransferModule etmA = new EntityTransferModule();
193 EntityTransferModule etmB = new EntityTransferModule();
194 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
195
196 IConfigSource config = new IniConfigSource();
197 IConfig modulesConfig = config.AddConfig("Modules");
198 modulesConfig.Set("EntityTransferModule", etmA.Name);
199 modulesConfig.Set("SimulationServices", lscm.Name);
200
201 SceneHelpers sh = new SceneHelpers();
202 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
203 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1002, 1000);
204
205 SceneHelpers.SetupSceneModules(sceneA, config, etmA);
206 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
207 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
208
209 Vector3 teleportPosition = new Vector3(10, 11, 12);
210 Vector3 teleportLookAt = new Vector3(20, 21, 22);
211
212 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
213 sp.AbsolutePosition = new Vector3(30, 31, 32);
214
215 List<TestClient> destinationTestClients = new List<TestClient>();
216 EntityTransferHelpers.SetupSendRegionTeleportTriggersDestinationClientCreateAndCompleteMovement(
217 (TestClient)sp.ControllingClient, destinationTestClients);
218
219 sceneA.RequestTeleportLocation(
220 sp.ControllingClient,
221 sceneB.RegionInfo.RegionHandle,
222 teleportPosition,
223 teleportLookAt,
224 (uint)TeleportFlags.ViaLocation);
225
226 Assert.That(sceneA.GetScenePresence(userId), Is.Null);
227
228 ScenePresence sceneBSp = sceneB.GetScenePresence(userId);
229 Assert.That(sceneBSp, Is.Not.Null);
230 Assert.That(sceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName));
231 Assert.That(sceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition));
232
233 Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0));
234 Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0));
235 Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1));
236 Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0));
237
238 // TODO: Add assertions to check correct circuit details in both scenes.
239
240 // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
241 // position instead).
242// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
243 }
244
179 /// <summary> 245 /// <summary>
180 /// Test teleport procedures when the target simulator returns false when queried about access. 246 /// Test teleport procedures when the target simulator returns false when queried about access.
181 /// </summary> 247 /// </summary>
@@ -224,7 +290,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
224 Vector3 teleportPosition = new Vector3(10, 11, 12); 290 Vector3 teleportPosition = new Vector3(10, 11, 12);
225 Vector3 teleportLookAt = new Vector3(20, 21, 22); 291 Vector3 teleportLookAt = new Vector3(20, 21, 22);
226 292
227 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 293 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
228 sp.AbsolutePosition = preTeleportPosition; 294 sp.AbsolutePosition = preTeleportPosition;
229 295
230 // Make sceneB return false on query access 296 // Make sceneB return false on query access
@@ -300,7 +366,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
300 Vector3 teleportPosition = new Vector3(10, 11, 12); 366 Vector3 teleportPosition = new Vector3(10, 11, 12);
301 Vector3 teleportLookAt = new Vector3(20, 21, 22); 367 Vector3 teleportLookAt = new Vector3(20, 21, 22);
302 368
303 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 369 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
304 sp.AbsolutePosition = preTeleportPosition; 370 sp.AbsolutePosition = preTeleportPosition;
305 371
306 // Make sceneB refuse CreateAgent 372 // Make sceneB refuse CreateAgent
@@ -389,7 +455,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
389 Vector3 teleportPosition = new Vector3(10, 11, 12); 455 Vector3 teleportPosition = new Vector3(10, 11, 12);
390 Vector3 teleportLookAt = new Vector3(20, 21, 22); 456 Vector3 teleportLookAt = new Vector3(20, 21, 22);
391 457
392 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager); 458 ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId);
393 sp.AbsolutePosition = preTeleportPosition; 459 sp.AbsolutePosition = preTeleportPosition;
394 460
395 sceneA.RequestTeleportLocation( 461 sceneA.RequestTeleportLocation(
@@ -425,10 +491,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
425 } 491 }
426 492
427 [Test] 493 [Test]
428 public void TestSameSimulatorNeighbouringRegions() 494 public void TestSameSimulatorNeighbouringRegionsV1()
429 { 495 {
430 TestHelpers.InMethod(); 496 TestHelpers.InMethod();
431 TestHelpers.EnableLogging(); 497// TestHelpers.EnableLogging();
432 498
433 UUID userId = TestHelpers.ParseTail(0x1); 499 UUID userId = TestHelpers.ParseTail(0x1);
434 500
@@ -454,15 +520,18 @@ namespace OpenSim.Region.Framework.Scenes.Tests
454 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA); 520 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
455 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB); 521 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
456 522
523 // FIXME: Hack - this is here temporarily to revert back to older entity transfer behaviour
524 lscm.ServiceVersion = "SIMULATION/0.1";
525
457 Vector3 teleportPosition = new Vector3(10, 11, 12); 526 Vector3 teleportPosition = new Vector3(10, 11, 12);
458 Vector3 teleportLookAt = new Vector3(20, 21, 22); 527 Vector3 teleportLookAt = new Vector3(20, 21, 22);
459 528
460 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 529 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
461 TestClient tc = new TestClient(acd, sceneA, sh.SceneManager); 530 TestClient tc = new TestClient(acd, sceneA);
462 List<TestClient> destinationTestClients = new List<TestClient>(); 531 List<TestClient> destinationTestClients = new List<TestClient>();
463 EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients); 532 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
464 533
465 ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager); 534 ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
466 beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32); 535 beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32);
467 536
468 Assert.That(beforeSceneASp, Is.Not.Null); 537 Assert.That(beforeSceneASp, Is.Not.Null);
@@ -506,5 +575,89 @@ namespace OpenSim.Region.Framework.Scenes.Tests
506 575
507// TestHelpers.DisableLogging(); 576// TestHelpers.DisableLogging();
508 } 577 }
578
579 [Test]
580 public void TestSameSimulatorNeighbouringRegionsV2()
581 {
582 TestHelpers.InMethod();
583// TestHelpers.EnableLogging();
584
585 UUID userId = TestHelpers.ParseTail(0x1);
586
587 EntityTransferModule etmA = new EntityTransferModule();
588 EntityTransferModule etmB = new EntityTransferModule();
589 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
590
591 IConfigSource config = new IniConfigSource();
592 IConfig modulesConfig = config.AddConfig("Modules");
593 modulesConfig.Set("EntityTransferModule", etmA.Name);
594 modulesConfig.Set("SimulationServices", lscm.Name);
595
596 SceneHelpers sh = new SceneHelpers();
597 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
598 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1001, 1000);
599
600 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
601 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
602 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
603
604 Vector3 teleportPosition = new Vector3(10, 11, 12);
605 Vector3 teleportLookAt = new Vector3(20, 21, 22);
606
607 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
608 TestClient tc = new TestClient(acd, sceneA);
609 List<TestClient> destinationTestClients = new List<TestClient>();
610 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
611
612 ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
613 beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32);
614
615 Assert.That(beforeSceneASp, Is.Not.Null);
616 Assert.That(beforeSceneASp.IsChildAgent, Is.False);
617
618 ScenePresence beforeSceneBSp = sceneB.GetScenePresence(userId);
619 Assert.That(beforeSceneBSp, Is.Not.Null);
620 Assert.That(beforeSceneBSp.IsChildAgent, Is.True);
621
622 // Here, we need to make clientA's receipt of SendRegionTeleport trigger clientB's CompleteMovement(). This
623 // is to operate the teleport V2 mechanism where the EntityTransferModule will first request the client to
624 // CompleteMovement to the region and then call UpdateAgent to the destination region to confirm the receipt
625 // Both these operations will occur on different threads and will wait for each other.
626 // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1
627 // test protocol, where we are trying to avoid unpredictable async operations in regression tests.
628 tc.OnTestClientSendRegionTeleport
629 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL)
630 => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null);
631
632 sceneA.RequestTeleportLocation(
633 beforeSceneASp.ControllingClient,
634 sceneB.RegionInfo.RegionHandle,
635 teleportPosition,
636 teleportLookAt,
637 (uint)TeleportFlags.ViaLocation);
638
639 ScenePresence afterSceneASp = sceneA.GetScenePresence(userId);
640 Assert.That(afterSceneASp, Is.Not.Null);
641 Assert.That(afterSceneASp.IsChildAgent, Is.True);
642
643 ScenePresence afterSceneBSp = sceneB.GetScenePresence(userId);
644 Assert.That(afterSceneBSp, Is.Not.Null);
645 Assert.That(afterSceneBSp.IsChildAgent, Is.False);
646 Assert.That(afterSceneBSp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneB.RegionInfo.RegionName));
647 Assert.That(afterSceneBSp.AbsolutePosition, Is.EqualTo(teleportPosition));
648
649 Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(0));
650 Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(1));
651 Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(1));
652 Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0));
653
654 // TODO: Add assertions to check correct circuit details in both scenes.
655
656 // Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
657 // position instead).
658// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
659
660// TestHelpers.DisableLogging();
661 }
509 } 662 }
510} 663}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs
new file mode 100644
index 0000000..1667002
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs
@@ -0,0 +1,71 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using NUnit.Framework;
32using OpenMetaverse;
33using OpenSim.Framework;
34using OpenSim.Framework.Communications;
35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock;
38
39namespace OpenSim.Region.Framework.Scenes.Tests
40{
41 [TestFixture]
42 public class SceneStatisticsTests : OpenSimTestCase
43 {
44 private TestScene m_scene;
45
46 [SetUp]
47 public void Init()
48 {
49 m_scene = new SceneHelpers().SetupScene();
50 }
51
52 [Test]
53 public void TestAddRemovePhysicalLinkset()
54 {
55 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(0));
56
57 UUID ownerId = TestHelpers.ParseTail(0x1);
58 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(3, ownerId, "so1", 0x10);
59 so1.ScriptSetPhysicsStatus(true);
60 m_scene.AddSceneObject(so1);
61
62 Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(3));
63 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(3));
64
65 m_scene.DeleteSceneObject(so1, false);
66
67 Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(0));
68 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(0));
69 }
70 }
71} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs
new file mode 100644
index 0000000..9a97acc
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs
@@ -0,0 +1,119 @@
1/*
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions are met:
4 * * Redistributions of source code must retain the above copyright
5 * notice, this list of conditions and the following disclaimer.
6 * * Redistributions in binary form must reproduce the above copyright
7 * notice, this list of conditions and the following disclaimer in the
8 * documentation and/or other materials provided with the distribution.
9 * * Neither the name of the OpenSimulator Project nor the
10 * names of its contributors may be used to endorse or promote products
11 * derived from this software without specific prior written permission.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25using System;
26using Nini.Config;
27using NUnit.Framework;
28using OpenMetaverse;
29using OpenSim.Framework;
30using OpenSim.Region.CoreModules.World.Estate;
31using OpenSim.Region.Framework.Scenes;
32using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Services.Interfaces;
34using OpenSim.Tests.Common;
35using OpenSim.Tests.Common.Mock;
36
37namespace OpenSim.Region.Framework.Scenes.Tests
38{
39 /// <summary>
40 /// Scene telehub tests
41 /// </summary>
42 /// <remarks>
43 /// TODO: Tests which run through normal functionality. Currently, the only test is one that checks behaviour
44 /// in the case of an error condition
45 /// </remarks>
46 [TestFixture]
47 public class SceneTelehubTests : OpenSimTestCase
48 {
49 /// <summary>
50 /// Test for desired behaviour when a telehub has no spawn points
51 /// </summary>
52 [Test]
53 public void TestNoTelehubSpawnPoints()
54 {
55 TestHelpers.InMethod();
56// TestHelpers.EnableLogging();
57
58 EstateManagementModule emm = new EstateManagementModule();
59
60 SceneHelpers sh = new SceneHelpers();
61 Scene scene = sh.SetupScene();
62 SceneHelpers.SetupSceneModules(scene, emm);
63
64 UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1);
65
66 SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner);
67
68 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId);
69 scene.RegionInfo.EstateSettings.AllowDirectTeleport = false;
70
71 // Must still be possible to successfully log in
72 UUID loggingInUserId = TestHelpers.ParseTail(0x2);
73
74 UserAccount ua
75 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
76
77 SceneHelpers.AddScenePresence(scene, ua);
78
79 Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null);
80 }
81
82 /// <summary>
83 /// Test for desired behaviour when the scene object nominated as a telehub object does not exist.
84 /// </summary>
85 [Test]
86 public void TestNoTelehubSceneObject()
87 {
88 TestHelpers.InMethod();
89// TestHelpers.EnableLogging();
90
91 EstateManagementModule emm = new EstateManagementModule();
92
93 SceneHelpers sh = new SceneHelpers();
94 Scene scene = sh.SetupScene();
95 SceneHelpers.SetupSceneModules(scene, emm);
96
97 UUID telehubSceneObjectOwner = TestHelpers.ParseTail(0x1);
98
99 SceneObjectGroup telehubSo = SceneHelpers.AddSceneObject(scene, "telehubObject", telehubSceneObjectOwner);
100 SceneObjectGroup spawnPointSo = SceneHelpers.AddSceneObject(scene, "spawnpointObject", telehubSceneObjectOwner);
101
102 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "connect", telehubSo.LocalId);
103 emm.HandleOnEstateManageTelehub(null, UUID.Zero, UUID.Zero, "spawnpoint add", spawnPointSo.LocalId);
104 scene.RegionInfo.EstateSettings.AllowDirectTeleport = false;
105
106 scene.DeleteSceneObject(telehubSo, false);
107
108 // Must still be possible to successfully log in
109 UUID loggingInUserId = TestHelpers.ParseTail(0x2);
110
111 UserAccount ua
112 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
113
114 SceneHelpers.AddScenePresence(scene, ua);
115
116 Assert.That(scene.GetScenePresence(loggingInUserId), Is.Not.Null);
117 }
118 }
119} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index dd27294..1e59e3f 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -62,8 +62,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero); 62 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero);
63 m_assetService.Store(corruptAsset); 63 m_assetService.Store(corruptAsset);
64 64
65 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 65 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, AssetType.Object, foundAssetUuids); 66 m_uuidGatherer.GatherAssetUuids(corruptAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
67 67
68 // We count the uuid as gathered even if the asset itself is corrupt. 68 // We count the uuid as gathered even if the asset itself is corrupt.
69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 69 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -78,9 +78,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
78 TestHelpers.InMethod(); 78 TestHelpers.InMethod();
79 79
80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); 80 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666");
81 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 81 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
82 82
83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, AssetType.Object, foundAssetUuids); 83 m_uuidGatherer.GatherAssetUuids(missingAssetUuid, (sbyte)AssetType.Object, foundAssetUuids);
84 84
85 // We count the uuid as gathered even if the asset itself is missing. 85 // We count the uuid as gathered even if the asset itself is missing.
86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1)); 86 Assert.That(foundAssetUuids.Count, Is.EqualTo(1));
@@ -103,8 +103,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString()); 103 AssetBase ncAsset = AssetHelpers.CreateNotecardAsset(ncAssetId, soAssetId.ToString());
104 m_assetService.Store(ncAsset); 104 m_assetService.Store(ncAsset);
105 105
106 IDictionary<UUID, AssetType> foundAssetUuids = new Dictionary<UUID, AssetType>(); 106 IDictionary<UUID, sbyte> foundAssetUuids = new Dictionary<UUID, sbyte>();
107 m_uuidGatherer.GatherAssetUuids(ncAssetId, AssetType.Notecard, foundAssetUuids); 107 m_uuidGatherer.GatherAssetUuids(ncAssetId, (sbyte)AssetType.Notecard, foundAssetUuids);
108 108
109 // We count the uuid as gathered even if the asset itself is corrupt. 109 // We count the uuid as gathered even if the asset itself is corrupt.
110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2)); 110 Assert.That(foundAssetUuids.Count, Is.EqualTo(2));
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index b09ae39..67655d6 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -34,9 +34,11 @@ using System.Threading;
34using log4net; 34using log4net;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenMetaverse.Assets; 36using OpenMetaverse.Assets;
37using OpenMetaverse.StructuredData;
37using OpenSim.Framework; 38using OpenSim.Framework;
38using OpenSim.Region.Framework.Scenes.Serialization; 39using OpenSim.Region.Framework.Scenes.Serialization;
39using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
41using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
40 42
41namespace OpenSim.Region.Framework.Scenes 43namespace OpenSim.Region.Framework.Scenes
42{ 44{
@@ -82,29 +84,33 @@ namespace OpenSim.Region.Framework.Scenes
82 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> 84 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param>
83 /// <param name="assetType">The type of the asset for the uuid given</param> 85 /// <param name="assetType">The type of the asset for the uuid given</param>
84 /// <param name="assetUuids">The assets gathered</param> 86 /// <param name="assetUuids">The assets gathered</param>
85 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 87 public void GatherAssetUuids(UUID assetUuid, sbyte assetType, IDictionary<UUID, sbyte> assetUuids)
86 { 88 {
87 try 89 try
88 { 90 {
89 assetUuids[assetUuid] = assetType; 91 assetUuids[assetUuid] = assetType;
90 92
91 if (AssetType.Bodypart == assetType || AssetType.Clothing == assetType) 93 if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType)
92 { 94 {
93 GetWearableAssetUuids(assetUuid, assetUuids); 95 GetWearableAssetUuids(assetUuid, assetUuids);
94 } 96 }
95 else if (AssetType.Gesture == assetType) 97 else if ((sbyte)AssetType.Gesture == assetType)
96 { 98 {
97 GetGestureAssetUuids(assetUuid, assetUuids); 99 GetGestureAssetUuids(assetUuid, assetUuids);
98 } 100 }
99 else if (AssetType.Notecard == assetType) 101 else if ((sbyte)AssetType.Notecard == assetType)
100 { 102 {
101 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 103 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
102 } 104 }
103 else if (AssetType.LSLText == assetType) 105 else if ((sbyte)AssetType.LSLText == assetType)
104 { 106 {
105 GetTextEmbeddedAssetUuids(assetUuid, assetUuids); 107 GetTextEmbeddedAssetUuids(assetUuid, assetUuids);
106 } 108 }
107 else if (AssetType.Object == assetType) 109 else if ((sbyte)OpenSimAssetType.Material == assetType)
110 {
111 GetMaterialAssetUuids(assetUuid, assetUuids);
112 }
113 else if ((sbyte)AssetType.Object == assetType)
108 { 114 {
109 GetSceneObjectAssetUuids(assetUuid, assetUuids); 115 GetSceneObjectAssetUuids(assetUuid, assetUuids);
110 } 116 }
@@ -131,7 +137,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset. 137 /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset.
132 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown. 138 /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown.
133 /// </param> 139 /// </param>
134 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids) 140 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, sbyte> assetUuids)
135 { 141 {
136// m_log.DebugFormat( 142// m_log.DebugFormat(
137// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); 143// "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
@@ -151,7 +157,7 @@ namespace OpenSim.Region.Framework.Scenes
151 { 157 {
152 // Get the prim's default texture. This will be used for faces which don't have their own texture 158 // Get the prim's default texture. This will be used for faces which don't have their own texture
153 if (textureEntry.DefaultTexture != null) 159 if (textureEntry.DefaultTexture != null)
154 assetUuids[textureEntry.DefaultTexture.TextureID] = AssetType.Texture; 160 assetUuids[textureEntry.DefaultTexture.TextureID] = (sbyte)AssetType.Texture;
155 161
156 if (textureEntry.FaceTextures != null) 162 if (textureEntry.FaceTextures != null)
157 { 163 {
@@ -159,15 +165,37 @@ namespace OpenSim.Region.Framework.Scenes
159 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures) 165 foreach (Primitive.TextureEntryFace texture in textureEntry.FaceTextures)
160 { 166 {
161 if (texture != null) 167 if (texture != null)
162 assetUuids[texture.TextureID] = AssetType.Texture; 168 assetUuids[texture.TextureID] = (sbyte)AssetType.Texture;
163 } 169 }
164 } 170 }
165 } 171 }
166 172
167 // If the prim is a sculpt then preserve this information too 173 // If the prim is a sculpt then preserve this information too
168 if (part.Shape.SculptTexture != UUID.Zero) 174 if (part.Shape.SculptTexture != UUID.Zero)
169 assetUuids[part.Shape.SculptTexture] = AssetType.Texture; 175 assetUuids[part.Shape.SculptTexture] = (sbyte)AssetType.Texture;
170 176
177 if (part.Shape.ProjectionTextureUUID != UUID.Zero)
178 assetUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture;
179
180 if (part.CollisionSound != UUID.Zero)
181 assetUuids[part.CollisionSound] = (sbyte)AssetType.Sound;
182
183 if (part.ParticleSystem.Length > 0)
184 {
185 try
186 {
187 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
188 if (ps.Texture != UUID.Zero)
189 assetUuids[ps.Texture] = (sbyte)AssetType.Texture;
190 }
191 catch (Exception e)
192 {
193 m_log.WarnFormat(
194 "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.",
195 part.Name, part.UUID, sceneObject.Name, sceneObject.UUID);
196 }
197 }
198
171 TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 199 TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
172 200
173 // Now analyze this prim's inventory items to preserve all the uuids that they reference 201 // Now analyze this prim's inventory items to preserve all the uuids that they reference
@@ -178,8 +206,18 @@ namespace OpenSim.Region.Framework.Scenes
178// tii.Name, tii.Type, part.Name, part.UUID); 206// tii.Name, tii.Type, part.Name, part.UUID);
179 207
180 if (!assetUuids.ContainsKey(tii.AssetID)) 208 if (!assetUuids.ContainsKey(tii.AssetID))
181 GatherAssetUuids(tii.AssetID, (AssetType)tii.Type, assetUuids); 209 GatherAssetUuids(tii.AssetID, (sbyte)tii.Type, assetUuids);
182 } 210 }
211
212 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
213 // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and
214 // inventory transfer. There needs to be a way for a module to register a method without assuming a
215 // Scene.EventManager is present.
216// part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
217
218
219 // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs
220 GatherMaterialsUuids(part, assetUuids);
183 } 221 }
184 catch (Exception e) 222 catch (Exception e)
185 { 223 {
@@ -190,7 +228,7 @@ namespace OpenSim.Region.Framework.Scenes
190 } 228 }
191 } 229 }
192 } 230 }
193 231
194// /// <summary> 232// /// <summary>
195// /// The callback made when we request the asset for an object from the asset service. 233// /// The callback made when we request the asset for an object from the asset service.
196// /// </summary> 234// /// </summary>
@@ -205,6 +243,75 @@ namespace OpenSim.Region.Framework.Scenes
205// } 243// }
206 244
207 /// <summary> 245 /// <summary>
246 /// Gather all of the texture asset UUIDs used to reference "Materials" such as normal and specular maps
247 /// stored in legacy format in part.DynAttrs
248 /// </summary>
249 /// <param name="part"></param>
250 /// <param name="assetUuids"></param>
251 //public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, AssetType> assetUuids)
252 public void GatherMaterialsUuids(SceneObjectPart part, IDictionary<UUID, sbyte> assetUuids)
253 {
254 // scan thru the dynAttrs map of this part for any textures used as materials
255 OSD osdMaterials = null;
256
257 lock (part.DynAttrs)
258 {
259 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
260 {
261 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
262
263 if (materialsStore == null)
264 return;
265
266 materialsStore.TryGetValue("Materials", out osdMaterials);
267 }
268
269 if (osdMaterials != null)
270 {
271 //m_log.Info("[UUID Gatherer]: found Materials: " + OSDParser.SerializeJsonString(osd));
272
273 if (osdMaterials is OSDArray)
274 {
275 OSDArray matsArr = osdMaterials as OSDArray;
276 foreach (OSDMap matMap in matsArr)
277 {
278 try
279 {
280 if (matMap.ContainsKey("Material"))
281 {
282 OSDMap mat = matMap["Material"] as OSDMap;
283 if (mat.ContainsKey("NormMap"))
284 {
285 UUID normalMapId = mat["NormMap"].AsUUID();
286 if (normalMapId != UUID.Zero)
287 {
288 assetUuids[normalMapId] = (sbyte)AssetType.Texture;
289 //m_log.Info("[UUID Gatherer]: found normal map ID: " + normalMapId.ToString());
290 }
291 }
292 if (mat.ContainsKey("SpecMap"))
293 {
294 UUID specularMapId = mat["SpecMap"].AsUUID();
295 if (specularMapId != UUID.Zero)
296 {
297 assetUuids[specularMapId] = (sbyte)AssetType.Texture;
298 //m_log.Info("[UUID Gatherer]: found specular map ID: " + specularMapId.ToString());
299 }
300 }
301 }
302
303 }
304 catch (Exception e)
305 {
306 m_log.Warn("[UUID Gatherer]: exception getting materials: " + e.Message);
307 }
308 }
309 }
310 }
311 }
312 }
313
314 /// <summary>
208 /// Get an asset synchronously, potentially using an asynchronous callback. If the 315 /// Get an asset synchronously, potentially using an asynchronous callback. If the
209 /// asynchronous callback is used, we will wait for it to complete. 316 /// asynchronous callback is used, we will wait for it to complete.
210 /// </summary> 317 /// </summary>
@@ -242,7 +349,7 @@ namespace OpenSim.Region.Framework.Scenes
242 /// </summary> 349 /// </summary>
243 /// <param name="scriptUuid"></param> 350 /// <param name="scriptUuid"></param>
244 /// <param name="assetUuids">Dictionary in which to record the references</param> 351 /// <param name="assetUuids">Dictionary in which to record the references</param>
245 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, AssetType> assetUuids) 352 private void GetTextEmbeddedAssetUuids(UUID embeddingAssetId, IDictionary<UUID, sbyte> assetUuids)
246 { 353 {
247// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId); 354// m_log.DebugFormat("[ASSET GATHERER]: Getting assets for uuid references in asset {0}", embeddingAssetId);
248 355
@@ -262,7 +369,7 @@ namespace OpenSim.Region.Framework.Scenes
262 369
263 // Embedded asset references (if not false positives) could be for many types of asset, so we will 370 // Embedded asset references (if not false positives) could be for many types of asset, so we will
264 // label these as unknown. 371 // label these as unknown.
265 assetUuids[uuid] = AssetType.Unknown; 372 assetUuids[uuid] = (sbyte)AssetType.Unknown;
266 } 373 }
267 } 374 }
268 } 375 }
@@ -272,7 +379,7 @@ namespace OpenSim.Region.Framework.Scenes
272 /// </summary> 379 /// </summary>
273 /// <param name="wearableAssetUuid"></param> 380 /// <param name="wearableAssetUuid"></param>
274 /// <param name="assetUuids">Dictionary in which to record the references</param> 381 /// <param name="assetUuids">Dictionary in which to record the references</param>
275 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, AssetType> assetUuids) 382 private void GetWearableAssetUuids(UUID wearableAssetUuid, IDictionary<UUID, sbyte> assetUuids)
276 { 383 {
277 AssetBase assetBase = GetAsset(wearableAssetUuid); 384 AssetBase assetBase = GetAsset(wearableAssetUuid);
278 385
@@ -287,7 +394,7 @@ namespace OpenSim.Region.Framework.Scenes
287 394
288 foreach (UUID uuid in wearableAsset.Textures.Values) 395 foreach (UUID uuid in wearableAsset.Textures.Values)
289 { 396 {
290 assetUuids[uuid] = AssetType.Texture; 397 assetUuids[uuid] = (sbyte)AssetType.Texture;
291 } 398 }
292 } 399 }
293 } 400 }
@@ -299,7 +406,7 @@ namespace OpenSim.Region.Framework.Scenes
299 /// </summary> 406 /// </summary>
300 /// <param name="sceneObject"></param> 407 /// <param name="sceneObject"></param>
301 /// <param name="assetUuids"></param> 408 /// <param name="assetUuids"></param>
302 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, AssetType> assetUuids) 409 private void GetSceneObjectAssetUuids(UUID sceneObjectUuid, IDictionary<UUID, sbyte> assetUuids)
303 { 410 {
304 AssetBase objectAsset = GetAsset(sceneObjectUuid); 411 AssetBase objectAsset = GetAsset(sceneObjectUuid);
305 412
@@ -328,7 +435,7 @@ namespace OpenSim.Region.Framework.Scenes
328 /// </summary> 435 /// </summary>
329 /// <param name="gestureUuid"></param> 436 /// <param name="gestureUuid"></param>
330 /// <param name="assetUuids"></param> 437 /// <param name="assetUuids"></param>
331 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, AssetType> assetUuids) 438 private void GetGestureAssetUuids(UUID gestureUuid, IDictionary<UUID, sbyte> assetUuids)
332 { 439 {
333 AssetBase assetBase = GetAsset(gestureUuid); 440 AssetBase assetBase = GetAsset(gestureUuid);
334 if (null == assetBase) 441 if (null == assetBase)
@@ -362,9 +469,29 @@ namespace OpenSim.Region.Framework.Scenes
362 // If it can be parsed as a UUID, it is an asset ID 469 // If it can be parsed as a UUID, it is an asset ID
363 UUID uuid; 470 UUID uuid;
364 if (UUID.TryParse(id, out uuid)) 471 if (UUID.TryParse(id, out uuid))
365 assetUuids[uuid] = AssetType.Animation; 472 assetUuids[uuid] = (sbyte)AssetType.Animation;
366 } 473 }
367 } 474 }
475
476 /// <summary>
477 /// Get the asset uuid's referenced in a material.
478 /// </summary>
479 private void GetMaterialAssetUuids(UUID materialUuid, IDictionary<UUID, sbyte> assetUuids)
480 {
481 AssetBase assetBase = GetAsset(materialUuid);
482 if (null == assetBase)
483 return;
484
485 OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(assetBase.Data);
486
487 UUID normMap = mat["NormMap"].AsUUID();
488 if (normMap != UUID.Zero)
489 assetUuids[normMap] = (sbyte)AssetType.Texture;
490
491 UUID specMap = mat["SpecMap"].AsUUID();
492 if (specMap != UUID.Zero)
493 assetUuids[specMap] = (sbyte)AssetType.Texture;
494 }
368 } 495 }
369 496
370 public class HGUuidGatherer : UuidGatherer 497 public class HGUuidGatherer : UuidGatherer
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index dd72cfb..373ed41 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -660,6 +660,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
660 public event BakeTerrain OnBakeTerrain; 660 public event BakeTerrain OnBakeTerrain;
661 public event EstateChangeInfo OnEstateChangeInfo; 661 public event EstateChangeInfo OnEstateChangeInfo;
662 public event EstateManageTelehub OnEstateManageTelehub; 662 public event EstateManageTelehub OnEstateManageTelehub;
663 public event CachedTextureRequest OnCachedTextureRequest;
663 public event SetAppearance OnSetAppearance; 664 public event SetAppearance OnSetAppearance;
664 public event AvatarNowWearing OnAvatarNowWearing; 665 public event AvatarNowWearing OnAvatarNowWearing;
665 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; 666 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
@@ -687,6 +688,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
687 public event Action<IClientAPI, bool> OnCompleteMovementToRegion; 688 public event Action<IClientAPI, bool> OnCompleteMovementToRegion;
688 public event UpdateAgent OnPreAgentUpdate; 689 public event UpdateAgent OnPreAgentUpdate;
689 public event UpdateAgent OnAgentUpdate; 690 public event UpdateAgent OnAgentUpdate;
691 public event UpdateAgent OnAgentCameraUpdate;
690 public event AgentRequestSit OnAgentRequestSit; 692 public event AgentRequestSit OnAgentRequestSit;
691 public event AgentSit OnAgentSit; 693 public event AgentSit OnAgentSit;
692 public event AvatarPickerRequest OnAvatarPickerRequest; 694 public event AvatarPickerRequest OnAvatarPickerRequest;
@@ -906,7 +908,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
906 908
907 public void Start() 909 public void Start()
908 { 910 {
909 m_scene.AddNewClient(this, PresenceType.User); 911 m_scene.AddNewAgent(this, PresenceType.User);
910 912
911 // Mimicking LLClientView which gets always set appearance from client. 913 // Mimicking LLClientView which gets always set appearance from client.
912 AvatarAppearance appearance; 914 AvatarAppearance appearance;
@@ -943,13 +945,18 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
943 { 945 {
944 946
945 } 947 }
948
949 public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures)
950 {
946 951
952 }
953
947 public void SendStartPingCheck(byte seq) 954 public void SendStartPingCheck(byte seq)
948 { 955 {
949 956
950 } 957 }
951 958
952 public void SendKillObject(ulong regionHandle, List<uint> localID) 959 public void SendKillObject(List<uint> localID)
953 { 960 {
954 961
955 } 962 }
@@ -1681,7 +1688,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1681 { 1688 {
1682 } 1689 }
1683 1690
1684 public void StopFlying(ISceneEntity presence) 1691 public void SendAgentTerseUpdate(ISceneEntity presence)
1685 { 1692 {
1686 } 1693 }
1687 1694
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
index 992f38e..ec18db0 100644
--- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
30using System.Reflection; 31using System.Reflection;
31using System.Text; 32using System.Text;
32using log4net; 33using log4net;
@@ -51,7 +52,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
51 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LindenUDPInfoModule")] 52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LindenUDPInfoModule")]
52 public class LindenUDPInfoModule : ISharedRegionModule 53 public class LindenUDPInfoModule : ISharedRegionModule
53 { 54 {
54// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 56
56 protected Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>(); 57 protected Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
57 58
@@ -130,6 +131,15 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
130 "Go on/off emergency monitoring mode", 131 "Go on/off emergency monitoring mode",
131 "Go on/off emergency monitoring mode", 132 "Go on/off emergency monitoring mode",
132 HandleEmergencyMonitoring); 133 HandleEmergencyMonitoring);
134
135 scene.AddCommand(
136 "Comms", this, "show client stats",
137 "show client stats [first_name last_name]",
138 "Show client request stats",
139 "Without the 'first_name last_name' option, all clients are shown."
140 + " With the 'first_name last_name' option only a specific client is shown.",
141 (mod, cmd) => MainConsole.Instance.Output(HandleClientStatsReport(cmd)));
142
133 } 143 }
134 144
135 public void RemoveRegion(Scene scene) 145 public void RemoveRegion(Scene scene)
@@ -294,7 +304,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
294 private string GetImageQueuesReport(string[] showParams) 304 private string GetImageQueuesReport(string[] showParams)
295 { 305 {
296 if (showParams.Length < 5 || showParams.Length > 6) 306 if (showParams.Length < 5 || showParams.Length > 6)
297 return "Usage: image queues show <first-name> <last-name> [full]"; 307 return "Usage: show image queues <first-name> <last-name> [full]";
298 308
299 string firstName = showParams[3]; 309 string firstName = showParams[3];
300 string lastName = showParams[4]; 310 string lastName = showParams[4];
@@ -385,7 +395,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
385 report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding)); 395 report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding));
386 396
387 report.AppendFormat( 397 report.AppendFormat(
388 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n", 398 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7}\n",
389 "Since", 399 "Since",
390 "Pkts", 400 "Pkts",
391 "Pkts", 401 "Pkts",
@@ -397,12 +407,11 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
397 "Q Pkts", 407 "Q Pkts",
398 "Q Pkts", 408 "Q Pkts",
399 "Q Pkts", 409 "Q Pkts",
400 "Q Pkts",
401 "Q Pkts"); 410 "Q Pkts");
402 411
403 report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", ""); 412 report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", "");
404 report.AppendFormat( 413 report.AppendFormat(
405 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n", 414 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7}\n",
406 "Last In", 415 "Last In",
407 "In", 416 "In",
408 "Out", 417 "Out",
@@ -414,8 +423,7 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
414 "Cloud", 423 "Cloud",
415 "Task", 424 "Task",
416 "Texture", 425 "Texture",
417 "Asset", 426 "Asset");
418 "State");
419 427
420 lock (m_scenes) 428 lock (m_scenes)
421 { 429 {
@@ -424,24 +432,24 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
424 scene.ForEachClient( 432 scene.ForEachClient(
425 delegate(IClientAPI client) 433 delegate(IClientAPI client)
426 { 434 {
427 bool isChild = client.SceneAgent.IsChildAgent;
428 if (isChild && !showChildren)
429 return;
430
431 string name = client.Name;
432 if (pname != "" && name != pname)
433 return;
434
435 string regionName = scene.RegionInfo.RegionName;
436
437 report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
438 report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
439 report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
440
441 if (client is IStatsCollector) 435 if (client is IStatsCollector)
442 { 436 {
443 IStatsCollector stats = (IStatsCollector)client; 437
438 bool isChild = client.SceneAgent.IsChildAgent;
439 if (isChild && !showChildren)
440 return;
444 441
442 string name = client.Name;
443 if (pname != "" && name != pname)
444 return;
445
446 string regionName = scene.RegionInfo.RegionName;
447
448 report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
449 report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
450 report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
451
452 IStatsCollector stats = (IStatsCollector)client;
445 report.AppendLine(stats.Report()); 453 report.AppendLine(stats.Report());
446 } 454 }
447 }); 455 });
@@ -587,6 +595,115 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden
587 (throttleRates.Asset * 8) / 1000); 595 (throttleRates.Asset * 8) / 1000);
588 596
589 return report.ToString(); 597 return report.ToString();
590 } 598 }
599
600 /// <summary>
601 /// Show client stats data
602 /// </summary>
603 /// <param name="showParams"></param>
604 /// <returns></returns>
605 protected string HandleClientStatsReport(string[] showParams)
606 {
607 // NOTE: This writes to m_log on purpose. We want to store this information
608 // in case we need to analyze it later.
609 //
610 if (showParams.Length <= 4)
611 {
612 m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", "Region", "Name", "Root", "Time", "Reqs/min", "AgentUpdates");
613 foreach (Scene scene in m_scenes.Values)
614 {
615 scene.ForEachClient(
616 delegate(IClientAPI client)
617 {
618 if (client is LLClientView)
619 {
620 LLClientView llClient = client as LLClientView;
621 ClientInfo cinfo = llClient.UDPClient.GetClientInfo();
622 int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum();
623 avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1);
624
625 string childAgentStatus;
626
627 if (llClient.SceneAgent != null)
628 childAgentStatus = llClient.SceneAgent.IsChildAgent ? "N" : "Y";
629 else
630 childAgentStatus = "Off!";
631
632 m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}",
633 scene.RegionInfo.RegionName, llClient.Name,
634 childAgentStatus,
635 (DateTime.Now - cinfo.StartedTime).Minutes,
636 avg_reqs,
637 string.Format(
638 "{0} ({1:0.00}%)",
639 llClient.TotalAgentUpdates,
640 (float)cinfo.SyncRequests["AgentUpdate"] / llClient.TotalAgentUpdates * 100));
641 }
642 });
643 }
644 return string.Empty;
645 }
646
647 string fname = "", lname = "";
648
649 if (showParams.Length > 3)
650 fname = showParams[3];
651 if (showParams.Length > 4)
652 lname = showParams[4];
653
654 foreach (Scene scene in m_scenes.Values)
655 {
656 scene.ForEachClient(
657 delegate(IClientAPI client)
658 {
659 if (client is LLClientView)
660 {
661 LLClientView llClient = client as LLClientView;
662
663 if (llClient.Name == fname + " " + lname)
664 {
665
666 ClientInfo cinfo = llClient.GetClientInfo();
667 AgentCircuitData aCircuit = scene.AuthenticateHandler.GetAgentCircuitData(llClient.CircuitCode);
668 if (aCircuit == null) // create a dummy one
669 aCircuit = new AgentCircuitData();
670
671 if (!llClient.SceneAgent.IsChildAgent)
672 m_log.InfoFormat("[INFO]: {0} # {1} # {2}", llClient.Name, aCircuit.Viewer, aCircuit.Id0);
673
674 int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum();
675 avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1);
676
677 m_log.InfoFormat("[INFO]:");
678 m_log.InfoFormat("[INFO]: {0} # {1} # Time: {2}min # Avg Reqs/min: {3}", scene.RegionInfo.RegionName,
679 (llClient.SceneAgent.IsChildAgent ? "Child" : "Root"), (DateTime.Now - cinfo.StartedTime).Minutes, avg_reqs);
680
681 Dictionary<string, int> sortedDict = (from entry in cinfo.AsyncRequests orderby entry.Value descending select entry)
682 .ToDictionary(pair => pair.Key, pair => pair.Value);
683 PrintRequests("TOP ASYNC", sortedDict, cinfo.AsyncRequests.Values.Sum());
684
685 sortedDict = (from entry in cinfo.SyncRequests orderby entry.Value descending select entry)
686 .ToDictionary(pair => pair.Key, pair => pair.Value);
687 PrintRequests("TOP SYNC", sortedDict, cinfo.SyncRequests.Values.Sum());
688
689 sortedDict = (from entry in cinfo.GenericRequests orderby entry.Value descending select entry)
690 .ToDictionary(pair => pair.Key, pair => pair.Value);
691 PrintRequests("TOP GENERIC", sortedDict, cinfo.GenericRequests.Values.Sum());
692 }
693 }
694 });
695 }
696 return string.Empty;
697 }
698
699 private void PrintRequests(string type, Dictionary<string, int> sortedDict, int sum)
700 {
701 m_log.InfoFormat("[INFO]:");
702 m_log.InfoFormat("[INFO]: {0,25}", type);
703 foreach (KeyValuePair<string, int> kvp in sortedDict.Take(12))
704 m_log.InfoFormat("[INFO]: {0,25} {1,-6}", kvp.Key, kvp.Value);
705 m_log.InfoFormat("[INFO]: {0,25}", "...");
706 m_log.InfoFormat("[INFO]: {0,25} {1,-6}", "Total", sum);
707 }
591 } 708 }
592} \ No newline at end of file 709} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
index 5a37fad..b5d9fda 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs
@@ -461,7 +461,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
461 461
462 string result = instr; 462 string result = instr;
463 463
464 if (result == null || result.Length == 0) 464 if (string.IsNullOrEmpty(result))
465 return result; 465 return result;
466 466
467 // Repeatedly scan the string until all possible 467 // Repeatedly scan the string until all possible
diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
index 018357a..c48e585 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
@@ -375,11 +375,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge
375 scene.GetRootAgentCount(), scene.RegionInfo.RegionName, 375 scene.GetRootAgentCount(), scene.RegionInfo.RegionName,
376 scene.RegionInfo.RegionID, 376 scene.RegionInfo.RegionID,
377 DateTime.UtcNow.ToString("s"))); 377 DateTime.UtcNow.ToString("s")));
378
378 scene.ForEachRootScenePresence(delegate(ScenePresence sp) 379 scene.ForEachRootScenePresence(delegate(ScenePresence sp)
379 { 380 {
380 list.Append(String.Format(" <avatar name=\"{0}\" uuid=\"{1}\" />\n", sp.Name, sp.UUID)); 381 list.Append(String.Format(" <avatar name=\"{0}\" uuid=\"{1}\" />\n", sp.Name, sp.UUID));
381 list.Append("</avatars>");
382 }); 382 });
383
384 list.Append("</avatars>");
383 string payload = list.ToString(); 385 string payload = list.ToString();
384 386
385 // post via REST to broker 387 // post via REST to broker
diff --git a/OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs
new file mode 100644
index 0000000..5a6b284
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs
@@ -0,0 +1,220 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using System.Text;
33using System.Text.RegularExpressions;
34using log4net;
35using Mono.Addins;
36using NDesk.Options;
37using Nini.Config;
38using OpenMetaverse;
39using OpenSim.Framework;
40using OpenSim.Framework.Console;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43
44namespace OpenSim.Region.OptionalModules.Avatar.SitStand
45{
46 /// <summary>
47 /// A module that just holds commands for changing avatar sitting and standing states.
48 /// </summary>
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AnimationsCommandModule")]
50 public class SitStandCommandModule : INonSharedRegionModule
51 {
52// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private Scene m_scene;
55
56 public string Name { get { return "SitStand Command Module"; } }
57
58 public Type ReplaceableInterface { get { return null; } }
59
60 public void Initialise(IConfigSource source)
61 {
62// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: INITIALIZED MODULE");
63 }
64
65 public void PostInitialise()
66 {
67// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: POST INITIALIZED MODULE");
68 }
69
70 public void Close()
71 {
72// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: CLOSED MODULE");
73 }
74
75 public void AddRegion(Scene scene)
76 {
77// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName);
78 }
79
80 public void RemoveRegion(Scene scene)
81 {
82// m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName);
83 }
84
85 public void RegionLoaded(Scene scene)
86 {
87// m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
88
89 m_scene = scene;
90
91 scene.AddCommand(
92 "Users", this, "sit user name",
93 "sit user name [--regex] <first-name> <last-name>",
94 "Sit the named user on an unoccupied object with a sit target.",
95 "If there are no such objects then nothing happens.\n"
96 + "If --regex is specified then the names are treated as regular expressions.",
97 HandleSitUserNameCommand);
98
99 scene.AddCommand(
100 "Users", this, "stand user name",
101 "stand user name [--regex] <first-name> <last-name>",
102 "Stand the named user.",
103 "If --regex is specified then the names are treated as regular expressions.",
104 HandleStandUserNameCommand);
105 }
106
107 private void HandleSitUserNameCommand(string module, string[] cmd)
108 {
109 if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
110 return;
111
112 if (cmd.Length < 5)
113 {
114 MainConsole.Instance.Output("Usage: sit user name [--regex] <first-name> <last-name>");
115 return;
116 }
117
118 List<ScenePresence> scenePresences = GetScenePresences(cmd);
119
120 foreach (ScenePresence sp in scenePresences)
121 {
122 if (sp.SitGround || sp.IsSatOnObject)
123 continue;
124
125 SceneObjectPart sitPart = null;
126 List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups();
127
128 foreach (SceneObjectGroup sceneObject in sceneObjects)
129 {
130 if (sceneObject.IsAttachment)
131 continue;
132
133 foreach (SceneObjectPart part in sceneObject.Parts)
134 {
135 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
136 {
137 sitPart = part;
138 break;
139 }
140 }
141 }
142
143 if (sitPart != null)
144 {
145 MainConsole.Instance.OutputFormat(
146 "Sitting {0} on {1} {2} in {3}",
147 sp.Name, sitPart.ParentGroup.Name, sitPart.ParentGroup.UUID, m_scene.Name);
148
149 sp.HandleAgentRequestSit(sp.ControllingClient, sp.UUID, sitPart.UUID, Vector3.Zero);
150 sp.HandleAgentSit(sp.ControllingClient, sp.UUID);
151 }
152 else
153 {
154 MainConsole.Instance.OutputFormat(
155 "Could not find any unoccupied set seat on which to sit {0} in {1}. Aborting",
156 sp.Name, m_scene.Name);
157
158 break;
159 }
160 }
161 }
162
163 private void HandleStandUserNameCommand(string module, string[] cmd)
164 {
165 if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
166 return;
167
168 if (cmd.Length < 5)
169 {
170 MainConsole.Instance.Output("Usage: stand user name [--regex] <first-name> <last-name>");
171 return;
172 }
173
174 List<ScenePresence> scenePresences = GetScenePresences(cmd);
175
176 foreach (ScenePresence sp in scenePresences)
177 {
178 if (sp.SitGround || sp.IsSatOnObject)
179 {
180 MainConsole.Instance.OutputFormat("Standing {0} in {1}", sp.Name, m_scene.Name);
181 sp.StandUp();
182 }
183 }
184 }
185
186 private List<ScenePresence> GetScenePresences(string[] cmdParams)
187 {
188 bool useRegex = false;
189 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
190
191 List<string> mainParams = options.Parse(cmdParams);
192
193 string firstName = mainParams[3];
194 string lastName = mainParams[4];
195
196 List<ScenePresence> scenePresencesMatched = new List<ScenePresence>();
197
198 if (useRegex)
199 {
200 Regex nameRegex = new Regex(string.Format("{0} {1}", firstName, lastName));
201 List<ScenePresence> scenePresences = m_scene.GetScenePresences();
202
203 foreach (ScenePresence sp in scenePresences)
204 {
205 if (!sp.IsChildAgent && nameRegex.IsMatch(sp.Name))
206 scenePresencesMatched.Add(sp);
207 }
208 }
209 else
210 {
211 ScenePresence sp = m_scene.GetScenePresence(firstName, lastName);
212
213 if (sp != null && !sp.IsChildAgent)
214 scenePresencesMatched.Add(sp);
215 }
216
217 return scenePresencesMatched;
218 }
219 }
220} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
index 0cec959..2b33084 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
@@ -326,15 +326,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
326 "ParcelVoiceInfoRequest", 326 "ParcelVoiceInfoRequest",
327 agentID.ToString())); 327 agentID.ToString()));
328 328
329 caps.RegisterHandler( 329 //caps.RegisterHandler(
330 "ChatSessionRequest", 330 // "ChatSessionRequest",
331 new RestStreamHandler( 331 // new RestStreamHandler(
332 "POST", 332 // "POST",
333 capsBase + m_chatSessionRequestPath, 333 // capsBase + m_chatSessionRequestPath,
334 (request, path, param, httpRequest, httpResponse) 334 // (request, path, param, httpRequest, httpResponse)
335 => ChatSessionRequest(scene, request, path, param, agentID, caps), 335 // => ChatSessionRequest(scene, request, path, param, agentID, caps),
336 "ChatSessionRequest", 336 // "ChatSessionRequest",
337 agentID.ToString())); 337 // agentID.ToString()));
338 } 338 }
339 339
340 /// <summary> 340 /// <summary>
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
index 9e6cc1a..38ba54d 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
@@ -117,6 +117,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
117 117
118 private IConfig m_config; 118 private IConfig m_config;
119 119
120 private object m_Lock;
121
120 public void Initialise(IConfigSource config) 122 public void Initialise(IConfigSource config)
121 { 123 {
122 124
@@ -128,6 +130,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
128 if (!m_config.GetBoolean("enabled", false)) 130 if (!m_config.GetBoolean("enabled", false))
129 return; 131 return;
130 132
133 m_Lock = new object();
134
131 try 135 try
132 { 136 {
133 // retrieve configuration variables 137 // retrieve configuration variables
@@ -429,15 +433,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
429 "ParcelVoiceInfoRequest", 433 "ParcelVoiceInfoRequest",
430 agentID.ToString())); 434 agentID.ToString()));
431 435
432 caps.RegisterHandler( 436 //caps.RegisterHandler(
433 "ChatSessionRequest", 437 // "ChatSessionRequest",
434 new RestStreamHandler( 438 // new RestStreamHandler(
435 "POST", 439 // "POST",
436 capsBase + m_chatSessionRequestPath, 440 // capsBase + m_chatSessionRequestPath,
437 (request, path, param, httpRequest, httpResponse) 441 // (request, path, param, httpRequest, httpResponse)
438 => ChatSessionRequest(scene, request, path, param, agentID, caps), 442 // => ChatSessionRequest(scene, request, path, param, agentID, caps),
439 "ChatSessionRequest", 443 // "ChatSessionRequest",
440 agentID.ToString())); 444 // agentID.ToString()));
441 } 445 }
442 446
443 /// <summary> 447 /// <summary>
@@ -823,11 +827,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
823 { 827 {
824 string requrl = String.Format(m_vivoxChannelPath, m_vivoxServer, "create", channelId, m_authToken); 828 string requrl = String.Format(m_vivoxChannelPath, m_vivoxServer, "create", channelId, m_authToken);
825 829
826 if (parent != null && parent != String.Empty) 830 if (!string.IsNullOrEmpty(parent))
827 { 831 {
828 requrl = String.Format("{0}&chan_parent={1}", requrl, parent); 832 requrl = String.Format("{0}&chan_parent={1}", requrl, parent);
829 } 833 }
830 if (description != null && description != String.Empty) 834 if (!string.IsNullOrEmpty(description))
831 { 835 {
832 requrl = String.Format("{0}&chan_desc={1}", requrl, description); 836 requrl = String.Format("{0}&chan_desc={1}", requrl, description);
833 } 837 }
@@ -837,7 +841,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
837 requrl = String.Format("{0}&chan_roll_off={1}", requrl, m_vivoxChannelRollOff); 841 requrl = String.Format("{0}&chan_roll_off={1}", requrl, m_vivoxChannelRollOff);
838 requrl = String.Format("{0}&chan_dist_model={1}", requrl, m_vivoxChannelDistanceModel); 842 requrl = String.Format("{0}&chan_dist_model={1}", requrl, m_vivoxChannelDistanceModel);
839 requrl = String.Format("{0}&chan_max_range={1}", requrl, m_vivoxChannelMaximumRange); 843 requrl = String.Format("{0}&chan_max_range={1}", requrl, m_vivoxChannelMaximumRange);
840 requrl = String.Format("{0}&chan_ckamping_distance={1}", requrl, m_vivoxChannelClampingDistance); 844 requrl = String.Format("{0}&chan_clamping_distance={1}", requrl, m_vivoxChannelClampingDistance);
841 845
842 XmlElement resp = VivoxCall(requrl, true); 846 XmlElement resp = VivoxCall(requrl, true);
843 if (XmlFind(resp, "response.level0.body.chan_uri", out channelUri)) 847 if (XmlFind(resp, "response.level0.body.chan_uri", out channelUri))
@@ -863,7 +867,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
863 // requrl = String.Format("{0}&chan_parent={1}", requrl, parent); 867 // requrl = String.Format("{0}&chan_parent={1}", requrl, parent);
864 // } 868 // }
865 869
866 if (description != null && description != String.Empty) 870 if (!string.IsNullOrEmpty(description))
867 { 871 {
868 requrl = String.Format("{0}&chan_desc={1}", requrl, description); 872 requrl = String.Format("{0}&chan_desc={1}", requrl, description);
869 } 873 }
@@ -1049,7 +1053,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1049 private XmlElement VivoxDeleteChannel(string parent, string channelid) 1053 private XmlElement VivoxDeleteChannel(string parent, string channelid)
1050 { 1054 {
1051 string requrl = String.Format(m_vivoxChannelDel, m_vivoxServer, "delete", channelid, m_authToken); 1055 string requrl = String.Format(m_vivoxChannelDel, m_vivoxServer, "delete", channelid, m_authToken);
1052 if (parent != null && parent != String.Empty) 1056 if (!string.IsNullOrEmpty(parent))
1053 { 1057 {
1054 requrl = String.Format("{0}&chan_parent={1}", requrl, parent); 1058 requrl = String.Format("{0}&chan_parent={1}", requrl, parent);
1055 } 1059 }
@@ -1118,25 +1122,32 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1118 1122
1119 doc = new XmlDocument(); 1123 doc = new XmlDocument();
1120 1124
1121 try 1125 // Let's serialize all calls to Vivox. Most of these are driven by
1126 // the clients (CAPs), when the user arrives at the region. We don't
1127 // want to issue many simultaneous http requests to Vivox, because mono
1128 // doesn't like that
1129 lock (m_Lock)
1122 { 1130 {
1123 // Otherwise prepare the request 1131 try
1124// m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl); 1132 {
1133 // Otherwise prepare the request
1134 //m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl);
1125 1135
1126 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl); 1136 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl);
1127 1137
1128 // We are sending just parameters, no content 1138 // We are sending just parameters, no content
1129 req.ContentLength = 0; 1139 req.ContentLength = 0;
1130 1140
1131 // Send request and retrieve the response 1141 // Send request and retrieve the response
1132 using (HttpWebResponse rsp = (HttpWebResponse)req.GetResponse()) 1142 using (HttpWebResponse rsp = (HttpWebResponse)req.GetResponse())
1133 using (Stream s = rsp.GetResponseStream()) 1143 using (Stream s = rsp.GetResponseStream())
1134 using (XmlTextReader rdr = new XmlTextReader(s)) 1144 using (XmlTextReader rdr = new XmlTextReader(s))
1135 doc.Load(rdr); 1145 doc.Load(rdr);
1136 } 1146 }
1137 catch (Exception e) 1147 catch (Exception e)
1138 { 1148 {
1139 m_log.ErrorFormat("[VivoxVoice] Error in admin call : {0}", e.Message); 1149 m_log.ErrorFormat("[VivoxVoice] Error in admin call : {0}", e.Message);
1150 }
1140 } 1151 }
1141 1152
1142 // If we're debugging server responses, dump the whole 1153 // If we're debugging server responses, dump the whole
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index d0a5989..d2a6828 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -39,6 +39,7 @@ using OpenSim.Framework.Communications;
39using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
42using System.Text;
42using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags; 43using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
43 44
44namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups 45namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
@@ -250,7 +251,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
250 251
251 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; 252 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
252 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; 253 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
253 client.OnDirFindQuery += OnDirFindQuery;
254 client.OnRequestAvatarProperties += OnRequestAvatarProperties; 254 client.OnRequestAvatarProperties += OnRequestAvatarProperties;
255 255
256 // Used for Notices and Group Invites/Accept/Reject 256 // Used for Notices and Group Invites/Accept/Reject
@@ -303,21 +303,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
303 } 303 }
304 */ 304 */
305 305
306 void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart)
307 {
308 if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups)
309 {
310 if (m_debugEnabled)
311 m_log.DebugFormat(
312 "[GROUPS]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})",
313 System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart);
314
315 // TODO: This currently ignores pretty much all the query flags including Mature and sort order
316 remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentID(remoteClient), queryText).ToArray());
317 }
318
319 }
320
321 private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) 306 private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID)
322 { 307 {
323 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 308 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
@@ -437,44 +422,75 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
437 string Subject = im.message.Substring(0, im.message.IndexOf('|')); 422 string Subject = im.message.Substring(0, im.message.IndexOf('|'));
438 string Message = im.message.Substring(Subject.Length + 1); 423 string Message = im.message.Substring(Subject.Length + 1);
439 424
425 InventoryItemBase item = null;
426 bool hasAttachment = false;
427 UUID itemID = UUID.Zero; //Assignment to quiet compiler
428 UUID ownerID = UUID.Zero; //Assignment to quiet compiler
440 byte[] bucket; 429 byte[] bucket;
441 430
442 if ((im.binaryBucket.Length == 1) && (im.binaryBucket[0] == 0)) 431 if (im.binaryBucket.Length >= 1 && im.binaryBucket[0] > 0)
443 {
444 bucket = new byte[19];
445 bucket[0] = 0; //dunno
446 bucket[1] = 0; //dunno
447 GroupID.ToBytes(bucket, 2);
448 bucket[18] = 0; //dunno
449 }
450 else
451 { 432 {
452 string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket); 433 string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket);
453 binBucket = binBucket.Remove(0, 14).Trim(); 434 binBucket = binBucket.Remove(0, 14).Trim();
454 if (m_debugEnabled) 435
436 OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket);
437 if (binBucketOSD is OSD)
455 { 438 {
456 m_log.WarnFormat("I don't understand a group notice binary bucket of: {0}", binBucket); 439 OSDMap binBucketMap = (OSDMap)binBucketOSD;
440
441 itemID = binBucketMap["item_id"].AsUUID();
442 ownerID = binBucketMap["owner_id"].AsUUID();
457 443
458 OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket); 444 //Attempt to get the details of the attached item.
459 445 //If sender doesn't own the attachment, the item
460 foreach (string key in binBucketOSD.Keys) 446 //variable will be set to null and attachment will
447 //not be included with the group notice.
448 Scene scene = (Scene)remoteClient.Scene;
449 item = new InventoryItemBase(itemID, ownerID);
450 item = scene.InventoryService.GetItem(item);
451
452 if (item != null)
461 { 453 {
462 if (binBucketOSD.ContainsKey(key)) 454 //Got item details so include the attachment.
463 { 455 hasAttachment = true;
464 m_log.WarnFormat("{0}: {1}", key, binBucketOSD[key].ToString());
465 }
466 } 456 }
467 } 457 }
468 458 else
469 // treat as if no attachment 459 {
460 m_log.DebugFormat("[Groups]: Received OSD with unexpected type: {0}", binBucketOSD.GetType());
461 }
462 }
463
464 if (hasAttachment)
465 {
466 //Bucket contains information about attachment.
467 //
468 //Byte offset and description of bucket data:
469 //0: 1 byte indicating if attachment is present
470 //1: 1 byte indicating the type of attachment
471 //2: 16 bytes - Group UUID
472 //18: 16 bytes - UUID of the attachment owner
473 //34: 16 bytes - UUID of the attachment
474 //50: variable - Name of the attachment
475 //??: NUL byte to terminate the attachment name
476 byte[] name = Encoding.UTF8.GetBytes(item.Name);
477 bucket = new byte[51 + name.Length];//3 bytes, 3 UUIDs, and name
478 bucket[0] = 1; //Has attachment flag
479 bucket[1] = (byte)item.InvType; //Type of Attachment
480 GroupID.ToBytes(bucket, 2);
481 ownerID.ToBytes(bucket, 18);
482 itemID.ToBytes(bucket, 34);
483 name.CopyTo(bucket, 50);
484 }
485 else
486 {
470 bucket = new byte[19]; 487 bucket = new byte[19];
471 bucket[0] = 0; //dunno 488 bucket[0] = 0; //Has attachment flag
472 bucket[1] = 0; //dunno 489 bucket[1] = 0; //Type of attachment
473 GroupID.ToBytes(bucket, 2); 490 GroupID.ToBytes(bucket, 2);
474 bucket[18] = 0; //dunno 491 bucket[18] = 0; //NUL terminate name of attachment
475 } 492 }
476 493
477
478 m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); 494 m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket);
479 if (OnNewGroupNotice != null) 495 if (OnNewGroupNotice != null)
480 { 496 {
@@ -499,7 +515,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
499 515
500 if (member.AcceptNotices) 516 if (member.AcceptNotices)
501 { 517 {
502 // Build notice IIM 518 // Build notice IM
503 GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); 519 GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice);
504 520
505 msg.toAgentID = member.AgentID.Guid; 521 msg.toAgentID = member.AgentID.Guid;
@@ -508,10 +524,40 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
508 } 524 }
509 } 525 }
510 } 526 }
511 527
528 if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted)
529 {
530 //Is bucket large enough to hold UUID of the attachment?
531 if (im.binaryBucket.Length < 16)
532 return;
533
534 UUID noticeID = new UUID(im.imSessionID);
535
536 GroupNoticeInfo notice = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), noticeID);
537 if (notice != null)
538 {
539 UUID giver = new UUID(notice.BinaryBucket, 18);
540 UUID attachmentUUID = new UUID(notice.BinaryBucket, 34);
541
542 if (m_debugEnabled)
543 m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId);
544
545 InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId,
546 giver, attachmentUUID);
547
548 if (itemCopy == null)
549 {
550 remoteClient.SendAgentAlertMessage("Can't find item to give. Nothing given.", false);
551 return;
552 }
553
554 remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0);
555 }
556 }
557
512 // Interop, received special 210 code for ejecting a group member 558 // Interop, received special 210 code for ejecting a group member
513 // this only works within the comms servers domain, and won't work hypergrid 559 // this only works within the comms servers domain, and won't work hypergrid
514 // TODO:FIXME: Use a presense server of some kind to find out where the 560 // TODO:FIXME: Use a presence server of some kind to find out where the
515 // client actually is, and try contacting that region directly to notify them, 561 // client actually is, and try contacting that region directly to notify them,
516 // or provide the notification via xmlrpc update queue 562 // or provide the notification via xmlrpc update queue
517 if ((im.dialog == 210)) 563 if ((im.dialog == 210))
@@ -889,26 +935,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
889 935
890 if (data != null) 936 if (data != null)
891 { 937 {
892 GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null); 938 GridInstantMessage msg = CreateGroupNoticeIM(remoteClient.AgentId, groupNoticeID, (byte)InstantMessageDialog.GroupNoticeRequested);
893
894 GridInstantMessage msg = new GridInstantMessage();
895 msg.imSessionID = UUID.Zero.Guid;
896 msg.fromAgentID = data.GroupID.Guid;
897 msg.toAgentID = GetRequestingAgentID(remoteClient).Guid;
898 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
899 msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName;
900 msg.message = data.noticeData.Subject + "|" + data.Message;
901 msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNoticeRequested;
902 msg.fromGroup = true;
903 msg.offline = (byte)0;
904 msg.ParentEstateID = 0;
905 msg.Position = Vector3.Zero;
906 msg.RegionID = UUID.Zero.Guid;
907 msg.binaryBucket = data.BinaryBucket;
908 939
909 OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); 940 OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient));
910 } 941 }
911
912 } 942 }
913 943
914 public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog) 944 public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog)
@@ -916,10 +946,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
916 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); 946 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
917 947
918 GridInstantMessage msg = new GridInstantMessage(); 948 GridInstantMessage msg = new GridInstantMessage();
919 msg.imSessionID = UUID.Zero.Guid; 949 byte[] bucket;
950
951 msg.imSessionID = groupNoticeID.Guid;
920 msg.toAgentID = agentID.Guid; 952 msg.toAgentID = agentID.Guid;
921 msg.dialog = dialog; 953 msg.dialog = dialog;
922 // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice;
923 msg.fromGroup = true; 954 msg.fromGroup = true;
924 msg.offline = (byte)1; // Allow this message to be stored for offline use 955 msg.offline = (byte)1; // Allow this message to be stored for offline use
925 msg.ParentEstateID = 0; 956 msg.ParentEstateID = 0;
@@ -933,13 +964,38 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
933 msg.timestamp = info.noticeData.Timestamp; 964 msg.timestamp = info.noticeData.Timestamp;
934 msg.fromAgentName = info.noticeData.FromName; 965 msg.fromAgentName = info.noticeData.FromName;
935 msg.message = info.noticeData.Subject + "|" + info.Message; 966 msg.message = info.noticeData.Subject + "|" + info.Message;
936 msg.binaryBucket = info.BinaryBucket; 967
968 if (info.BinaryBucket[0] > 0)
969 {
970 //32 is due to not needing space for two of the UUIDs.
971 //(Don't need UUID of attachment or its owner in IM)
972 //50 offset gets us to start of attachment name.
973 //We are skipping the attachment flag, type, and
974 //the three UUID fields at the start of the bucket.
975 bucket = new byte[info.BinaryBucket.Length-32];
976 bucket[0] = 1; //Has attachment
977 bucket[1] = info.BinaryBucket[1];
978 Array.Copy(info.BinaryBucket, 50,
979 bucket, 18, info.BinaryBucket.Length-50);
980 }
981 else
982 {
983 bucket = new byte[19];
984 bucket[0] = 0; //No attachment
985 bucket[1] = 0; //Attachment type
986 bucket[18] = 0; //NUL terminate name
987 }
988
989 info.GroupID.ToBytes(bucket, 2);
990 msg.binaryBucket = bucket;
937 } 991 }
938 else 992 else
939 { 993 {
940 if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID); 994 if (m_debugEnabled)
995 m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID);
996
941 msg.fromAgentID = UUID.Zero.Guid; 997 msg.fromAgentID = UUID.Zero.Guid;
942 msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); ; 998 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
943 msg.fromAgentName = string.Empty; 999 msg.fromAgentName = string.Empty;
944 msg.message = string.Empty; 1000 msg.message = string.Empty;
945 msg.binaryBucket = new byte[0]; 1001 msg.binaryBucket = new byte[0];
@@ -1063,7 +1119,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1063 // Message to ejector 1119 // Message to ejector
1064 // Interop, received special 210 code for ejecting a group member 1120 // Interop, received special 210 code for ejecting a group member
1065 // this only works within the comms servers domain, and won't work hypergrid 1121 // this only works within the comms servers domain, and won't work hypergrid
1066 // TODO:FIXME: Use a presense server of some kind to find out where the 1122 // TODO:FIXME: Use a presence server of some kind to find out where the
1067 // client actually is, and try contacting that region directly to notify them, 1123 // client actually is, and try contacting that region directly to notify them,
1068 // or provide the notification via xmlrpc update queue 1124 // or provide the notification via xmlrpc update queue
1069 1125
@@ -1178,6 +1234,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1178 } 1234 }
1179 } 1235 }
1180 1236
1237 public List<DirGroupsReplyData> FindGroups(IClientAPI remoteClient, string query)
1238 {
1239 return m_groupData.FindGroups(GetRequestingAgentID(remoteClient), query);
1240 }
1241
1242
1181 #endregion 1243 #endregion
1182 1244
1183 #region Client/Update Tools 1245 #region Client/Update Tools
@@ -1222,7 +1284,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
1222 AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID)); 1284 AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID));
1223 AgentData.Add(AgentDataMap); 1285 AgentData.Add(AgentDataMap);
1224 1286
1225
1226 OSDArray GroupData = new OSDArray(data.Length); 1287 OSDArray GroupData = new OSDArray(data.Length);
1227 OSDArray NewGroupData = new OSDArray(data.Length); 1288 OSDArray NewGroupData = new OSDArray(data.Length);
1228 1289
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
index 7bae8f7..8095b28 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs
@@ -212,8 +212,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
212 m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Initializing {0}", this.Name); 212 m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Initializing {0}", this.Name);
213 213
214 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); 214 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty);
215 if ((m_groupsServerURI == null) || 215 if (string.IsNullOrEmpty(m_groupsServerURI))
216 (m_groupsServerURI == string.Empty))
217 { 216 {
218 m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]"); 217 m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]");
219 m_connectorEnabled = false; 218 m_connectorEnabled = false;
@@ -438,7 +437,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
438 return null; 437 return null;
439 } 438 }
440 } 439 }
441 else if ((groupName != null) && (groupName != string.Empty)) 440 else if (!string.IsNullOrEmpty(groupName))
442 { 441 {
443 if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap)) 442 if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap))
444 { 443 {
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
index c1bdacb..26d2597 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
@@ -26,13 +26,23 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
30using System.Net;
29using System.Reflection; 31using System.Reflection;
30using Nini.Config; 32using Nini.Config;
31using NUnit.Framework; 33using NUnit.Framework;
32using OpenMetaverse; 34using OpenMetaverse;
35using OpenMetaverse.Messages.Linden;
36using OpenMetaverse.Packets;
37using OpenMetaverse.StructuredData;
33using OpenSim.Framework; 38using OpenSim.Framework;
34using OpenSim.Framework.Communications; 39using OpenSim.Framework.Communications;
40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Region.ClientStack.Linden;
43using OpenSim.Region.CoreModules.Framework;
35using OpenSim.Region.Framework.Scenes; 44using OpenSim.Region.Framework.Scenes;
45using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups;
36using OpenSim.Tests.Common; 46using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock; 47using OpenSim.Tests.Common.Mock;
38 48
@@ -44,11 +54,28 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
44 [TestFixture] 54 [TestFixture]
45 public class GroupsModuleTests : OpenSimTestCase 55 public class GroupsModuleTests : OpenSimTestCase
46 { 56 {
57 [SetUp]
58 public override void SetUp()
59 {
60 base.SetUp();
61
62 uint port = 9999;
63 uint sslPort = 9998;
64
65 // This is an unfortunate bit of clean up we have to do because MainServer manages things through static
66 // variables and the VM is not restarted between tests.
67 MainServer.RemoveHttpServer(port);
68
69 BaseHttpServer server = new BaseHttpServer(port, false, sslPort, "");
70 MainServer.AddHttpServer(server);
71 MainServer.Instance = server;
72 }
73
47 [Test] 74 [Test]
48 public void TestBasic() 75 public void TestSendAgentGroupDataUpdate()
49 { 76 {
50 TestHelpers.InMethod(); 77 TestHelpers.InMethod();
51// log4net.Config.XmlConfigurator.Configure(); 78// TestHelpers.EnableLogging();
52 79
53 TestScene scene = new SceneHelpers().SetupScene(); 80 TestScene scene = new SceneHelpers().SetupScene();
54 IConfigSource configSource = new IniConfigSource(); 81 IConfigSource configSource = new IniConfigSource();
@@ -56,8 +83,40 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
56 config.Set("Enabled", true); 83 config.Set("Enabled", true);
57 config.Set("Module", "GroupsModule"); 84 config.Set("Module", "GroupsModule");
58 config.Set("DebugEnabled", true); 85 config.Set("DebugEnabled", true);
86
87 GroupsModule gm = new GroupsModule();
88 EventQueueGetModule eqgm = new EventQueueGetModule();
89
90 // We need a capabilities module active so that adding the scene presence creates an event queue in the
91 // EventQueueGetModule
59 SceneHelpers.SetupSceneModules( 92 SceneHelpers.SetupSceneModules(
60 scene, configSource, new object[] { new MockGroupsServicesConnector() }); 93 scene, configSource, gm, new MockGroupsServicesConnector(), new CapabilitiesModule(), eqgm);
94
95 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseStem("1"));
96
97 gm.SendAgentGroupDataUpdate(sp.ControllingClient);
98
99 Hashtable eventsResponse = eqgm.GetEvents(UUID.Zero, sp.UUID);
100
101 Assert.That((int)eventsResponse["int_response_code"], Is.EqualTo((int)HttpStatusCode.OK));
102
103// Console.WriteLine("Response [{0}]", (string)eventsResponse["str_response_string"]);
104
105 OSDMap rawOsd = (OSDMap)OSDParser.DeserializeLLSDXml((string)eventsResponse["str_response_string"]);
106 OSDArray eventsOsd = (OSDArray)rawOsd["events"];
107
108 bool foundUpdate = false;
109 foreach (OSD osd in eventsOsd)
110 {
111 OSDMap eventOsd = (OSDMap)osd;
112
113 if (eventOsd["message"] == "AgentGroupDataUpdate")
114 foundUpdate = true;
115 }
116
117 Assert.That(foundUpdate, Is.True, "Did not find AgentGroupDataUpdate in response");
118
119 // TODO: More checking of more actual event data.
61 } 120 }
62 } 121 }
63} \ No newline at end of file 122} \ No newline at end of file
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
index 71b24ac..e28d0c2 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
@@ -168,8 +168,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
168 m_log.DebugFormat("[XMLRPC-GROUPS-CONNECTOR]: Initializing {0}", this.Name); 168 m_log.DebugFormat("[XMLRPC-GROUPS-CONNECTOR]: Initializing {0}", this.Name);
169 169
170 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); 170 m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty);
171 if ((m_groupsServerURI == null) || 171 if (string.IsNullOrEmpty(m_groupsServerURI))
172 (m_groupsServerURI == string.Empty))
173 { 172 {
174 m_log.ErrorFormat("Please specify a valid URL for GroupsServerURI in OpenSim.ini, [Groups]"); 173 m_log.ErrorFormat("Please specify a valid URL for GroupsServerURI in OpenSim.ini, [Groups]");
175 m_connectorEnabled = false; 174 m_connectorEnabled = false;
@@ -354,7 +353,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
354 { 353 {
355 param["GroupID"] = GroupID.ToString(); 354 param["GroupID"] = GroupID.ToString();
356 } 355 }
357 if ((GroupName != null) && (GroupName != string.Empty)) 356 if (!string.IsNullOrEmpty(GroupName))
358 { 357 {
359 param["Name"] = GroupName.ToString(); 358 param["Name"] = GroupName.ToString();
360 } 359 }
diff --git a/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs b/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs
deleted file mode 100644
index 6e74ce0..0000000
--- a/OpenSim/Region/OptionalModules/Framework/Monitoring/ServerStats.cs
+++ /dev/null
@@ -1,339 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Diagnostics;
31using System.Linq;
32using System.Net.NetworkInformation;
33using System.Text;
34using System.Threading;
35
36using log4net;
37using Mono.Addins;
38using Nini.Config;
39
40using OpenSim.Framework;
41using OpenSim.Framework.Console;
42using OpenSim.Framework.Monitoring;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45
46using OpenMetaverse.StructuredData;
47
48namespace OpenSim.Region.OptionalModules.Framework.Monitoring
49{
50[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ServerStatistics")]
51public class ServerStats : ISharedRegionModule
52{
53 private readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
54 private readonly string LogHeader = "[SERVER STATS]";
55
56 public bool Enabled = false;
57 private static Dictionary<string, Stat> RegisteredStats = new Dictionary<string, Stat>();
58
59 public readonly string CategoryServer = "server";
60
61 public readonly string ContainerProcessor = "processor";
62 public readonly string ContainerMemory = "memory";
63 public readonly string ContainerNetwork = "network";
64 public readonly string ContainerProcess = "process";
65
66 public string NetworkInterfaceTypes = "Ethernet";
67
68 readonly int performanceCounterSampleInterval = 500;
69 int lastperformanceCounterSampleTime = 0;
70
71 private class PerfCounterControl
72 {
73 public PerformanceCounter perfCounter;
74 public int lastFetch;
75 public string name;
76 public PerfCounterControl(PerformanceCounter pPc)
77 : this(pPc, String.Empty)
78 {
79 }
80 public PerfCounterControl(PerformanceCounter pPc, string pName)
81 {
82 perfCounter = pPc;
83 lastFetch = 0;
84 name = pName;
85 }
86 }
87
88 PerfCounterControl processorPercentPerfCounter = null;
89
90 #region ISharedRegionModule
91 // IRegionModuleBase.Name
92 public string Name { get { return "Server Stats"; } }
93 // IRegionModuleBase.ReplaceableInterface
94 public Type ReplaceableInterface { get { return null; } }
95 // IRegionModuleBase.Initialize
96 public void Initialise(IConfigSource source)
97 {
98 IConfig cfg = source.Configs["Monitoring"];
99
100 if (cfg != null)
101 Enabled = cfg.GetBoolean("ServerStatsEnabled", true);
102
103 if (Enabled)
104 {
105 NetworkInterfaceTypes = cfg.GetString("NetworkInterfaceTypes", "Ethernet");
106 }
107 }
108 // IRegionModuleBase.Close
109 public void Close()
110 {
111 if (RegisteredStats.Count > 0)
112 {
113 foreach (Stat stat in RegisteredStats.Values)
114 {
115 StatsManager.DeregisterStat(stat);
116 stat.Dispose();
117 }
118 RegisteredStats.Clear();
119 }
120 }
121 // IRegionModuleBase.AddRegion
122 public void AddRegion(Scene scene)
123 {
124 }
125 // IRegionModuleBase.RemoveRegion
126 public void RemoveRegion(Scene scene)
127 {
128 }
129 // IRegionModuleBase.RegionLoaded
130 public void RegionLoaded(Scene scene)
131 {
132 }
133 // ISharedRegionModule.PostInitialize
134 public void PostInitialise()
135 {
136 if (RegisteredStats.Count == 0)
137 {
138 RegisterServerStats();
139 }
140 }
141 #endregion ISharedRegionModule
142
143 private void MakeStat(string pName, string pDesc, string pUnit, string pContainer, Action<Stat> act)
144 {
145 string desc = pDesc;
146 if (desc == null)
147 desc = pName;
148 Stat stat = new Stat(pName, pName, desc, pUnit, CategoryServer, pContainer, StatType.Pull, act, StatVerbosity.Info);
149 StatsManager.RegisterStat(stat);
150 RegisteredStats.Add(pName, stat);
151 }
152
153 public void RegisterServerStats()
154 {
155 lastperformanceCounterSampleTime = Util.EnvironmentTickCount();
156 PerformanceCounter tempPC;
157 Stat tempStat;
158 string tempName;
159
160 try
161 {
162 tempName = "CPUPercent";
163 tempPC = new PerformanceCounter("Processor", "% Processor Time", "_Total");
164 processorPercentPerfCounter = new PerfCounterControl(tempPC);
165 // A long time bug in mono is that CPU percent is reported as CPU percent idle. Windows reports CPU percent busy.
166 tempStat = new Stat(tempName, tempName, "", "percent", CategoryServer, ContainerProcessor,
167 StatType.Pull, (s) => { GetNextValue(s, processorPercentPerfCounter, Util.IsWindows() ? 1 : -1); },
168 StatVerbosity.Info);
169 StatsManager.RegisterStat(tempStat);
170 RegisteredStats.Add(tempName, tempStat);
171
172 MakeStat("TotalProcessorTime", null, "sec", ContainerProcessor,
173 (s) => { s.Value = Process.GetCurrentProcess().TotalProcessorTime.TotalSeconds; });
174
175 MakeStat("UserProcessorTime", null, "sec", ContainerProcessor,
176 (s) => { s.Value = Process.GetCurrentProcess().UserProcessorTime.TotalSeconds; });
177
178 MakeStat("PrivilegedProcessorTime", null, "sec", ContainerProcessor,
179 (s) => { s.Value = Process.GetCurrentProcess().PrivilegedProcessorTime.TotalSeconds; });
180
181 MakeStat("Threads", null, "threads", ContainerProcessor,
182 (s) => { s.Value = Process.GetCurrentProcess().Threads.Count; });
183 }
184 catch (Exception e)
185 {
186 m_log.ErrorFormat("{0} Exception creating 'Process': {1}", LogHeader, e);
187 }
188
189 try
190 {
191 List<string> okInterfaceTypes = new List<string>(NetworkInterfaceTypes.Split(','));
192
193 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces();
194 foreach (NetworkInterface nic in nics)
195 {
196 if (nic.OperationalStatus != OperationalStatus.Up)
197 continue;
198
199 string nicInterfaceType = nic.NetworkInterfaceType.ToString();
200 if (!okInterfaceTypes.Contains(nicInterfaceType))
201 {
202 m_log.DebugFormat("{0} Not including stats for network interface '{1}' of type '{2}'.",
203 LogHeader, nic.Name, nicInterfaceType);
204 m_log.DebugFormat("{0} To include, add to comma separated list in [Monitoring]NetworkInterfaceTypes={1}",
205 LogHeader, NetworkInterfaceTypes);
206 continue;
207 }
208
209 if (nic.Supports(NetworkInterfaceComponent.IPv4))
210 {
211 IPv4InterfaceStatistics nicStats = nic.GetIPv4Statistics();
212 if (nicStats != null)
213 {
214 MakeStat("BytesRcvd/" + nic.Name, nic.Name, "KB", ContainerNetwork,
215 (s) => { LookupNic(s, (ns) => { return ns.BytesReceived; }, 1024.0); });
216 MakeStat("BytesSent/" + nic.Name, nic.Name, "KB", ContainerNetwork,
217 (s) => { LookupNic(s, (ns) => { return ns.BytesSent; }, 1024.0); });
218 MakeStat("TotalBytes/" + nic.Name, nic.Name, "KB", ContainerNetwork,
219 (s) => { LookupNic(s, (ns) => { return ns.BytesSent + ns.BytesReceived; }, 1024.0); });
220 }
221 }
222 // TODO: add IPv6 (it may actually happen someday)
223 }
224 }
225 catch (Exception e)
226 {
227 m_log.ErrorFormat("{0} Exception creating 'Network Interface': {1}", LogHeader, e);
228 }
229
230 MakeStat("ProcessMemory", null, "MB", ContainerMemory,
231 (s) => { s.Value = Process.GetCurrentProcess().WorkingSet64 / 1024d / 1024d; });
232 MakeStat("ObjectMemory", null, "MB", ContainerMemory,
233 (s) => { s.Value = GC.GetTotalMemory(false) / 1024d / 1024d; });
234 MakeStat("LastMemoryChurn", null, "MB/sec", ContainerMemory,
235 (s) => { s.Value = Math.Round(MemoryWatchdog.LastMemoryChurn * 1000d / 1024d / 1024d, 3); });
236 MakeStat("AverageMemoryChurn", null, "MB/sec", ContainerMemory,
237 (s) => { s.Value = Math.Round(MemoryWatchdog.AverageMemoryChurn * 1000d / 1024d / 1024d, 3); });
238 }
239
240 // Notes on performance counters:
241 // "How To Read Performance Counters": http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx
242 // "How to get the CPU Usage in C#": http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c
243 // "Mono Performance Counters": http://www.mono-project.com/Mono_Performance_Counters
244 private delegate double PerfCounterNextValue();
245 private void GetNextValue(Stat stat, PerfCounterControl perfControl)
246 {
247 GetNextValue(stat, perfControl, 1.0);
248 }
249 private void GetNextValue(Stat stat, PerfCounterControl perfControl, double factor)
250 {
251 if (Util.EnvironmentTickCountSubtract(perfControl.lastFetch) > performanceCounterSampleInterval)
252 {
253 if (perfControl != null && perfControl.perfCounter != null)
254 {
255 try
256 {
257 // Kludge for factor to run double duty. If -1, subtract the value from one
258 if (factor == -1)
259 stat.Value = 1 - perfControl.perfCounter.NextValue();
260 else
261 stat.Value = perfControl.perfCounter.NextValue() / factor;
262 }
263 catch (Exception e)
264 {
265 m_log.ErrorFormat("{0} Exception on NextValue fetching {1}: {2}", LogHeader, stat.Name, e);
266 }
267 perfControl.lastFetch = Util.EnvironmentTickCount();
268 }
269 }
270 }
271
272 // Lookup the nic that goes with this stat and set the value by using a fetch action.
273 // Not sure about closure with delegates inside delegates.
274 private delegate double GetIPv4StatValue(IPv4InterfaceStatistics interfaceStat);
275 private void LookupNic(Stat stat, GetIPv4StatValue getter, double factor)
276 {
277 // Get the one nic that has the name of this stat
278 IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
279 (network) => network.Name == stat.Description);
280 try
281 {
282 foreach (NetworkInterface nic in nics)
283 {
284 IPv4InterfaceStatistics intrStats = nic.GetIPv4Statistics();
285 if (intrStats != null)
286 {
287 double newVal = Math.Round(getter(intrStats) / factor, 3);
288 stat.Value = newVal;
289 }
290 break;
291 }
292 }
293 catch
294 {
295 // There are times interfaces go away so we just won't update the stat for this
296 m_log.ErrorFormat("{0} Exception fetching stat on interface '{1}'", LogHeader, stat.Description);
297 }
298 }
299}
300
301public class ServerStatsAggregator : Stat
302{
303 public ServerStatsAggregator(
304 string shortName,
305 string name,
306 string description,
307 string unitName,
308 string category,
309 string container
310 )
311 : base(
312 shortName,
313 name,
314 description,
315 unitName,
316 category,
317 container,
318 StatType.Push,
319 MeasuresOfInterest.None,
320 null,
321 StatVerbosity.Info)
322 {
323 }
324 public override string ToConsoleString()
325 {
326 StringBuilder sb = new StringBuilder();
327
328 return sb.ToString();
329 }
330
331 public override OSDMap ToOSDMap()
332 {
333 OSDMap ret = new OSDMap();
334
335 return ret;
336 }
337}
338
339}
diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
new file mode 100644
index 0000000..afb788b
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs
@@ -0,0 +1,590 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Reflection;
32using System.Security.Cryptography; // for computing md5 hash
33using log4net;
34using Mono.Addins;
35using Nini.Config;
36
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39
40using OpenSim.Framework;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45using OpenSimAssetType = OpenSim.Framework.SLUtil.OpenSimAssetType;
46
47using Ionic.Zlib;
48
49// You will need to uncomment these lines if you are adding a region module to some other assembly which does not already
50// specify its assembly. Otherwise, the region modules in the assembly will not be picked up when OpenSimulator scans
51// the available DLLs
52//[assembly: Addin("MaterialsModule", "1.0")]
53//[assembly: AddinDependency("OpenSim", "0.5")]
54
55namespace OpenSim.Region.OptionalModules.Materials
56{
57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MaterialsModule")]
58 public class MaterialsModule : INonSharedRegionModule
59 {
60 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61
62 public string Name { get { return "MaterialsModule"; } }
63
64 public Type ReplaceableInterface { get { return null; } }
65
66 private Scene m_scene = null;
67 private bool m_enabled = false;
68
69 public Dictionary<UUID, OSDMap> m_regionMaterials = new Dictionary<UUID, OSDMap>();
70
71 public void Initialise(IConfigSource source)
72 {
73 IConfig config = source.Configs["Materials"];
74 if (config == null)
75 return;
76
77 m_enabled = config.GetBoolean("enable_materials", true);
78 if (!m_enabled)
79 return;
80
81 m_log.DebugFormat("[Materials]: Initialized");
82 }
83
84 public void Close()
85 {
86 if (!m_enabled)
87 return;
88 }
89
90 public void AddRegion(Scene scene)
91 {
92 if (!m_enabled)
93 return;
94
95 m_scene = scene;
96 m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
97 m_scene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
98 }
99
100 private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
101 {
102 foreach (var part in obj.Parts)
103 if (part != null)
104 GetStoredMaterialsInPart(part);
105 }
106
107 private void OnRegisterCaps(OpenMetaverse.UUID agentID, OpenSim.Framework.Capabilities.Caps caps)
108 {
109 string capsBase = "/CAPS/" + caps.CapsObjectPath;
110
111 IRequestHandler renderMaterialsPostHandler
112 = new RestStreamHandler("POST", capsBase + "/",
113 (request, path, param, httpRequest, httpResponse)
114 => RenderMaterialsPostCap(request, agentID),
115 "RenderMaterials", null);
116 caps.RegisterHandler("RenderMaterials", renderMaterialsPostHandler);
117
118 // OpenSimulator CAPs infrastructure seems to be somewhat hostile towards any CAP that requires both GET
119 // and POST handlers, (at least at the time this was originally written), so we first set up a POST
120 // handler normally and then add a GET handler via MainServer
121
122 IRequestHandler renderMaterialsGetHandler
123 = new RestStreamHandler("GET", capsBase + "/",
124 (request, path, param, httpRequest, httpResponse)
125 => RenderMaterialsGetCap(request),
126 "RenderMaterials", null);
127 MainServer.Instance.AddStreamHandler(renderMaterialsGetHandler);
128
129 // materials viewer seems to use either POST or PUT, so assign POST handler for PUT as well
130 IRequestHandler renderMaterialsPutHandler
131 = new RestStreamHandler("PUT", capsBase + "/",
132 (request, path, param, httpRequest, httpResponse)
133 => RenderMaterialsPostCap(request, agentID),
134 "RenderMaterials", null);
135 MainServer.Instance.AddStreamHandler(renderMaterialsPutHandler);
136 }
137
138 public void RemoveRegion(Scene scene)
139 {
140 if (!m_enabled)
141 return;
142
143 m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
144 m_scene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
145 }
146
147 public void RegionLoaded(Scene scene)
148 {
149 }
150
151 /// <summary>
152 /// Finds any legacy materials stored in DynAttrs that may exist for this part and add them to 'm_regionMaterials'.
153 /// </summary>
154 /// <param name="part"></param>
155 private void GetLegacyStoredMaterialsInPart(SceneObjectPart part)
156 {
157 if (part.DynAttrs == null)
158 return;
159
160 OSD OSMaterials = null;
161 OSDArray matsArr = null;
162
163 lock (part.DynAttrs)
164 {
165 if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
166 {
167 OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
168
169 if (materialsStore == null)
170 return;
171
172 materialsStore.TryGetValue("Materials", out OSMaterials);
173 }
174
175 if (OSMaterials != null && OSMaterials is OSDArray)
176 matsArr = OSMaterials as OSDArray;
177 else
178 return;
179 }
180
181 if (matsArr == null)
182 return;
183
184 foreach (OSD elemOsd in matsArr)
185 {
186 if (elemOsd != null && elemOsd is OSDMap)
187 {
188 OSDMap matMap = elemOsd as OSDMap;
189 if (matMap.ContainsKey("ID") && matMap.ContainsKey("Material"))
190 {
191 try
192 {
193 lock (m_regionMaterials)
194 m_regionMaterials[matMap["ID"].AsUUID()] = (OSDMap)matMap["Material"];
195 }
196 catch (Exception e)
197 {
198 m_log.Warn("[Materials]: exception decoding persisted legacy material: " + e.ToString());
199 }
200 }
201 }
202 }
203 }
204
205 /// <summary>
206 /// Find the materials used in the SOP, and add them to 'm_regionMaterials'.
207 /// </summary>
208 private void GetStoredMaterialsInPart(SceneObjectPart part)
209 {
210 if (part.Shape == null)
211 return;
212
213 var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length);
214 if (te == null)
215 return;
216
217 GetLegacyStoredMaterialsInPart(part);
218
219 GetStoredMaterialInFace(part, te.DefaultTexture);
220
221 foreach (Primitive.TextureEntryFace face in te.FaceTextures)
222 {
223 if (face != null)
224 GetStoredMaterialInFace(part, face);
225 }
226 }
227
228 /// <summary>
229 /// Find the materials used in one Face, and add them to 'm_regionMaterials'.
230 /// </summary>
231 private void GetStoredMaterialInFace(SceneObjectPart part, Primitive.TextureEntryFace face)
232 {
233 UUID id = face.MaterialID;
234 if (id == UUID.Zero)
235 return;
236
237 lock (m_regionMaterials)
238 {
239 if (m_regionMaterials.ContainsKey(id))
240 return;
241
242 byte[] data = m_scene.AssetService.GetData(id.ToString());
243 if (data == null)
244 {
245 m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id);
246 return;
247 }
248
249 OSDMap mat;
250 try
251 {
252 mat = (OSDMap)OSDParser.DeserializeLLSDXml(data);
253 }
254 catch (Exception e)
255 {
256 m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", id, e.Message);
257 return;
258 }
259
260 m_regionMaterials[id] = mat;
261 }
262 }
263
264 public string RenderMaterialsPostCap(string request, UUID agentID)
265 {
266 OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(request);
267 OSDMap resp = new OSDMap();
268
269 OSDMap materialsFromViewer = null;
270
271 OSDArray respArr = new OSDArray();
272
273 if (req.ContainsKey("Zipped"))
274 {
275 OSD osd = null;
276
277 byte[] inBytes = req["Zipped"].AsBinary();
278
279 try
280 {
281 osd = ZDecompressBytesToOsd(inBytes);
282
283 if (osd != null)
284 {
285 if (osd is OSDArray) // assume array of MaterialIDs designating requested material entries
286 {
287 foreach (OSD elem in (OSDArray)osd)
288 {
289 try
290 {
291 UUID id = new UUID(elem.AsBinary(), 0);
292
293 lock (m_regionMaterials)
294 {
295 if (m_regionMaterials.ContainsKey(id))
296 {
297 OSDMap matMap = new OSDMap();
298 matMap["ID"] = OSD.FromBinary(id.GetBytes());
299 matMap["Material"] = m_regionMaterials[id];
300 respArr.Add(matMap);
301 }
302 else
303 {
304 m_log.Warn("[Materials]: request for unknown material ID: " + id.ToString());
305
306 // Theoretically we could try to load the material from the assets service,
307 // but that shouldn't be necessary because the viewer should only request
308 // materials that exist in a prim on the region, and all of these materials
309 // are already stored in m_regionMaterials.
310 }
311 }
312 }
313 catch (Exception e)
314 {
315 m_log.Error("Error getting materials in response to viewer request", e);
316 continue;
317 }
318 }
319 }
320 else if (osd is OSDMap) // request to assign a material
321 {
322 materialsFromViewer = osd as OSDMap;
323
324 if (materialsFromViewer.ContainsKey("FullMaterialsPerFace"))
325 {
326 OSD matsOsd = materialsFromViewer["FullMaterialsPerFace"];
327 if (matsOsd is OSDArray)
328 {
329 OSDArray matsArr = matsOsd as OSDArray;
330
331 try
332 {
333 foreach (OSDMap matsMap in matsArr)
334 {
335 uint primLocalID = 0;
336 try {
337 primLocalID = matsMap["ID"].AsUInteger();
338 }
339 catch (Exception e) {
340 m_log.Warn("[Materials]: cannot decode \"ID\" from matsMap: " + e.Message);
341 continue;
342 }
343
344 OSDMap mat = null;
345 try
346 {
347 mat = matsMap["Material"] as OSDMap;
348 }
349 catch (Exception e)
350 {
351 m_log.Warn("[Materials]: cannot decode \"Material\" from matsMap: " + e.Message);
352 continue;
353 }
354
355 SceneObjectPart sop = m_scene.GetSceneObjectPart(primLocalID);
356 if (sop == null)
357 {
358 m_log.WarnFormat("[Materials]: SOP not found for localId: {0}", primLocalID.ToString());
359 continue;
360 }
361
362 if (!m_scene.Permissions.CanEditObject(sop.UUID, agentID))
363 {
364 m_log.WarnFormat("User {0} can't edit object {1} {2}", agentID, sop.Name, sop.UUID);
365 continue;
366 }
367
368 Primitive.TextureEntry te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
369 if (te == null)
370 {
371 m_log.WarnFormat("[Materials]: Error in TextureEntry for SOP {0} {1}", sop.Name, sop.UUID);
372 continue;
373 }
374
375
376 UUID id;
377 if (mat == null)
378 {
379 // This happens then the user removes a material from a prim
380 id = UUID.Zero;
381 }
382 else
383 {
384 id = StoreMaterialAsAsset(agentID, mat, sop);
385 }
386
387
388 int face = -1;
389
390 if (matsMap.ContainsKey("Face"))
391 {
392 face = matsMap["Face"].AsInteger();
393 Primitive.TextureEntryFace faceEntry = te.CreateFace((uint)face);
394 faceEntry.MaterialID = id;
395 }
396 else
397 {
398 if (te.DefaultTexture == null)
399 m_log.WarnFormat("[Materials]: TextureEntry.DefaultTexture is null in {0} {1}", sop.Name, sop.UUID);
400 else
401 te.DefaultTexture.MaterialID = id;
402 }
403
404 //m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
405
406 // We can't use sop.UpdateTextureEntry(te) because it filters, so do it manually
407 sop.Shape.TextureEntry = te.GetBytes();
408
409 if (sop.ParentGroup != null)
410 {
411 sop.TriggerScriptChangedEvent(Changed.TEXTURE);
412 sop.UpdateFlag = UpdateRequired.FULL;
413 sop.ParentGroup.HasGroupChanged = true;
414 sop.ScheduleFullUpdate();
415 }
416 }
417 }
418 catch (Exception e)
419 {
420 m_log.Warn("[Materials]: exception processing received material ", e);
421 }
422 }
423 }
424 }
425 }
426
427 }
428 catch (Exception e)
429 {
430 m_log.Warn("[Materials]: exception decoding zipped CAP payload ", e);
431 //return "";
432 }
433 }
434
435
436 resp["Zipped"] = ZCompressOSD(respArr, false);
437 string response = OSDParser.SerializeLLSDXmlString(resp);
438
439 //m_log.Debug("[Materials]: cap request: " + request);
440 //m_log.Debug("[Materials]: cap request (zipped portion): " + ZippedOsdBytesToString(req["Zipped"].AsBinary()));
441 //m_log.Debug("[Materials]: cap response: " + response);
442 return response;
443 }
444
445 private UUID StoreMaterialAsAsset(UUID agentID, OSDMap mat, SceneObjectPart sop)
446 {
447 UUID id;
448 // Material UUID = hash of the material's data.
449 // This makes materials deduplicate across the entire grid (but isn't otherwise required).
450 byte[] data = System.Text.Encoding.ASCII.GetBytes(OSDParser.SerializeLLSDXmlString(mat));
451 using (var md5 = MD5.Create())
452 id = new UUID(md5.ComputeHash(data), 0);
453
454 lock (m_regionMaterials)
455 {
456 if (!m_regionMaterials.ContainsKey(id))
457 {
458 m_regionMaterials[id] = mat;
459
460 // This asset might exist already, but it's ok to try to store it again
461 string name = "Material " + ChooseMaterialName(mat, sop);
462 name = name.Substring(0, Math.Min(64, name.Length)).Trim();
463 AssetBase asset = new AssetBase(id, name, (sbyte)OpenSimAssetType.Material, agentID.ToString());
464 asset.Data = data;
465 m_scene.AssetService.Store(asset);
466 }
467 }
468 return id;
469 }
470
471 /// <summary>
472 /// Use heuristics to choose a good name for the material.
473 /// </summary>
474 private string ChooseMaterialName(OSDMap mat, SceneObjectPart sop)
475 {
476 UUID normMap = mat["NormMap"].AsUUID();
477 if (normMap != UUID.Zero)
478 {
479 AssetBase asset = m_scene.AssetService.GetCached(normMap.ToString());
480 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
481 return asset.Name;
482 }
483
484 UUID specMap = mat["SpecMap"].AsUUID();
485 if (specMap != UUID.Zero)
486 {
487 AssetBase asset = m_scene.AssetService.GetCached(specMap.ToString());
488 if ((asset != null) && (asset.Name.Length > 0) && !asset.Name.Equals("From IAR"))
489 return asset.Name;
490 }
491
492 if (sop.Name != "Primitive")
493 return sop.Name;
494
495 if ((sop.ParentGroup != null) && (sop.ParentGroup.Name != "Primitive"))
496 return sop.ParentGroup.Name;
497
498 return "";
499 }
500
501
502 public string RenderMaterialsGetCap(string request)
503 {
504 OSDMap resp = new OSDMap();
505 int matsCount = 0;
506 OSDArray allOsd = new OSDArray();
507
508 lock (m_regionMaterials)
509 {
510 foreach (KeyValuePair<UUID, OSDMap> kvp in m_regionMaterials)
511 {
512 OSDMap matMap = new OSDMap();
513
514 matMap["ID"] = OSD.FromBinary(kvp.Key.GetBytes());
515 matMap["Material"] = kvp.Value;
516 allOsd.Add(matMap);
517 matsCount++;
518 }
519 }
520
521 resp["Zipped"] = ZCompressOSD(allOsd, false);
522
523 return OSDParser.SerializeLLSDXmlString(resp);
524 }
525
526 private static string ZippedOsdBytesToString(byte[] bytes)
527 {
528 try
529 {
530 return OSDParser.SerializeJsonString(ZDecompressBytesToOsd(bytes));
531 }
532 catch (Exception e)
533 {
534 return "ZippedOsdBytesToString caught an exception: " + e.ToString();
535 }
536 }
537
538 /// <summary>
539 /// computes a UUID by hashing a OSD object
540 /// </summary>
541 /// <param name="osd"></param>
542 /// <returns></returns>
543 private static UUID HashOsd(OSD osd)
544 {
545 byte[] data = OSDParser.SerializeLLSDBinary(osd, false);
546 using (var md5 = MD5.Create())
547 return new UUID(md5.ComputeHash(data), 0);
548 }
549
550 public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
551 {
552 OSD osd = null;
553
554 byte[] data = OSDParser.SerializeLLSDBinary(inOsd, useHeader);
555
556 using (MemoryStream msSinkCompressed = new MemoryStream())
557 {
558 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
559 Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
560 {
561 zOut.Write(data, 0, data.Length);
562 }
563
564 msSinkCompressed.Seek(0L, SeekOrigin.Begin);
565 osd = OSD.FromBinary(msSinkCompressed.ToArray());
566 }
567
568 return osd;
569 }
570
571
572 public static OSD ZDecompressBytesToOsd(byte[] input)
573 {
574 OSD osd = null;
575
576 using (MemoryStream msSinkUnCompressed = new MemoryStream())
577 {
578 using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true))
579 {
580 zOut.Write(input, 0, input.Length);
581 }
582
583 msSinkUnCompressed.Seek(0L, SeekOrigin.Begin);
584 osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
585 }
586
587 return osd;
588 }
589 }
590}
diff --git a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
index 70bda72..ba0b578 100644
--- a/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/OptionalModules/Properties/AssemblyInfo.cs
@@ -30,7 +30,7 @@ using Mono.Addins;
30// Build Number 30// Build Number
31// Revision 31// Revision
32// 32//
33[assembly: AssemblyVersion("0.7.6.*")] 33[assembly: AssemblyVersion("0.8.0.*")]
34 34
35 35
36[assembly: Addin("OpenSim.Region.OptionalModules", "0.1")] 36[assembly: Addin("OpenSim.Region.OptionalModules", "0.1")]
diff --git a/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs b/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs
index 6009dc5..9daf9d7 100755
--- a/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs
@@ -29,12 +29,14 @@ using System.Collections.Generic;
29using System.Linq; 29using System.Linq;
30using System.Reflection; 30using System.Reflection;
31using System.Text; 31using System.Text;
32using System.Threading;
32 33
33using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Region.CoreModules;
34using OpenSim.Region.Framework; 36using OpenSim.Region.Framework;
35using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
37using OpenSim.Region.CoreModules; 39using OpenSim.Region.Physics.Manager;
38 40
39using Mono.Addins; 41using Mono.Addins;
40using Nini.Config; 42using Nini.Config;
@@ -49,6 +51,24 @@ public class ExtendedPhysics : INonSharedRegionModule
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 private static string LogHeader = "[EXTENDED PHYSICS]"; 52 private static string LogHeader = "[EXTENDED PHYSICS]";
51 53
54 // =============================================================
55 // Since BulletSim is a plugin, this these values aren't defined easily in one place.
56 // This table must correspond to an identical table in BSScene.
57
58 // Per scene functions. See BSScene.
59
60 // Per avatar functions. See BSCharacter.
61
62 // Per prim functions. See BSPrim.
63 public const string PhysFunctGetLinksetType = "BulletSim.GetLinksetType";
64 public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType";
65 public const string PhysFunctChangeLinkFixed = "BulletSim.ChangeLinkFixed";
66 public const string PhysFunctChangeLinkType = "BulletSim.ChangeLinkType";
67 public const string PhysFunctGetLinkType = "BulletSim.GetLinkType";
68 public const string PhysFunctChangeLinkParams = "BulletSim.ChangeLinkParams";
69
70 // =============================================================
71
52 private IConfig Configuration { get; set; } 72 private IConfig Configuration { get; set; }
53 private bool Enabled { get; set; } 73 private bool Enabled { get; set; }
54 private Scene BaseScene { get; set; } 74 private Scene BaseScene { get; set; }
@@ -119,6 +139,7 @@ public class ExtendedPhysics : INonSharedRegionModule
119 139
120 // Register as LSL functions all the [ScriptInvocation] marked methods. 140 // Register as LSL functions all the [ScriptInvocation] marked methods.
121 Comms.RegisterScriptInvocations(this); 141 Comms.RegisterScriptInvocations(this);
142 Comms.RegisterConstants(this);
122 143
123 // When an object is modified, we might need to update its extended physics parameters 144 // When an object is modified, we might need to update its extended physics parameters
124 BaseScene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene; 145 BaseScene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
@@ -132,7 +153,6 @@ public class ExtendedPhysics : INonSharedRegionModule
132 153
133 private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj) 154 private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
134 { 155 {
135 throw new NotImplementedException();
136 } 156 }
137 157
138 // Event generated when some property of a prim changes. 158 // Event generated when some property of a prim changes.
@@ -141,14 +161,7 @@ public class ExtendedPhysics : INonSharedRegionModule
141 } 161 }
142 162
143 [ScriptConstant] 163 [ScriptConstant]
144 public static int PHYS_CENTER_OF_MASS = 1 << 0; 164 public const int PHYS_CENTER_OF_MASS = 1 << 0;
145
146 [ScriptConstant]
147 public static int PHYS_LINKSET_TYPE_CONSTRAINT = 1;
148 [ScriptConstant]
149 public static int PHYS_LINKSET_TYPE_COMPOUND = 2;
150 [ScriptConstant]
151 public static int PHYS_LINKSET_TYPE_MANUAL = 3;
152 165
153 [ScriptInvocation] 166 [ScriptInvocation]
154 public string physGetEngineType(UUID hostID, UUID scriptID) 167 public string physGetEngineType(UUID hostID, UUID scriptID)
@@ -163,9 +176,406 @@ public class ExtendedPhysics : INonSharedRegionModule
163 return ret; 176 return ret;
164 } 177 }
165 178
179 [ScriptConstant]
180 public const int PHYS_LINKSET_TYPE_CONSTRAINT = 0;
181 [ScriptConstant]
182 public const int PHYS_LINKSET_TYPE_COMPOUND = 1;
183 [ScriptConstant]
184 public const int PHYS_LINKSET_TYPE_MANUAL = 2;
185
186 [ScriptInvocation]
187 public int physSetLinksetType(UUID hostID, UUID scriptID, int linksetType)
188 {
189 int ret = -1;
190
191 if (!Enabled) return ret;
192
193 // The part that is requesting the change.
194 SceneObjectPart requestingPart = BaseScene.GetSceneObjectPart(hostID);
195
196 if (requestingPart != null)
197 {
198 // The change is always made to the root of a linkset.
199 SceneObjectGroup containingGroup = requestingPart.ParentGroup;
200 SceneObjectPart rootPart = containingGroup.RootPart;
201
202 if (rootPart != null)
203 {
204 PhysicsActor rootPhysActor = rootPart.PhysActor;
205 if (rootPhysActor != null)
206 {
207 if (rootPhysActor.IsPhysical)
208 {
209 // Change a physical linkset by making non-physical, waiting for one heartbeat so all
210 // the prim and linkset state is updated, changing the type and making the
211 // linkset physical again.
212 containingGroup.ScriptSetPhysicsStatus(false);
213 Thread.Sleep(150); // longer than one heartbeat tick
214
215 // A kludge for the moment.
216 // Since compound linksets move the children but don't generate position updates to the
217 // simulator, it is possible for compound linkset children to have out-of-sync simulator
218 // and physical positions. The following causes the simulator to push the real child positions
219 // down into the physics engine to get everything synced.
220 containingGroup.UpdateGroupPosition(containingGroup.AbsolutePosition);
221 containingGroup.UpdateGroupRotationR(containingGroup.GroupRotation);
222
223 object[] parms2 = { rootPhysActor, null, linksetType };
224 ret = MakeIntError(rootPhysActor.Extension(PhysFunctSetLinksetType, parms2));
225 Thread.Sleep(150); // longer than one heartbeat tick
226
227 containingGroup.ScriptSetPhysicsStatus(true);
228 }
229 else
230 {
231 // Non-physical linksets don't have a physical instantiation so there is no state to
232 // worry about being updated.
233 object[] parms2 = { rootPhysActor, null, linksetType };
234 ret = MakeIntError(rootPhysActor.Extension(PhysFunctSetLinksetType, parms2));
235 }
236 }
237 else
238 {
239 m_log.WarnFormat("{0} physSetLinksetType: root part does not have a physics actor. rootName={1}, hostID={2}",
240 LogHeader, rootPart.Name, hostID);
241 }
242 }
243 else
244 {
245 m_log.WarnFormat("{0} physSetLinksetType: root part does not exist. RequestingPartName={1}, hostID={2}",
246 LogHeader, requestingPart.Name, hostID);
247 }
248 }
249 else
250 {
251 m_log.WarnFormat("{0} physSetLinsetType: cannot find script object in scene. hostID={1}", LogHeader, hostID);
252 }
253 return ret;
254 }
255
166 [ScriptInvocation] 256 [ScriptInvocation]
167 public void physSetLinksetType(UUID hostID, UUID scriptID, int linksetType) 257 public int physGetLinksetType(UUID hostID, UUID scriptID)
168 { 258 {
259 int ret = -1;
260 if (!Enabled) return ret;
261
262 // The part that is requesting the change.
263 SceneObjectPart requestingPart = BaseScene.GetSceneObjectPart(hostID);
264
265 if (requestingPart != null)
266 {
267 // The type is is always on the root of a linkset.
268 SceneObjectGroup containingGroup = requestingPart.ParentGroup;
269 SceneObjectPart rootPart = containingGroup.RootPart;
270
271 if (rootPart != null)
272 {
273 PhysicsActor rootPhysActor = rootPart.PhysActor;
274 if (rootPhysActor != null)
275 {
276 object[] parms2 = { rootPhysActor, null };
277 ret = MakeIntError(rootPhysActor.Extension(PhysFunctGetLinksetType, parms2));
278 }
279 else
280 {
281 m_log.WarnFormat("{0} physGetLinksetType: root part does not have a physics actor. rootName={1}, hostID={2}",
282 LogHeader, rootPart.Name, hostID);
283 }
284 }
285 else
286 {
287 m_log.WarnFormat("{0} physGetLinksetType: root part does not exist. RequestingPartName={1}, hostID={2}",
288 LogHeader, requestingPart.Name, hostID);
289 }
290 }
291 else
292 {
293 m_log.WarnFormat("{0} physGetLinsetType: cannot find script object in scene. hostID={1}", LogHeader, hostID);
294 }
295 return ret;
296 }
297
298 [ScriptConstant]
299 public const int PHYS_LINK_TYPE_FIXED = 1234;
300 [ScriptConstant]
301 public const int PHYS_LINK_TYPE_HINGE = 4;
302 [ScriptConstant]
303 public const int PHYS_LINK_TYPE_SPRING = 9;
304 [ScriptConstant]
305 public const int PHYS_LINK_TYPE_6DOF = 6;
306 [ScriptConstant]
307 public const int PHYS_LINK_TYPE_SLIDER = 7;
308
309 // physChangeLinkType(integer linkNum, integer typeCode)
310 [ScriptInvocation]
311 public int physChangeLinkType(UUID hostID, UUID scriptID, int linkNum, int typeCode)
312 {
313 int ret = -1;
314 if (!Enabled) return ret;
315
316 PhysicsActor rootPhysActor;
317 PhysicsActor childPhysActor;
318
319 if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
320 {
321 object[] parms2 = { rootPhysActor, childPhysActor, typeCode };
322 ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkType, parms2));
323 }
324
325 return ret;
326 }
327
328 // physGetLinkType(integer linkNum)
329 [ScriptInvocation]
330 public int physGetLinkType(UUID hostID, UUID scriptID, int linkNum)
331 {
332 int ret = -1;
333 if (!Enabled) return ret;
334
335 PhysicsActor rootPhysActor;
336 PhysicsActor childPhysActor;
337
338 if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
339 {
340 object[] parms2 = { rootPhysActor, childPhysActor };
341 ret = MakeIntError(rootPhysActor.Extension(PhysFunctGetLinkType, parms2));
342 }
343
344 return ret;
345 }
346
347 // physChangeLinkFixed(integer linkNum)
348 // Change the link between the root and the linkNum into a fixed, static physical connection.
349 [ScriptInvocation]
350 public int physChangeLinkFixed(UUID hostID, UUID scriptID, int linkNum)
351 {
352 int ret = -1;
353 if (!Enabled) return ret;
354
355 PhysicsActor rootPhysActor;
356 PhysicsActor childPhysActor;
357
358 if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
359 {
360 object[] parms2 = { rootPhysActor, childPhysActor , PHYS_LINK_TYPE_FIXED };
361 ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkType, parms2));
362 }
363
364 return ret;
365 }
366
367 // Code for specifying params.
368 // The choice if 14400 is arbitrary and only serves to catch parameter code misuse.
369 public const int PHYS_PARAM_MIN = 14401;
370
371 [ScriptConstant]
372 public const int PHYS_PARAM_FRAMEINA_LOC = 14401;
373 [ScriptConstant]
374 public const int PHYS_PARAM_FRAMEINA_ROT = 14402;
375 [ScriptConstant]
376 public const int PHYS_PARAM_FRAMEINB_LOC = 14403;
377 [ScriptConstant]
378 public const int PHYS_PARAM_FRAMEINB_ROT = 14404;
379 [ScriptConstant]
380 public const int PHYS_PARAM_LINEAR_LIMIT_LOW = 14405;
381 [ScriptConstant]
382 public const int PHYS_PARAM_LINEAR_LIMIT_HIGH = 14406;
383 [ScriptConstant]
384 public const int PHYS_PARAM_ANGULAR_LIMIT_LOW = 14407;
385 [ScriptConstant]
386 public const int PHYS_PARAM_ANGULAR_LIMIT_HIGH = 14408;
387 [ScriptConstant]
388 public const int PHYS_PARAM_USE_FRAME_OFFSET = 14409;
389 [ScriptConstant]
390 public const int PHYS_PARAM_ENABLE_TRANSMOTOR = 14410;
391 [ScriptConstant]
392 public const int PHYS_PARAM_TRANSMOTOR_MAXVEL = 14411;
393 [ScriptConstant]
394 public const int PHYS_PARAM_TRANSMOTOR_MAXFORCE = 14412;
395 [ScriptConstant]
396 public const int PHYS_PARAM_CFM = 14413;
397 [ScriptConstant]
398 public const int PHYS_PARAM_ERP = 14414;
399 [ScriptConstant]
400 public const int PHYS_PARAM_SOLVER_ITERATIONS = 14415;
401 [ScriptConstant]
402 public const int PHYS_PARAM_SPRING_AXIS_ENABLE = 14416;
403 [ScriptConstant]
404 public const int PHYS_PARAM_SPRING_DAMPING = 14417;
405 [ScriptConstant]
406 public const int PHYS_PARAM_SPRING_STIFFNESS = 14418;
407 [ScriptConstant]
408 public const int PHYS_PARAM_LINK_TYPE = 14419;
409 [ScriptConstant]
410 public const int PHYS_PARAM_USE_LINEAR_FRAMEA = 14420;
411 [ScriptConstant]
412 public const int PHYS_PARAM_SPRING_EQUILIBRIUM_POINT = 14421;
413
414 public const int PHYS_PARAM_MAX = 14421;
415
416 // Used when specifying a parameter that has settings for the three linear and three angular axis
417 [ScriptConstant]
418 public const int PHYS_AXIS_ALL = -1;
419 [ScriptConstant]
420 public const int PHYS_AXIS_LINEAR_ALL = -2;
421 [ScriptConstant]
422 public const int PHYS_AXIS_ANGULAR_ALL = -3;
423 [ScriptConstant]
424 public const int PHYS_AXIS_LINEAR_X = 0;
425 [ScriptConstant]
426 public const int PHYS_AXIS_LINEAR_Y = 1;
427 [ScriptConstant]
428 public const int PHYS_AXIS_LINEAR_Z = 2;
429 [ScriptConstant]
430 public const int PHYS_AXIS_ANGULAR_X = 3;
431 [ScriptConstant]
432 public const int PHYS_AXIS_ANGULAR_Y = 4;
433 [ScriptConstant]
434 public const int PHYS_AXIS_ANGULAR_Z = 5;
435
436 // physChangeLinkParams(integer linkNum, [ PHYS_PARAM_*, value, PHYS_PARAM_*, value, ...])
437 [ScriptInvocation]
438 public int physChangeLinkParams(UUID hostID, UUID scriptID, int linkNum, object[] parms)
439 {
440 int ret = -1;
441 if (!Enabled) return ret;
442
443 PhysicsActor rootPhysActor;
444 PhysicsActor childPhysActor;
445
446 if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
447 {
448 object[] parms2 = AddToBeginningOfArray(rootPhysActor, childPhysActor, parms);
449 ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkParams, parms2));
450 }
451
452 return ret;
453 }
454
455 private bool GetRootPhysActor(UUID hostID, out PhysicsActor rootPhysActor)
456 {
457 SceneObjectGroup containingGroup;
458 SceneObjectPart rootPart;
459 return GetRootPhysActor(hostID, out containingGroup, out rootPart, out rootPhysActor);
460 }
461
462 private bool GetRootPhysActor(UUID hostID, out SceneObjectGroup containingGroup, out SceneObjectPart rootPart, out PhysicsActor rootPhysActor)
463 {
464 bool ret = false;
465 rootPhysActor = null;
466 containingGroup = null;
467 rootPart = null;
468
469 SceneObjectPart requestingPart;
470
471 requestingPart = BaseScene.GetSceneObjectPart(hostID);
472 if (requestingPart != null)
473 {
474 // The type is is always on the root of a linkset.
475 containingGroup = requestingPart.ParentGroup;
476 if (containingGroup != null && !containingGroup.IsDeleted)
477 {
478 rootPart = containingGroup.RootPart;
479 if (rootPart != null)
480 {
481 rootPhysActor = rootPart.PhysActor;
482 if (rootPhysActor != null)
483 {
484 ret = true;
485 }
486 else
487 {
488 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not have a physics actor. rootName={1}, hostID={2}",
489 LogHeader, rootPart.Name, hostID);
490 }
491 }
492 else
493 {
494 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not exist. RequestingPartName={1}, hostID={2}",
495 LogHeader, requestingPart.Name, hostID);
496 }
497 }
498 else
499 {
500 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Containing group missing or deleted. hostID={1}", LogHeader, hostID);
501 }
502 }
503 else
504 {
505 m_log.WarnFormat("{0} GetRootAndChildPhysActors: cannot find script object in scene. hostID={1}", LogHeader, hostID);
506 }
507
508 return ret;
509 }
510
511 // Find the root and child PhysActors based on the linkNum.
512 // Return 'true' if both are found and returned.
513 private bool GetRootAndChildPhysActors(UUID hostID, int linkNum, out PhysicsActor rootPhysActor, out PhysicsActor childPhysActor)
514 {
515 bool ret = false;
516 rootPhysActor = null;
517 childPhysActor = null;
518
519 SceneObjectGroup containingGroup;
520 SceneObjectPart rootPart;
521
522 if (GetRootPhysActor(hostID, out containingGroup, out rootPart, out rootPhysActor))
523 {
524 SceneObjectPart linkPart = containingGroup.GetLinkNumPart(linkNum);
525 if (linkPart != null)
526 {
527 childPhysActor = linkPart.PhysActor;
528 if (childPhysActor != null)
529 {
530 ret = true;
531 }
532 else
533 {
534 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Link part has no physical actor. rootName={1}, hostID={2}, linknum={3}",
535 LogHeader, rootPart.Name, hostID, linkNum);
536 }
537 }
538 else
539 {
540 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Could not find linknum part. rootName={1}, hostID={2}, linknum={3}",
541 LogHeader, rootPart.Name, hostID, linkNum);
542 }
543 }
544 else
545 {
546 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not have a physics actor. rootName={1}, hostID={2}",
547 LogHeader, rootPart.Name, hostID);
548 }
549
550 return ret;
551 }
552
553 // Return an array of objects with the passed object as the first object of a new array
554 private object[] AddToBeginningOfArray(object firstOne, object secondOne, object[] prevArray)
555 {
556 object[] newArray = new object[2 + prevArray.Length];
557 newArray[0] = firstOne;
558 newArray[1] = secondOne;
559 prevArray.CopyTo(newArray, 2);
560 return newArray;
561 }
562
563 // Extension() returns an object. Convert that object into the integer error we expect to return.
564 private int MakeIntError(object extensionRet)
565 {
566 int ret = -1;
567 if (extensionRet != null)
568 {
569 try
570 {
571 ret = (int)extensionRet;
572 }
573 catch
574 {
575 ret = -1;
576 }
577 }
578 return ret;
169 } 579 }
170} 580}
171} 581}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs
new file mode 100644
index 0000000..d4b19dd
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreCommands.cs
@@ -0,0 +1,195 @@
1/*
2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using Mono.Addins;
28
29using System;
30using System.Reflection;
31using System.Threading;
32using System.Text;
33using System.Net;
34using System.Net.Sockets;
35using log4net;
36using Nini.Config;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic;
43using System.Text.RegularExpressions;
44
45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreCommandsModule")]
48
49 public class JsonStoreCommandsModule : INonSharedRegionModule
50 {
51 private static readonly ILog m_log =
52 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private IConfig m_config = null;
55 private bool m_enabled = false;
56
57 private Scene m_scene = null;
58 //private IJsonStoreModule m_store;
59 private JsonStoreModule m_store;
60
61#region Region Module interface
62
63 // -----------------------------------------------------------------
64 /// <summary>
65 /// Name of this shared module is it's class name
66 /// </summary>
67 // -----------------------------------------------------------------
68 public string Name
69 {
70 get { return this.GetType().Name; }
71 }
72
73 // -----------------------------------------------------------------
74 /// <summary>
75 /// Initialise this shared module
76 /// </summary>
77 /// <param name="scene">this region is getting initialised</param>
78 /// <param name="source">nini config, we are not using this</param>
79 // -----------------------------------------------------------------
80 public void Initialise(IConfigSource config)
81 {
82 try
83 {
84 if ((m_config = config.Configs["JsonStore"]) == null)
85 {
86 // There is no configuration, the module is disabled
87 // m_log.InfoFormat("[JsonStore] no configuration info");
88 return;
89 }
90
91 m_enabled = m_config.GetBoolean("Enabled", m_enabled);
92 }
93 catch (Exception e)
94 {
95 m_log.Error("[JsonStore]: initialization error: {0}", e);
96 return;
97 }
98
99 if (m_enabled)
100 m_log.DebugFormat("[JsonStore]: module is enabled");
101 }
102
103 // -----------------------------------------------------------------
104 /// <summary>
105 /// everything is loaded, perform post load configuration
106 /// </summary>
107 // -----------------------------------------------------------------
108 public void PostInitialise()
109 {
110 }
111
112 // -----------------------------------------------------------------
113 /// <summary>
114 /// Nothing to do on close
115 /// </summary>
116 // -----------------------------------------------------------------
117 public void Close()
118 {
119 }
120
121 // -----------------------------------------------------------------
122 /// <summary>
123 /// </summary>
124 // -----------------------------------------------------------------
125 public void AddRegion(Scene scene)
126 {
127 if (m_enabled)
128 {
129 m_scene = scene;
130
131 }
132 }
133
134 // -----------------------------------------------------------------
135 /// <summary>
136 /// </summary>
137 // -----------------------------------------------------------------
138 public void RemoveRegion(Scene scene)
139 {
140 // need to remove all references to the scene in the subscription
141 // list to enable full garbage collection of the scene object
142 }
143
144 // -----------------------------------------------------------------
145 /// <summary>
146 /// Called when all modules have been added for a region. This is
147 /// where we hook up events
148 /// </summary>
149 // -----------------------------------------------------------------
150 public void RegionLoaded(Scene scene)
151 {
152 if (m_enabled)
153 {
154 m_scene = scene;
155
156 m_store = (JsonStoreModule) m_scene.RequestModuleInterface<IJsonStoreModule>();
157 if (m_store == null)
158 {
159 m_log.ErrorFormat("[JsonStoreCommands]: JsonModule interface not defined");
160 m_enabled = false;
161 return;
162 }
163
164 scene.AddCommand("JsonStore", this, "jsonstore stats", "jsonstore stats",
165 "Display statistics about the state of the JsonStore module", "",
166 CmdStats);
167 }
168 }
169
170 /// -----------------------------------------------------------------
171 /// <summary>
172 /// </summary>
173 // -----------------------------------------------------------------
174 public Type ReplaceableInterface
175 {
176 get { return null; }
177 }
178
179#endregion
180
181#region Commands
182
183 private void CmdStats(string module, string[] cmd)
184 {
185 if (MainConsole.Instance.ConsoleScene != m_scene && MainConsole.Instance.ConsoleScene != null)
186 return;
187
188 JsonStoreStats stats = m_store.GetStoreStats();
189 MainConsole.Instance.OutputFormat("{0}\t{1}",m_scene.RegionInfo.RegionName,stats.StoreCount);
190 }
191
192#endregion
193
194 }
195}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
index 5fbfcc5..b502a55 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
@@ -42,7 +42,6 @@ using OpenSim.Region.Framework.Scenes;
42using System.Collections.Generic; 42using System.Collections.Generic;
43using System.Text.RegularExpressions; 43using System.Text.RegularExpressions;
44 44
45
46namespace OpenSim.Region.OptionalModules.Scripting.JsonStore 45namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
47{ 46{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")] 47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "JsonStoreModule")]
@@ -60,6 +59,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
60 private Scene m_scene = null; 59 private Scene m_scene = null;
61 60
62 private Dictionary<UUID,JsonStore> m_JsonValueStore; 61 private Dictionary<UUID,JsonStore> m_JsonValueStore;
62
63 private UUID m_sharedStore; 63 private UUID m_sharedStore;
64 64
65#region Region Module interface 65#region Region Module interface
@@ -140,6 +140,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
140 m_sharedStore = UUID.Zero; 140 m_sharedStore = UUID.Zero;
141 m_JsonValueStore = new Dictionary<UUID,JsonStore>(); 141 m_JsonValueStore = new Dictionary<UUID,JsonStore>();
142 m_JsonValueStore.Add(m_sharedStore,new JsonStore("")); 142 m_JsonValueStore.Add(m_sharedStore,new JsonStore(""));
143
144 scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene;
143 } 145 }
144 } 146 }
145 147
@@ -149,6 +151,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
149 // ----------------------------------------------------------------- 151 // -----------------------------------------------------------------
150 public void RemoveRegion(Scene scene) 152 public void RemoveRegion(Scene scene)
151 { 153 {
154 scene.EventManager.OnObjectBeingRemovedFromScene -= EventManagerOnObjectBeingRemovedFromScene;
155
152 // need to remove all references to the scene in the subscription 156 // need to remove all references to the scene in the subscription
153 // list to enable full garbage collection of the scene object 157 // list to enable full garbage collection of the scene object
154 } 158 }
@@ -161,7 +165,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
161 // ----------------------------------------------------------------- 165 // -----------------------------------------------------------------
162 public void RegionLoaded(Scene scene) 166 public void RegionLoaded(Scene scene)
163 { 167 {
164 if (m_enabled) {} 168 if (m_enabled)
169 {
170 }
165 } 171 }
166 172
167 /// ----------------------------------------------------------------- 173 /// -----------------------------------------------------------------
@@ -175,8 +181,39 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
175 181
176#endregion 182#endregion
177 183
184#region SceneEvents
185 // -----------------------------------------------------------------
186 /// <summary>
187 ///
188 /// </summary>
189 // -----------------------------------------------------------------
190 public void EventManagerOnObjectBeingRemovedFromScene(SceneObjectGroup obj)
191 {
192 obj.ForEachPart(delegate(SceneObjectPart sop) { DestroyStore(sop.UUID); } );
193 }
194
195#endregion
196
178#region ScriptInvocationInteface 197#region ScriptInvocationInteface
179 198
199
200 // -----------------------------------------------------------------
201 /// <summary>
202 ///
203 /// </summary>
204 // -----------------------------------------------------------------
205 public JsonStoreStats GetStoreStats()
206 {
207 JsonStoreStats stats;
208
209 lock (m_JsonValueStore)
210 {
211 stats.StoreCount = m_JsonValueStore.Count;
212 }
213
214 return stats;
215 }
216
180 // ----------------------------------------------------------------- 217 // -----------------------------------------------------------------
181 /// <summary> 218 /// <summary>
182 /// 219 ///
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
index 1bb5aee..9fbfb66 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
@@ -59,7 +59,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
59 59
60 private IScriptModuleComms m_comms; 60 private IScriptModuleComms m_comms;
61 private IJsonStoreModule m_store; 61 private IJsonStoreModule m_store;
62 62
63 private Dictionary<UUID,HashSet<UUID>> m_scriptStores = new Dictionary<UUID,HashSet<UUID>>();
64
63#region Region Module interface 65#region Region Module interface
64 66
65 // ----------------------------------------------------------------- 67 // -----------------------------------------------------------------
@@ -126,6 +128,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
126 // ----------------------------------------------------------------- 128 // -----------------------------------------------------------------
127 public void AddRegion(Scene scene) 129 public void AddRegion(Scene scene)
128 { 130 {
131 scene.EventManager.OnScriptReset += HandleScriptReset;
132 scene.EventManager.OnRemoveScript += HandleScriptReset;
129 } 133 }
130 134
131 // ----------------------------------------------------------------- 135 // -----------------------------------------------------------------
@@ -134,12 +138,34 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
134 // ----------------------------------------------------------------- 138 // -----------------------------------------------------------------
135 public void RemoveRegion(Scene scene) 139 public void RemoveRegion(Scene scene)
136 { 140 {
141 scene.EventManager.OnScriptReset -= HandleScriptReset;
142 scene.EventManager.OnRemoveScript -= HandleScriptReset;
143
137 // need to remove all references to the scene in the subscription 144 // need to remove all references to the scene in the subscription
138 // list to enable full garbage collection of the scene object 145 // list to enable full garbage collection of the scene object
139 } 146 }
140 147
141 // ----------------------------------------------------------------- 148 // -----------------------------------------------------------------
142 /// <summary> 149 /// <summary>
150 /// </summary>
151 // -----------------------------------------------------------------
152 private void HandleScriptReset(uint localID, UUID itemID)
153 {
154 HashSet<UUID> stores;
155
156 lock (m_scriptStores)
157 {
158 if (! m_scriptStores.TryGetValue(itemID, out stores))
159 return;
160 m_scriptStores.Remove(itemID);
161 }
162
163 foreach (UUID id in stores)
164 m_store.DestroyStore(id);
165 }
166
167 // -----------------------------------------------------------------
168 /// <summary>
143 /// Called when all modules have been added for a region. This is 169 /// Called when all modules have been added for a region. This is
144 /// where we hook up events 170 /// where we hook up events
145 /// </summary> 171 /// </summary>
@@ -250,6 +276,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
250 if (! m_store.CreateStore(value, ref uuid)) 276 if (! m_store.CreateStore(value, ref uuid))
251 GenerateRuntimeError("Failed to create Json store"); 277 GenerateRuntimeError("Failed to create Json store");
252 278
279 lock (m_scriptStores)
280 {
281 if (! m_scriptStores.ContainsKey(scriptID))
282 m_scriptStores[scriptID] = new HashSet<UUID>();
283
284 m_scriptStores[scriptID].Add(uuid);
285 }
253 return uuid; 286 return uuid;
254 } 287 }
255 288
@@ -261,6 +294,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
261 [ScriptInvocation] 294 [ScriptInvocation]
262 public int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID) 295 public int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID)
263 { 296 {
297 lock(m_scriptStores)
298 {
299 if (m_scriptStores.ContainsKey(scriptID))
300 m_scriptStores[scriptID].Remove(storeID);
301 }
302
264 return m_store.DestroyStore(storeID) ? 1 : 0; 303 return m_store.DestroyStore(storeID) ? 1 : 0;
265 } 304 }
266 305
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
index c550c44..eb386fe 100644
--- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
@@ -105,7 +105,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
105 m_scene.LoginLock = true; 105 m_scene.LoginLock = true;
106 m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; 106 m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue;
107 107
108 m_log.InfoFormat("[RegionReady]: Region {0} - LOGINS DISABLED DURING INITIALIZATION.", m_scene.Name); 108 // Warn level because the region cannot be used while logins are disabled
109 m_log.WarnFormat("[RegionReady]: Region {0} - LOGINS DISABLED DURING INITIALIZATION.", m_scene.Name);
109 110
110 if (m_uri != string.Empty) 111 if (m_uri != string.Empty)
111 { 112 {
@@ -215,8 +216,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
215 // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", 216 // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}",
216 // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); 217 // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString());
217 218
218 m_log.InfoFormat( 219 // Putting this out to console to make it eye-catching for people who are running OpenSimulator
219 "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); 220 // without info log messages enabled. Making this a warning is arguably misleading since it isn't a
221 // warning, and monitor scripts looking for warn/error/fatal messages will received false positives.
222 // Arguably, log4net needs a status log level (like Apache).
223 MainConsole.Instance.OutputFormat("INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name);
220 } 224 }
221 225
222 m_scene.SceneGridService.InformNeighborsThatRegionisUp( 226 m_scene.SceneGridService.InformNeighborsThatRegionisUp(
diff --git a/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs
index c68fe99..3b3b300 100644
--- a/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs
+++ b/OpenSim/Region/OptionalModules/ViewerSupport/DynamicMenuModule.cs
@@ -263,7 +263,7 @@ namespace OpenSim.Region.OptionalModules.ViewerSupport
263 m_module = module; 263 m_module = module;
264 } 264 }
265 265
266 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 266 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
267 { 267 {
268 StreamReader reader = new StreamReader(request); 268 StreamReader reader = new StreamReader(request);
269 string requestBody = reader.ReadToEnd(); 269 string requestBody = reader.ReadToEnd();
diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
index 5d10e93..bcb21d0 100644
--- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
+++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs
@@ -696,7 +696,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule
696 /// <param name="agentId"></param> 696 /// <param name="agentId"></param>
697 public void EconomyDataRequestHandler(IClientAPI user) 697 public void EconomyDataRequestHandler(IClientAPI user)
698 { 698 {
699 Scene s = LocateSceneClientIn(user.AgentId); 699 Scene s = (Scene)user.Scene;
700 700
701 user.SendEconomyData(EnergyEfficiency, s.RegionInfo.ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate, 701 user.SendEconomyData(EnergyEfficiency, s.RegionInfo.ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate,
702 PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor, 702 PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor,
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 4674489..c88ccc5 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -44,6 +44,20 @@ namespace OpenSim.Region.OptionalModules.World.NPC
44 { 44 {
45 public bool SenseAsAgent { get; set; } 45 public bool SenseAsAgent { get; set; }
46 46
47 public delegate void ChatToNPC(
48 string message, byte type, Vector3 fromPos, string fromName,
49 UUID fromAgentID, UUID ownerID, byte source, byte audible);
50
51 /// <summary>
52 /// Fired when the NPC receives a chat message.
53 /// </summary>
54 public event ChatToNPC OnChatToNPC;
55
56 /// <summary>
57 /// Fired when the NPC receives an instant message.
58 /// </summary>
59 public event Action<GridInstantMessage> OnInstantMessageToNPC;
60
47 private readonly string m_firstname; 61 private readonly string m_firstname;
48 private readonly string m_lastname; 62 private readonly string m_lastname;
49 private readonly Vector3 m_startPos; 63 private readonly Vector3 m_startPos;
@@ -259,6 +273,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
259 public event Action<IClientAPI, bool> OnCompleteMovementToRegion; 273 public event Action<IClientAPI, bool> OnCompleteMovementToRegion;
260 public event UpdateAgent OnPreAgentUpdate; 274 public event UpdateAgent OnPreAgentUpdate;
261 public event UpdateAgent OnAgentUpdate; 275 public event UpdateAgent OnAgentUpdate;
276 public event UpdateAgent OnAgentCameraUpdate;
262 public event AgentRequestSit OnAgentRequestSit; 277 public event AgentRequestSit OnAgentRequestSit;
263 public event AgentSit OnAgentSit; 278 public event AgentSit OnAgentSit;
264 public event AvatarPickerRequest OnAvatarPickerRequest; 279 public event AvatarPickerRequest OnAvatarPickerRequest;
@@ -393,6 +408,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
393 public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest; 408 public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest;
394 public event EstateChangeInfo OnEstateChangeInfo; 409 public event EstateChangeInfo OnEstateChangeInfo;
395 public event EstateManageTelehub OnEstateManageTelehub; 410 public event EstateManageTelehub OnEstateManageTelehub;
411 public event CachedTextureRequest OnCachedTextureRequest;
396 public event ScriptReset OnScriptReset; 412 public event ScriptReset OnScriptReset;
397 public event GetScriptRunning OnGetScriptRunning; 413 public event GetScriptRunning OnGetScriptRunning;
398 public event SetScriptRunning OnSetScriptRunning; 414 public event SetScriptRunning OnSetScriptRunning;
@@ -573,6 +589,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
573 { 589 {
574 } 590 }
575 591
592 public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures)
593 {
594
595 }
596
576 public virtual void Kick(string message) 597 public virtual void Kick(string message)
577 { 598 {
578 } 599 }
@@ -590,7 +611,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
590 611
591 } 612 }
592 613
593 public virtual void SendKillObject(ulong regionHandle, List<uint> localID) 614 public virtual void SendKillObject(List<uint> localID)
594 { 615 {
595 } 616 }
596 617
@@ -617,17 +638,18 @@ namespace OpenSim.Region.OptionalModules.World.NPC
617 string message, byte type, Vector3 fromPos, string fromName, 638 string message, byte type, Vector3 fromPos, string fromName,
618 UUID fromAgentID, UUID ownerID, byte source, byte audible) 639 UUID fromAgentID, UUID ownerID, byte source, byte audible)
619 { 640 {
620 } 641 ChatToNPC ctn = OnChatToNPC;
621 642
622 public virtual void SendChatMessage( 643 if (ctn != null)
623 byte[] message, byte type, Vector3 fromPos, string fromName, 644 ctn(message, type, fromPos, fromName, fromAgentID, ownerID, source, audible);
624 UUID fromAgentID, UUID ownerID, byte source, byte audible)
625 {
626 } 645 }
627 646
628 public void SendInstantMessage(GridInstantMessage im) 647 public void SendInstantMessage(GridInstantMessage im)
629 { 648 {
630 649 Action<GridInstantMessage> oimtn = OnInstantMessageToNPC;
650
651 if (oimtn != null)
652 oimtn(im);
631 } 653 }
632 654
633 public void SendGenericMessage(string method, UUID invoice, List<string> message) 655 public void SendGenericMessage(string method, UUID invoice, List<string> message)
@@ -1236,7 +1258,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
1236 { 1258 {
1237 } 1259 }
1238 1260
1239 public void StopFlying(ISceneEntity presence) 1261 public void SendAgentTerseUpdate(ISceneEntity presence)
1240 { 1262 {
1241 } 1263 }
1242 1264
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 8c9c006..9ec4740 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -116,7 +116,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
116 return false; 116 return false;
117 117
118 // Delete existing npc attachments 118 // Delete existing npc attachments
119 scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false); 119 if(scene.AttachmentsModule != null)
120 scene.AttachmentsModule.DeleteAttachmentsFromScene(npc, false);
120 121
121 // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet 122 // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet
122 // since it doesn't transfer attachments 123 // since it doesn't transfer attachments
@@ -125,7 +126,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
125 npc.Appearance = npcAppearance; 126 npc.Appearance = npcAppearance;
126 127
127 // Rez needed npc attachments 128 // Rez needed npc attachments
128 scene.AttachmentsModule.RezAttachments(npc); 129 if (scene.AttachmentsModule != null)
130 scene.AttachmentsModule.RezAttachments(npc);
129 131
130 IAvatarFactoryModule module = 132 IAvatarFactoryModule module =
131 scene.RequestModuleInterface<IAvatarFactoryModule>(); 133 scene.RequestModuleInterface<IAvatarFactoryModule>();
@@ -174,7 +176,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
174 lock (m_avatars) 176 lock (m_avatars)
175 { 177 {
176 scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd); 178 scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
177 scene.AddNewClient(npcAvatar, PresenceType.Npc); 179 scene.AddNewAgent(npcAvatar, PresenceType.Npc);
178 180
179 ScenePresence sp; 181 ScenePresence sp;
180 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp)) 182 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
@@ -205,8 +207,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC
205 if (scene.TryGetScenePresence(agentID, out sp)) 207 if (scene.TryGetScenePresence(agentID, out sp))
206 { 208 {
207// m_log.DebugFormat( 209// m_log.DebugFormat(
208// "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}", 210// "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
209// sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget); 211// sp.Name, pos, scene.RegionInfo.RegionName,
212// noFly, landAtTarget);
210 213
211 sp.MoveToTarget(pos, noFly, landAtTarget); 214 sp.MoveToTarget(pos, noFly, landAtTarget);
212 sp.SetAlwaysRun = running; 215 sp.SetAlwaysRun = running;
@@ -283,9 +286,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
283 ScenePresence sp; 286 ScenePresence sp;
284 if (scene.TryGetScenePresence(agentID, out sp)) 287 if (scene.TryGetScenePresence(agentID, out sp))
285 { 288 {
286 sp.HandleAgentRequestSit(m_avatars[agentID], agentID, 289 sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero);
287 partID, Vector3.Zero);
288 //sp.HandleAgentSit(m_avatars[agentID], agentID);
289 290
290 return true; 291 return true;
291 } 292 }
@@ -375,10 +376,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
375 m_log.DebugFormat("[NPC MODULE]: Found {0} {1} to remove", 376 m_log.DebugFormat("[NPC MODULE]: Found {0} {1} to remove",
376 agentID, av.Name); 377 agentID, av.Name);
377 */ 378 */
378 scene.RemoveClient(agentID, false); 379
380 scene.CloseAgent(agentID, false);
381
379 m_avatars.Remove(agentID); 382 m_avatars.Remove(agentID);
380 383
381// m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}", agentID, av.Name); 384 /*
385 m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}",
386 agentID, av.Name);
387 */
382 return true; 388 return true;
383 } 389 }
384 } 390 }
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index 34362af..14eb25b 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -155,7 +155,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
155 public void TestCreateWithAttachments() 155 public void TestCreateWithAttachments()
156 { 156 {
157 TestHelpers.InMethod(); 157 TestHelpers.InMethod();
158// log4net.Config.XmlConfigurator.Configure(); 158// TestHelpers.EnableLogging();
159 159
160 UUID userId = TestHelpers.ParseTail(0x1); 160 UUID userId = TestHelpers.ParseTail(0x1);
161 UserAccountHelpers.CreateUserWithInventory(m_scene, userId); 161 UserAccountHelpers.CreateUserWithInventory(m_scene, userId);
@@ -321,9 +321,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
321 321
322 Assert.That(part.SitTargetAvatar, Is.EqualTo(npcId)); 322 Assert.That(part.SitTargetAvatar, Is.EqualTo(npcId));
323 Assert.That(npc.ParentID, Is.EqualTo(part.LocalId)); 323 Assert.That(npc.ParentID, Is.EqualTo(part.LocalId));
324 Assert.That( 324// Assert.That(
325 npc.AbsolutePosition, 325// npc.AbsolutePosition,
326 Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); 326// Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT));
327 327
328 m_npcMod.Stand(npc.UUID, m_scene); 328 m_npcMod.Stand(npc.UUID, m_scene);
329 329
@@ -335,7 +335,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
335 public void TestSitAndStandWithNoSitTarget() 335 public void TestSitAndStandWithNoSitTarget()
336 { 336 {
337 TestHelpers.InMethod(); 337 TestHelpers.InMethod();
338// log4net.Config.XmlConfigurator.Configure(); 338// TestHelpers.EnableLogging();
339 339
340 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); 340 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1));
341 341
@@ -353,13 +353,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
353 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); 353 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
354 Assert.That(npc.ParentID, Is.EqualTo(part.LocalId)); 354 Assert.That(npc.ParentID, Is.EqualTo(part.LocalId));
355 355
356 // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the 356 // We should really be using the NPC size but this would mean preserving the physics actor since it is
357 // default avatar. 357 // removed on sit.
358 // Curiously, Vector3.ToString() will not display the last two places of the float. For example,
359 // printing out npc.AbsolutePosition will give <0, 0, 0.8454993> not <0, 0, 0.845499337>
360 Assert.That( 358 Assert.That(
361 npc.AbsolutePosition, 359 npc.AbsolutePosition,
362 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, 0.845499337f))); 360 Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, sp.PhysicsActor.Size.Z / 2)));
363 361
364 m_npcMod.Stand(npc.UUID, m_scene); 362 m_npcMod.Stand(npc.UUID, m_scene);
365 363
diff --git a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs
index 550b5d4..8720cc7 100644
--- a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs
+++ b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.OptionalModules.World.WorldView
55 m_WorldViewModule = fmodule; 55 m_WorldViewModule = fmodule;
56 } 56 }
57 57
58 public override byte[] Handle(string path, Stream requestData, 58 protected override byte[] ProcessRequest(string path, Stream requestData,
59 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 59 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
60 { 60 {
61 httpResponse.ContentType = "image/jpeg"; 61 httpResponse.ContentType = "image/jpeg";
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs
index 6fd6f7e..ffcb01e 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.7.6.*")] 58[assembly : AssemblyVersion("0.8.0.*")]
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
index e43136a..0d17e0e 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs
@@ -118,14 +118,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
118 118
119 public override Vector3 Position { get; set; } 119 public override Vector3 Position { get; set; }
120 120
121 public override Vector3 Size 121 public override Vector3 Size { get; set; }
122 {
123 get { return _size; }
124 set {
125 _size = value;
126 _size.Z = _size.Z / 2.0f;
127 }
128 }
129 122
130 public override PrimitiveBaseShape Shape 123 public override PrimitiveBaseShape Shape
131 { 124 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
index f5b84d4..3bd81d4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
@@ -75,11 +75,11 @@ private sealed class BulletBodyUnman : BulletBody
75private sealed class BulletShapeUnman : BulletShape 75private sealed class BulletShapeUnman : BulletShape
76{ 76{
77 public IntPtr ptr; 77 public IntPtr ptr;
78 public BulletShapeUnman(IntPtr xx, BSPhysicsShapeType typ) 78 public BulletShapeUnman(IntPtr xx, BSPhysicsShapeType typ)
79 : base() 79 : base()
80 { 80 {
81 ptr = xx; 81 ptr = xx;
82 type = typ; 82 shapeType = typ;
83 } 83 }
84 public override bool HasPhysicalShape 84 public override bool HasPhysicalShape
85 { 85 {
@@ -91,7 +91,7 @@ private sealed class BulletShapeUnman : BulletShape
91 } 91 }
92 public override BulletShape Clone() 92 public override BulletShape Clone()
93 { 93 {
94 return new BulletShapeUnman(ptr, type); 94 return new BulletShapeUnman(ptr, shapeType);
95 } 95 }
96 public override bool ReferenceSame(BulletShape other) 96 public override bool ReferenceSame(BulletShape other)
97 { 97 {
@@ -251,11 +251,21 @@ public override BulletShape CreateMeshShape(BulletWorld world,
251 BSPhysicsShapeType.SHAPE_MESH); 251 BSPhysicsShapeType.SHAPE_MESH);
252} 252}
253 253
254public override BulletShape CreateGImpactShape(BulletWorld world,
255 int indicesCount, int[] indices,
256 int verticesCount, float[] vertices)
257{
258 BulletWorldUnman worldu = world as BulletWorldUnman;
259 return new BulletShapeUnman(
260 BSAPICPP.CreateGImpactShape2(worldu.ptr, indicesCount, indices, verticesCount, vertices),
261 BSPhysicsShapeType.SHAPE_GIMPACT);
262}
263
254public override BulletShape CreateHullShape(BulletWorld world, int hullCount, float[] hulls) 264public override BulletShape CreateHullShape(BulletWorld world, int hullCount, float[] hulls)
255{ 265{
256 BulletWorldUnman worldu = world as BulletWorldUnman; 266 BulletWorldUnman worldu = world as BulletWorldUnman;
257 return new BulletShapeUnman( 267 return new BulletShapeUnman(
258 BSAPICPP.CreateHullShape2(worldu.ptr, hullCount, hulls), 268 BSAPICPP.CreateHullShape2(worldu.ptr, hullCount, hulls),
259 BSPhysicsShapeType.SHAPE_HULL); 269 BSPhysicsShapeType.SHAPE_HULL);
260} 270}
261 271
@@ -268,6 +278,25 @@ public override BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShap
268 BSPhysicsShapeType.SHAPE_HULL); 278 BSPhysicsShapeType.SHAPE_HULL);
269} 279}
270 280
281public override BulletShape BuildConvexHullShapeFromMesh(BulletWorld world, BulletShape meshShape)
282{
283 BulletWorldUnman worldu = world as BulletWorldUnman;
284 BulletShapeUnman shapeu = meshShape as BulletShapeUnman;
285 return new BulletShapeUnman(
286 BSAPICPP.BuildConvexHullShapeFromMesh2(worldu.ptr, shapeu.ptr),
287 BSPhysicsShapeType.SHAPE_CONVEXHULL);
288}
289
290public override BulletShape CreateConvexHullShape(BulletWorld world,
291 int indicesCount, int[] indices,
292 int verticesCount, float[] vertices)
293{
294 BulletWorldUnman worldu = world as BulletWorldUnman;
295 return new BulletShapeUnman(
296 BSAPICPP.CreateConvexHullShape2(worldu.ptr, indicesCount, indices, verticesCount, vertices),
297 BSPhysicsShapeType.SHAPE_CONVEXHULL);
298}
299
271public override BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData) 300public override BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData)
272{ 301{
273 BulletWorldUnman worldu = world as BulletWorldUnman; 302 BulletWorldUnman worldu = world as BulletWorldUnman;
@@ -356,7 +385,7 @@ public override BulletShape DuplicateCollisionShape(BulletWorld world, BulletSha
356{ 385{
357 BulletWorldUnman worldu = world as BulletWorldUnman; 386 BulletWorldUnman worldu = world as BulletWorldUnman;
358 BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman; 387 BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman;
359 return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.type); 388 return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.shapeType);
360} 389}
361 390
362public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape) 391public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape)
@@ -567,6 +596,60 @@ public override bool SetBreakingImpulseThreshold(BulletConstraint constrain, flo
567 return BSAPICPP.SetBreakingImpulseThreshold2(constrainu.ptr, threshold); 596 return BSAPICPP.SetBreakingImpulseThreshold2(constrainu.ptr, threshold);
568} 597}
569 598
599public override bool HingeSetLimits(BulletConstraint constrain, float low, float high, float softness, float bias, float relaxation)
600{
601 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
602 return BSAPICPP.HingeSetLimits2(constrainu.ptr, low, high, softness, bias, relaxation);
603}
604
605public override bool SpringEnable(BulletConstraint constrain, int index, float numericTrueFalse)
606{
607 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
608 return BSAPICPP.ConstraintSpringEnable2(constrainu.ptr, index, numericTrueFalse);
609}
610
611public override bool SpringSetEquilibriumPoint(BulletConstraint constrain, int index, float equilibriumPoint)
612{
613 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
614 return BSAPICPP.ConstraintSpringSetEquilibriumPoint2(constrainu.ptr, index, equilibriumPoint);
615}
616
617public override bool SpringSetStiffness(BulletConstraint constrain, int index, float stiffnesss)
618{
619 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
620 return BSAPICPP.ConstraintSpringSetStiffness2(constrainu.ptr, index, stiffnesss);
621}
622
623public override bool SpringSetDamping(BulletConstraint constrain, int index, float damping)
624{
625 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
626 return BSAPICPP.ConstraintSpringSetDamping2(constrainu.ptr, index, damping);
627}
628
629public override bool SliderSetLimits(BulletConstraint constrain, int lowerUpper, int linAng, float val)
630{
631 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
632 return BSAPICPP.SliderSetLimits2(constrainu.ptr, lowerUpper, linAng, val);
633}
634
635public override bool SliderSet(BulletConstraint constrain, int softRestDamp, int dirLimOrtho, int linAng, float val)
636{
637 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
638 return BSAPICPP.SliderSet2(constrainu.ptr, softRestDamp, dirLimOrtho, linAng, val);
639}
640
641public override bool SliderMotorEnable(BulletConstraint constrain, int linAng, float numericTrueFalse)
642{
643 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
644 return BSAPICPP.SliderMotorEnable2(constrainu.ptr, linAng, numericTrueFalse);
645}
646
647public override bool SliderMotor(BulletConstraint constrain, int forceVel, int linAng, float val)
648{
649 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
650 return BSAPICPP.SliderMotor2(constrainu.ptr, forceVel, linAng, val);
651}
652
570public override bool CalculateTransforms(BulletConstraint constrain) 653public override bool CalculateTransforms(BulletConstraint constrain)
571{ 654{
572 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; 655 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
@@ -642,6 +725,13 @@ public override bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj)
642 return BSAPICPP.RemoveObjectFromWorld2(worldu.ptr, bodyu.ptr); 725 return BSAPICPP.RemoveObjectFromWorld2(worldu.ptr, bodyu.ptr);
643} 726}
644 727
728public override bool ClearCollisionProxyCache(BulletWorld world, BulletBody obj)
729{
730 BulletWorldUnman worldu = world as BulletWorldUnman;
731 BulletBodyUnman bodyu = obj as BulletBodyUnman;
732 return BSAPICPP.ClearCollisionProxyCache2(worldu.ptr, bodyu.ptr);
733}
734
645public override bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects) 735public override bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects)
646{ 736{
647 BulletWorldUnman worldu = world as BulletWorldUnman; 737 BulletWorldUnman worldu = world as BulletWorldUnman;
@@ -1407,6 +1497,11 @@ public static extern IntPtr CreateMeshShape2(IntPtr world,
1407 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); 1497 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
1408 1498
1409[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1499[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1500public static extern IntPtr CreateGImpactShape2(IntPtr world,
1501 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
1502 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
1503
1504[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1410public static extern IntPtr CreateHullShape2(IntPtr world, 1505public static extern IntPtr CreateHullShape2(IntPtr world,
1411 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls); 1506 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
1412 1507
@@ -1414,6 +1509,14 @@ public static extern IntPtr CreateHullShape2(IntPtr world,
1414public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape, HACDParams parms); 1509public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape, HACDParams parms);
1415 1510
1416[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1511[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1512public static extern IntPtr BuildConvexHullShapeFromMesh2(IntPtr world, IntPtr meshShape);
1513
1514[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1515public static extern IntPtr CreateConvexHullShape2(IntPtr world,
1516 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
1517 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
1518
1519[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1417public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData); 1520public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData);
1418 1521
1419[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1522[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -1476,7 +1579,7 @@ public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
1476public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin); 1579public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
1477 1580
1478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1581[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1479public static extern IntPtr CreateTerrainShape2(uint id, Vector3 size, float minHeight, float maxHeight, 1582public static extern IntPtr CreateTerrainShape2(uint id, Vector3 size, float minHeight, float maxHeight,
1480 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, 1583 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap,
1481 float scaleFactor, float collisionMargin); 1584 float scaleFactor, float collisionMargin);
1482 1585
@@ -1559,6 +1662,33 @@ public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enabl
1559public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold); 1662public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold);
1560 1663
1561[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1664[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1665public static extern bool HingeSetLimits2(IntPtr constrain, float low, float high, float softness, float bias, float relaxation);
1666
1667[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1668public static extern bool ConstraintSpringEnable2(IntPtr constrain, int index, float numericTrueFalse);
1669
1670[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1671public static extern bool ConstraintSpringSetEquilibriumPoint2(IntPtr constrain, int index, float equilibriumPoint);
1672
1673[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1674public static extern bool ConstraintSpringSetStiffness2(IntPtr constrain, int index, float stiffness);
1675
1676[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1677public static extern bool ConstraintSpringSetDamping2(IntPtr constrain, int index, float damping);
1678
1679[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1680public static extern bool SliderSetLimits2(IntPtr constrain, int lowerUpper, int linAng, float val);
1681
1682[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1683public static extern bool SliderSet2(IntPtr constrain, int softRestDamp, int dirLimOrtho, int linAng, float val);
1684
1685[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1686public static extern bool SliderMotorEnable2(IntPtr constrain, int linAng, float numericTrueFalse);
1687
1688[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1689public static extern bool SliderMotor2(IntPtr constrain, int forceVel, int linAng, float val);
1690
1691[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1562public static extern bool CalculateTransforms2(IntPtr constrain); 1692public static extern bool CalculateTransforms2(IntPtr constrain);
1563 1693
1564[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1694[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -1590,6 +1720,9 @@ public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
1590public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj); 1720public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
1591 1721
1592[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1722[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1723public static extern bool ClearCollisionProxyCache2(IntPtr world, IntPtr obj);
1724
1725[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1593public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects); 1726public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects);
1594 1727
1595[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1728[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
index f6b4359..17ebed2 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -81,11 +81,11 @@ private sealed class BulletBodyXNA : BulletBody
81private sealed class BulletShapeXNA : BulletShape 81private sealed class BulletShapeXNA : BulletShape
82{ 82{
83 public CollisionShape shape; 83 public CollisionShape shape;
84 public BulletShapeXNA(CollisionShape xx, BSPhysicsShapeType typ) 84 public BulletShapeXNA(CollisionShape xx, BSPhysicsShapeType typ)
85 : base() 85 : base()
86 { 86 {
87 shape = xx; 87 shape = xx;
88 type = typ; 88 shapeType = typ;
89 } 89 }
90 public override bool HasPhysicalShape 90 public override bool HasPhysicalShape
91 { 91 {
@@ -97,7 +97,7 @@ private sealed class BulletShapeXNA : BulletShape
97 } 97 }
98 public override BulletShape Clone() 98 public override BulletShape Clone()
99 { 99 {
100 return new BulletShapeXNA(shape, type); 100 return new BulletShapeXNA(shape, shapeType);
101 } 101 }
102 public override bool ReferenceSame(BulletShape other) 102 public override bool ReferenceSame(BulletShape other)
103 { 103 {
@@ -137,8 +137,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
137 internal int LastEntityProperty = 0; 137 internal int LastEntityProperty = 0;
138 138
139 internal EntityProperties[] UpdatedObjects; 139 internal EntityProperties[] UpdatedObjects;
140 internal Dictionary<uint, GhostObject> specialCollisionObjects; 140 internal Dictionary<uint, GhostObject> specialCollisionObjects;
141 141
142 private static int m_collisionsThisFrame; 142 private static int m_collisionsThisFrame;
143 private BSScene PhysicsScene { get; set; } 143 private BSScene PhysicsScene { get; set; }
144 144
@@ -151,7 +151,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
151 } 151 }
152 152
153 /// <summary> 153 /// <summary>
154 /// 154 ///
155 /// </summary> 155 /// </summary>
156 /// <param name="p"></param> 156 /// <param name="p"></param>
157 /// <param name="p_2"></param> 157 /// <param name="p_2"></param>
@@ -169,12 +169,25 @@ private sealed class BulletConstraintXNA : BulletConstraint
169 return true; 169 return true;
170 } 170 }
171 171
172 public override bool ClearCollisionProxyCache(BulletWorld pWorld, BulletBody pBody)
173 {
174 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
175 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
176 CollisionObject collisionObject = ((BulletBodyXNA)pBody).body;
177 if (body != null && collisionObject != null && collisionObject.GetBroadphaseHandle() != null)
178 {
179 world.RemoveCollisionObject(collisionObject);
180 world.AddCollisionObject(collisionObject);
181 }
182 return true;
183 }
184
172 public override bool AddConstraintToWorld(BulletWorld pWorld, BulletConstraint pConstraint, bool pDisableCollisionsBetweenLinkedObjects) 185 public override bool AddConstraintToWorld(BulletWorld pWorld, BulletConstraint pConstraint, bool pDisableCollisionsBetweenLinkedObjects)
173 { 186 {
174 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 187 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
175 TypedConstraint constraint = (pConstraint as BulletConstraintXNA).constrain; 188 TypedConstraint constraint = (pConstraint as BulletConstraintXNA).constrain;
176 world.AddConstraint(constraint, pDisableCollisionsBetweenLinkedObjects); 189 world.AddConstraint(constraint, pDisableCollisionsBetweenLinkedObjects);
177 190
178 return true; 191 return true;
179 192
180 } 193 }
@@ -300,7 +313,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
300 public override bool GetForceUpdateAllAabbs(BulletWorld pWorld) { 313 public override bool GetForceUpdateAllAabbs(BulletWorld pWorld) {
301 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 314 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
302 return world.GetForceUpdateAllAabbs(); 315 return world.GetForceUpdateAllAabbs();
303 316
304 } 317 }
305 public override void SetForceUpdateAllAabbs(BulletWorld pWorld, bool pForce) 318 public override void SetForceUpdateAllAabbs(BulletWorld pWorld, bool pForce)
306 { 319 {
@@ -404,7 +417,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
404 IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(vquaternion); 417 IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(vquaternion);
405 mat._origin = vposition; 418 mat._origin = vposition;
406 collisionObject.SetWorldTransform(mat); 419 collisionObject.SetWorldTransform(mat);
407 420
408 } 421 }
409 422
410 public override Vector3 GetPosition(BulletBody pCollisionObject) 423 public override Vector3 GetPosition(BulletBody pCollisionObject)
@@ -457,7 +470,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
457 { 470 {
458 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody; 471 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
459 collisionObject.Activate(pforceactivation); 472 collisionObject.Activate(pforceactivation);
460 473
461 } 474 }
462 475
463 public override Quaternion GetOrientation(BulletBody pCollisionObject) 476 public override Quaternion GetOrientation(BulletBody pCollisionObject)
@@ -486,7 +499,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
486 { 499 {
487 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody; 500 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
488 return collisionObject.GetCcdSweptSphereRadius(); 501 return collisionObject.GetCcdSweptSphereRadius();
489 502
490 } 503 }
491 504
492 public override IntPtr GetUserPointer(BulletBody pCollisionObject) 505 public override IntPtr GetUserPointer(BulletBody pCollisionObject)
@@ -559,8 +572,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
559 } 572 }
560 573
561 574
562 public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, 575 public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
563 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, 576 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot,
564 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) 577 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
565 578
566 { 579 {
@@ -604,7 +617,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
604 } 617 }
605 618
606 /// <summary> 619 /// <summary>
607 /// 620 ///
608 /// </summary> 621 /// </summary>
609 /// <param name="pWorld"></param> 622 /// <param name="pWorld"></param>
610 /// <param name="pBody1"></param> 623 /// <param name="pBody1"></param>
@@ -752,6 +765,214 @@ private sealed class BulletConstraintXNA : BulletConstraint
752 constraint.SetBreakingImpulseThreshold(threshold); 765 constraint.SetBreakingImpulseThreshold(threshold);
753 return true; 766 return true;
754 } 767 }
768 public override bool HingeSetLimits(BulletConstraint pConstraint, float low, float high, float softness, float bias, float relaxation)
769 {
770 HingeConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as HingeConstraint;
771 if (softness == HINGE_NOT_SPECIFIED)
772 constraint.SetLimit(low, high);
773 else
774 constraint.SetLimit(low, high, softness, bias, relaxation);
775 return true;
776 }
777 public override bool SpringEnable(BulletConstraint pConstraint, int index, float numericTrueFalse)
778 {
779 Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
780 constraint.EnableSpring(index, (numericTrueFalse == 0f ? false : true));
781 return true;
782 }
783
784 public override bool SpringSetEquilibriumPoint(BulletConstraint pConstraint, int index, float equilibriumPoint)
785 {
786 Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
787 if (index == SPRING_NOT_SPECIFIED)
788 {
789 constraint.SetEquilibriumPoint();
790 }
791 else
792 {
793 if (equilibriumPoint == SPRING_NOT_SPECIFIED)
794 constraint.SetEquilibriumPoint(index);
795 else
796 constraint.SetEquilibriumPoint(index, equilibriumPoint);
797 }
798 return true;
799 }
800
801 public override bool SpringSetStiffness(BulletConstraint pConstraint, int index, float stiffness)
802 {
803 Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
804 constraint.SetStiffness(index, stiffness);
805 return true;
806 }
807
808 public override bool SpringSetDamping(BulletConstraint pConstraint, int index, float damping)
809 {
810 Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
811 constraint.SetDamping(index, damping);
812 return true;
813 }
814
815 public override bool SliderSetLimits(BulletConstraint pConstraint, int lowerUpper, int linAng, float val)
816 {
817 SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
818 switch (lowerUpper)
819 {
820 case SLIDER_LOWER_LIMIT:
821 switch (linAng)
822 {
823 case SLIDER_LINEAR:
824 constraint.SetLowerLinLimit(val);
825 break;
826 case SLIDER_ANGULAR:
827 constraint.SetLowerAngLimit(val);
828 break;
829 }
830 break;
831 case SLIDER_UPPER_LIMIT:
832 switch (linAng)
833 {
834 case SLIDER_LINEAR:
835 constraint.SetUpperLinLimit(val);
836 break;
837 case SLIDER_ANGULAR:
838 constraint.SetUpperAngLimit(val);
839 break;
840 }
841 break;
842 }
843 return true;
844 }
845 public override bool SliderSet(BulletConstraint pConstraint, int softRestDamp, int dirLimOrtho, int linAng, float val)
846 {
847 SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
848 switch (softRestDamp)
849 {
850 case SLIDER_SET_SOFTNESS:
851 switch (dirLimOrtho)
852 {
853 case SLIDER_SET_DIRECTION:
854 switch (linAng)
855 {
856 case SLIDER_LINEAR: constraint.SetSoftnessDirLin(val); break;
857 case SLIDER_ANGULAR: constraint.SetSoftnessDirAng(val); break;
858 }
859 break;
860 case SLIDER_SET_LIMIT:
861 switch (linAng)
862 {
863 case SLIDER_LINEAR: constraint.SetSoftnessLimLin(val); break;
864 case SLIDER_ANGULAR: constraint.SetSoftnessLimAng(val); break;
865 }
866 break;
867 case SLIDER_SET_ORTHO:
868 switch (linAng)
869 {
870 case SLIDER_LINEAR: constraint.SetSoftnessOrthoLin(val); break;
871 case SLIDER_ANGULAR: constraint.SetSoftnessOrthoAng(val); break;
872 }
873 break;
874 }
875 break;
876 case SLIDER_SET_RESTITUTION:
877 switch (dirLimOrtho)
878 {
879 case SLIDER_SET_DIRECTION:
880 switch (linAng)
881 {
882 case SLIDER_LINEAR: constraint.SetRestitutionDirLin(val); break;
883 case SLIDER_ANGULAR: constraint.SetRestitutionDirAng(val); break;
884 }
885 break;
886 case SLIDER_SET_LIMIT:
887 switch (linAng)
888 {
889 case SLIDER_LINEAR: constraint.SetRestitutionLimLin(val); break;
890 case SLIDER_ANGULAR: constraint.SetRestitutionLimAng(val); break;
891 }
892 break;
893 case SLIDER_SET_ORTHO:
894 switch (linAng)
895 {
896 case SLIDER_LINEAR: constraint.SetRestitutionOrthoLin(val); break;
897 case SLIDER_ANGULAR: constraint.SetRestitutionOrthoAng(val); break;
898 }
899 break;
900 }
901 break;
902 case SLIDER_SET_DAMPING:
903 switch (dirLimOrtho)
904 {
905 case SLIDER_SET_DIRECTION:
906 switch (linAng)
907 {
908 case SLIDER_LINEAR: constraint.SetDampingDirLin(val); break;
909 case SLIDER_ANGULAR: constraint.SetDampingDirAng(val); break;
910 }
911 break;
912 case SLIDER_SET_LIMIT:
913 switch (linAng)
914 {
915 case SLIDER_LINEAR: constraint.SetDampingLimLin(val); break;
916 case SLIDER_ANGULAR: constraint.SetDampingLimAng(val); break;
917 }
918 break;
919 case SLIDER_SET_ORTHO:
920 switch (linAng)
921 {
922 case SLIDER_LINEAR: constraint.SetDampingOrthoLin(val); break;
923 case SLIDER_ANGULAR: constraint.SetDampingOrthoAng(val); break;
924 }
925 break;
926 }
927 break;
928 }
929 return true;
930 }
931 public override bool SliderMotorEnable(BulletConstraint pConstraint, int linAng, float numericTrueFalse)
932 {
933 SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
934 switch (linAng)
935 {
936 case SLIDER_LINEAR:
937 constraint.SetPoweredLinMotor(numericTrueFalse == 0.0 ? false : true);
938 break;
939 case SLIDER_ANGULAR:
940 constraint.SetPoweredAngMotor(numericTrueFalse == 0.0 ? false : true);
941 break;
942 }
943 return true;
944 }
945 public override bool SliderMotor(BulletConstraint pConstraint, int forceVel, int linAng, float val)
946 {
947 SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
948 switch (forceVel)
949 {
950 case SLIDER_MOTOR_VELOCITY:
951 switch (linAng)
952 {
953 case SLIDER_LINEAR:
954 constraint.SetTargetLinMotorVelocity(val);
955 break;
956 case SLIDER_ANGULAR:
957 constraint.SetTargetAngMotorVelocity(val);
958 break;
959 }
960 break;
961 case SLIDER_MAX_MOTOR_FORCE:
962 switch (linAng)
963 {
964 case SLIDER_LINEAR:
965 constraint.SetMaxLinMotorForce(val);
966 break;
967 case SLIDER_ANGULAR:
968 constraint.SetMaxAngMotorForce(val);
969 break;
970 }
971 break;
972 }
973 return true;
974 }
975
755 //BulletSimAPI.SetAngularDamping(Prim.PhysBody.ptr, angularDamping); 976 //BulletSimAPI.SetAngularDamping(Prim.PhysBody.ptr, angularDamping);
756 public override void SetAngularDamping(BulletBody pBody, float angularDamping) 977 public override void SetAngularDamping(BulletBody pBody, float angularDamping)
757 { 978 {
@@ -824,7 +1045,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
824 { 1045 {
825 RigidBody body = (pBody as BulletBodyXNA).rigidBody; 1046 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
826 float angularDamping = body.GetAngularDamping(); 1047 float angularDamping = body.GetAngularDamping();
827 body.SetDamping(lin_damping, angularDamping); 1048 body.SetDamping(lin_damping, angularDamping);
828 } 1049 }
829 1050
830 public override float GetLinearDamping(BulletBody pBody) 1051 public override float GetLinearDamping(BulletBody pBody)
@@ -907,7 +1128,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
907 RigidBody bo = co as RigidBody; 1128 RigidBody bo = co as RigidBody;
908 if (bo == null) 1129 if (bo == null)
909 { 1130 {
910 1131
911 if (world.IsInWorld(co)) 1132 if (world.IsInWorld(co))
912 { 1133 {
913 world.RemoveCollisionObject(co); 1134 world.RemoveCollisionObject(co);
@@ -915,7 +1136,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
915 } 1136 }
916 else 1137 else
917 { 1138 {
918 1139
919 if (world.IsInWorld(bo)) 1140 if (world.IsInWorld(bo))
920 { 1141 {
921 world.RemoveRigidBody(bo); 1142 world.RemoveRigidBody(bo);
@@ -947,7 +1168,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
947 1168
948 // TODO: Turn this from a reference copy to a Value Copy. 1169 // TODO: Turn this from a reference copy to a Value Copy.
949 BulletShapeXNA shape2 = new BulletShapeXNA(shape1, BSShapeTypeFromBroadPhaseNativeType(shape1.GetShapeType())); 1170 BulletShapeXNA shape2 = new BulletShapeXNA(shape1, BSShapeTypeFromBroadPhaseNativeType(shape1.GetShapeType()));
950 1171
951 return shape2; 1172 return shape2;
952 } 1173 }
953 1174
@@ -957,7 +1178,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
957 return false; 1178 return false;
958 } 1179 }
959 //(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation); 1180 //(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation);
960 1181
961 public override BulletBody CreateBodyFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) 1182 public override BulletBody CreateBodyFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
962 { 1183 {
963 CollisionWorld world = (pWorld as BulletWorldXNA).world; 1184 CollisionWorld world = (pWorld as BulletWorldXNA).world;
@@ -993,11 +1214,11 @@ private sealed class BulletConstraintXNA : BulletConstraint
993 m_startWorldTransform = IndexedMatrix.Identity; 1214 m_startWorldTransform = IndexedMatrix.Identity;
994 */ 1215 */
995 body.SetUserPointer(pLocalID); 1216 body.SetUserPointer(pLocalID);
996 1217
997 return new BulletBodyXNA(pLocalID, body); 1218 return new BulletBodyXNA(pLocalID, body);
998 } 1219 }
999 1220
1000 1221
1001 public override BulletBody CreateBodyWithDefaultMotionState( BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) 1222 public override BulletBody CreateBodyWithDefaultMotionState( BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
1002 { 1223 {
1003 1224
@@ -1025,7 +1246,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1025 public override Vector3 GetAnisotripicFriction(BulletConstraint pconstrain) 1246 public override Vector3 GetAnisotripicFriction(BulletConstraint pconstrain)
1026 { 1247 {
1027 1248
1028 /* TODO */ 1249 /* TODO */
1029 return Vector3.Zero; 1250 return Vector3.Zero;
1030 } 1251 }
1031 public override Vector3 SetAnisotripicFriction(BulletConstraint pconstrain, Vector3 frict) { /* TODO */ return Vector3.Zero; } 1252 public override Vector3 SetAnisotripicFriction(BulletConstraint pconstrain, Vector3 frict) { /* TODO */ return Vector3.Zero; }
@@ -1035,7 +1256,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1035 { 1256 {
1036 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody; 1257 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
1037 return collisionObject.IsStaticObject(); 1258 return collisionObject.IsStaticObject();
1038 1259
1039 } 1260 }
1040 public override bool IsKinematicObject(BulletBody pCollisionObject) 1261 public override bool IsKinematicObject(BulletBody pCollisionObject)
1041 { 1262 {
@@ -1098,10 +1319,10 @@ private sealed class BulletConstraintXNA : BulletConstraint
1098 return new BulletWorldXNA(1, PhysicsScene, BSAPIXNA.Initialize2(worldExtent, configparms, maxCollisions, ref collisionArray, maxUpdates, ref updateArray, null)); 1319 return new BulletWorldXNA(1, PhysicsScene, BSAPIXNA.Initialize2(worldExtent, configparms, maxCollisions, ref collisionArray, maxUpdates, ref updateArray, null));
1099 } 1320 }
1100 1321
1101 private static DiscreteDynamicsWorld Initialize2(Vector3 worldExtent, 1322 private static DiscreteDynamicsWorld Initialize2(Vector3 worldExtent,
1102 ConfigurationParameters[] o, 1323 ConfigurationParameters[] o,
1103 int mMaxCollisionsPerFrame, ref CollisionDesc[] collisionArray, 1324 int mMaxCollisionsPerFrame, ref CollisionDesc[] collisionArray,
1104 int mMaxUpdatesPerFrame, ref EntityProperties[] updateArray, 1325 int mMaxUpdatesPerFrame, ref EntityProperties[] updateArray,
1105 object mDebugLogCallbackHandle) 1326 object mDebugLogCallbackHandle)
1106 { 1327 {
1107 CollisionWorld.WorldData.ParamData p = new CollisionWorld.WorldData.ParamData(); 1328 CollisionWorld.WorldData.ParamData p = new CollisionWorld.WorldData.ParamData();
@@ -1138,9 +1359,9 @@ private sealed class BulletConstraintXNA : BulletConstraint
1138 p.avatarCapsuleDepth = BSParam.AvatarCapsuleDepth; 1359 p.avatarCapsuleDepth = BSParam.AvatarCapsuleDepth;
1139 p.avatarCapsuleHeight = BSParam.AvatarCapsuleHeight; 1360 p.avatarCapsuleHeight = BSParam.AvatarCapsuleHeight;
1140 p.avatarContactProcessingThreshold = BSParam.AvatarContactProcessingThreshold; 1361 p.avatarContactProcessingThreshold = BSParam.AvatarContactProcessingThreshold;
1141 1362
1142 p.vehicleAngularDamping = BSParam.VehicleAngularDamping; 1363 p.vehicleAngularDamping = BSParam.VehicleAngularDamping;
1143 1364
1144 p.maxPersistantManifoldPoolSize = o[0].maxPersistantManifoldPoolSize; 1365 p.maxPersistantManifoldPoolSize = o[0].maxPersistantManifoldPoolSize;
1145 p.maxCollisionAlgorithmPoolSize = o[0].maxCollisionAlgorithmPoolSize; 1366 p.maxCollisionAlgorithmPoolSize = o[0].maxCollisionAlgorithmPoolSize;
1146 p.shouldDisableContactPoolDynamicAllocation = o[0].shouldDisableContactPoolDynamicAllocation; 1367 p.shouldDisableContactPoolDynamicAllocation = o[0].shouldDisableContactPoolDynamicAllocation;
@@ -1160,7 +1381,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1160 p.linkConstraintSolverIterations = BSParam.LinkConstraintSolverIterations; 1381 p.linkConstraintSolverIterations = BSParam.LinkConstraintSolverIterations;
1161 p.physicsLoggingFrames = o[0].physicsLoggingFrames; 1382 p.physicsLoggingFrames = o[0].physicsLoggingFrames;
1162 DefaultCollisionConstructionInfo ccci = new DefaultCollisionConstructionInfo(); 1383 DefaultCollisionConstructionInfo ccci = new DefaultCollisionConstructionInfo();
1163 1384
1164 DefaultCollisionConfiguration cci = new DefaultCollisionConfiguration(); 1385 DefaultCollisionConfiguration cci = new DefaultCollisionConfiguration();
1165 CollisionDispatcher m_dispatcher = new CollisionDispatcher(cci); 1386 CollisionDispatcher m_dispatcher = new CollisionDispatcher(cci);
1166 1387
@@ -1221,6 +1442,50 @@ private sealed class BulletConstraintXNA : BulletConstraint
1221 //BSParam.TerrainImplementation = 0; 1442 //BSParam.TerrainImplementation = 0;
1222 world.SetGravity(new IndexedVector3(0,0,p.gravity)); 1443 world.SetGravity(new IndexedVector3(0,0,p.gravity));
1223 1444
1445 // Turn off Pooling since globals and pooling are bad for threading.
1446 BulletGlobals.VoronoiSimplexSolverPool.SetPoolingEnabled(false);
1447 BulletGlobals.SubSimplexConvexCastPool.SetPoolingEnabled(false);
1448 BulletGlobals.ManifoldPointPool.SetPoolingEnabled(false);
1449 BulletGlobals.CastResultPool.SetPoolingEnabled(false);
1450 BulletGlobals.SphereShapePool.SetPoolingEnabled(false);
1451 BulletGlobals.DbvtNodePool.SetPoolingEnabled(false);
1452 BulletGlobals.SingleRayCallbackPool.SetPoolingEnabled(false);
1453 BulletGlobals.SubSimplexClosestResultPool.SetPoolingEnabled(false);
1454 BulletGlobals.GjkPairDetectorPool.SetPoolingEnabled(false);
1455 BulletGlobals.DbvtTreeColliderPool.SetPoolingEnabled(false);
1456 BulletGlobals.SingleSweepCallbackPool.SetPoolingEnabled(false);
1457 BulletGlobals.BroadphaseRayTesterPool.SetPoolingEnabled(false);
1458 BulletGlobals.ClosestNotMeConvexResultCallbackPool.SetPoolingEnabled(false);
1459 BulletGlobals.GjkEpaPenetrationDepthSolverPool.SetPoolingEnabled(false);
1460 BulletGlobals.ContinuousConvexCollisionPool.SetPoolingEnabled(false);
1461 BulletGlobals.DbvtStackDataBlockPool.SetPoolingEnabled(false);
1462
1463 BulletGlobals.BoxBoxCollisionAlgorithmPool.SetPoolingEnabled(false);
1464 BulletGlobals.CompoundCollisionAlgorithmPool.SetPoolingEnabled(false);
1465 BulletGlobals.ConvexConcaveCollisionAlgorithmPool.SetPoolingEnabled(false);
1466 BulletGlobals.ConvexConvexAlgorithmPool.SetPoolingEnabled(false);
1467 BulletGlobals.ConvexPlaneAlgorithmPool.SetPoolingEnabled(false);
1468 BulletGlobals.SphereBoxCollisionAlgorithmPool.SetPoolingEnabled(false);
1469 BulletGlobals.SphereSphereCollisionAlgorithmPool.SetPoolingEnabled(false);
1470 BulletGlobals.SphereTriangleCollisionAlgorithmPool.SetPoolingEnabled(false);
1471 BulletGlobals.GImpactCollisionAlgorithmPool.SetPoolingEnabled(false);
1472 BulletGlobals.GjkEpaSolver2MinkowskiDiffPool.SetPoolingEnabled(false);
1473 BulletGlobals.PersistentManifoldPool.SetPoolingEnabled(false);
1474 BulletGlobals.ManifoldResultPool.SetPoolingEnabled(false);
1475 BulletGlobals.GJKPool.SetPoolingEnabled(false);
1476 BulletGlobals.GIM_ShapeRetrieverPool.SetPoolingEnabled(false);
1477 BulletGlobals.TriangleShapePool.SetPoolingEnabled(false);
1478 BulletGlobals.SphereTriangleDetectorPool.SetPoolingEnabled(false);
1479 BulletGlobals.CompoundLeafCallbackPool.SetPoolingEnabled(false);
1480 BulletGlobals.GjkConvexCastPool.SetPoolingEnabled(false);
1481 BulletGlobals.LocalTriangleSphereCastCallbackPool.SetPoolingEnabled(false);
1482 BulletGlobals.BridgeTriangleRaycastCallbackPool.SetPoolingEnabled(false);
1483 BulletGlobals.BridgeTriangleConcaveRaycastCallbackPool.SetPoolingEnabled(false);
1484 BulletGlobals.BridgeTriangleConvexcastCallbackPool.SetPoolingEnabled(false);
1485 BulletGlobals.MyNodeOverlapCallbackPool.SetPoolingEnabled(false);
1486 BulletGlobals.ClosestRayResultCallbackPool.SetPoolingEnabled(false);
1487 BulletGlobals.DebugDrawcallbackPool.SetPoolingEnabled(false);
1488
1224 return world; 1489 return world;
1225 } 1490 }
1226 //m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL 1491 //m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL
@@ -1263,7 +1528,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1263 } 1528 }
1264 } 1529 }
1265 return ret; 1530 return ret;
1266 1531
1267 } 1532 }
1268 1533
1269 public override float GetAngularMotionDisc(BulletShape pShape) 1534 public override float GetAngularMotionDisc(BulletShape pShape)
@@ -1353,10 +1618,10 @@ private sealed class BulletConstraintXNA : BulletConstraint
1353 CollisionShape shape = (pShape as BulletShapeXNA).shape; 1618 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1354 gObj.SetCollisionShape(shape); 1619 gObj.SetCollisionShape(shape);
1355 gObj.SetUserPointer(pLocalID); 1620 gObj.SetUserPointer(pLocalID);
1356 1621
1357 if (specialCollisionObjects.ContainsKey(pLocalID)) 1622 if (specialCollisionObjects.ContainsKey(pLocalID))
1358 specialCollisionObjects[pLocalID] = gObj; 1623 specialCollisionObjects[pLocalID] = gObj;
1359 else 1624 else
1360 specialCollisionObjects.Add(pLocalID, gObj); 1625 specialCollisionObjects.Add(pLocalID, gObj);
1361 1626
1362 // TODO: Add to Special CollisionObjects! 1627 // TODO: Add to Special CollisionObjects!
@@ -1447,8 +1712,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
1447 return new BulletShapeXNA(ret, BSShapeTypeFromBroadPhaseNativeType(ret.GetShapeType())); 1712 return new BulletShapeXNA(ret, BSShapeTypeFromBroadPhaseNativeType(ret.GetShapeType()));
1448 } 1713 }
1449 1714
1450 public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) { 1715 public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) {
1451 1716
1452 if (cShape == null) 1717 if (cShape == null)
1453 return null; 1718 return null;
1454 CompoundShape compoundShape = (cShape as BulletShapeXNA).shape as CompoundShape; 1719 CompoundShape compoundShape = (cShape as BulletShapeXNA).shape as CompoundShape;
@@ -1456,7 +1721,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1456 BulletShape retShape = new BulletShapeXNA(shape, BSShapeTypeFromBroadPhaseNativeType(shape.GetShapeType())); 1721 BulletShape retShape = new BulletShapeXNA(shape, BSShapeTypeFromBroadPhaseNativeType(shape.GetShapeType()));
1457 1722
1458 1723
1459 return retShape; 1724 return retShape;
1460 } 1725 }
1461 1726
1462 public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin) 1727 public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin)
@@ -1475,7 +1740,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1475 ret = BSPhysicsShapeType.SHAPE_UNKNOWN; 1740 ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
1476 break; 1741 break;
1477 case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE: 1742 case BroadphaseNativeTypes.CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE:
1478 ret = BSPhysicsShapeType.SHAPE_MESH; 1743 ret = BSPhysicsShapeType.SHAPE_CONVEXHULL;
1479 break; 1744 break;
1480 case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE: 1745 case BroadphaseNativeTypes.CONVEX_HULL_SHAPE_PROXYTYPE:
1481 ret = BSPhysicsShapeType.SHAPE_HULL; 1746 ret = BSPhysicsShapeType.SHAPE_HULL;
@@ -1503,7 +1768,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1503 ret = BSPhysicsShapeType.SHAPE_CONE; 1768 ret = BSPhysicsShapeType.SHAPE_CONE;
1504 break; 1769 break;
1505 case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE: 1770 case BroadphaseNativeTypes.CONVEX_SHAPE_PROXYTYPE:
1506 ret = BSPhysicsShapeType.SHAPE_UNKNOWN; 1771 ret = BSPhysicsShapeType.SHAPE_CONVEXHULL;
1507 break; 1772 break;
1508 case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE: 1773 case BroadphaseNativeTypes.CYLINDER_SHAPE_PROXYTYPE:
1509 ret = BSPhysicsShapeType.SHAPE_CYLINDER; 1774 ret = BSPhysicsShapeType.SHAPE_CYLINDER;
@@ -1547,7 +1812,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1547 break; 1812 break;
1548 ///Used for GIMPACT Trimesh integration 1813 ///Used for GIMPACT Trimesh integration
1549 case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE: 1814 case BroadphaseNativeTypes.GIMPACT_SHAPE_PROXYTYPE:
1550 ret = BSPhysicsShapeType.SHAPE_MESH; 1815 ret = BSPhysicsShapeType.SHAPE_GIMPACT;
1551 break; 1816 break;
1552 ///Multimaterial mesh 1817 ///Multimaterial mesh
1553 case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE: 1818 case BroadphaseNativeTypes.MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE:
@@ -1598,8 +1863,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
1598 return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE); 1863 return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE);
1599 } 1864 }
1600 1865
1601 public override BulletConstraint Create6DofSpringConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, 1866 public override BulletConstraint Create6DofSpringConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
1602 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, 1867 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot,
1603 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) 1868 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
1604 1869
1605 { 1870 {
@@ -1745,7 +2010,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1745 { 2010 {
1746 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 2011 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1747 CompoundShape compoundshape = new CompoundShape(false); 2012 CompoundShape compoundshape = new CompoundShape(false);
1748 2013
1749 compoundshape.SetMargin(world.WorldSettings.Params.collisionMargin); 2014 compoundshape.SetMargin(world.WorldSettings.Params.collisionMargin);
1750 int ii = 1; 2015 int ii = 1;
1751 2016
@@ -1761,7 +2026,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1761 int ender = ((ii + 4) + (vertexCount*3)); 2026 int ender = ((ii + 4) + (vertexCount*3));
1762 for (int iii = ii + 4; iii < ender; iii+=3) 2027 for (int iii = ii + 4; iii < ender; iii+=3)
1763 { 2028 {
1764 2029
1765 virts.Add(new IndexedVector3(pConvHulls[iii], pConvHulls[iii + 1], pConvHulls[iii +2])); 2030 virts.Add(new IndexedVector3(pConvHulls[iii], pConvHulls[iii + 1], pConvHulls[iii +2]));
1766 } 2031 }
1767 ConvexHullShape convexShape = new ConvexHullShape(virts, vertexCount); 2032 ConvexHullShape convexShape = new ConvexHullShape(virts, vertexCount);
@@ -1769,7 +2034,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1769 compoundshape.AddChildShape(ref childTrans, convexShape); 2034 compoundshape.AddChildShape(ref childTrans, convexShape);
1770 ii += (vertexCount*3 + 4); 2035 ii += (vertexCount*3 + 4);
1771 } 2036 }
1772 2037
1773 return new BulletShapeXNA(compoundshape, BSPhysicsShapeType.SHAPE_HULL); 2038 return new BulletShapeXNA(compoundshape, BSPhysicsShapeType.SHAPE_HULL);
1774 } 2039 }
1775 2040
@@ -1778,16 +2043,26 @@ private sealed class BulletConstraintXNA : BulletConstraint
1778 /* TODO */ return null; 2043 /* TODO */ return null;
1779 } 2044 }
1780 2045
2046 public override BulletShape BuildConvexHullShapeFromMesh(BulletWorld world, BulletShape meshShape)
2047 {
2048 /* TODO */ return null;
2049 }
2050
2051 public override BulletShape CreateConvexHullShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
2052 {
2053 /* TODO */ return null;
2054 }
2055
1781 public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats) 2056 public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
1782 { 2057 {
1783 //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount); 2058 //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount);
1784 2059
1785 for (int iter = 0; iter < pVerticesCount; iter++) 2060 for (int iter = 0; iter < pVerticesCount; iter++)
1786 { 2061 {
1787 if (verticesAsFloats[iter] > 0 && verticesAsFloats[iter] < 0.0001) verticesAsFloats[iter] = 0; 2062 if (verticesAsFloats[iter] > 0 && verticesAsFloats[iter] < 0.0001) verticesAsFloats[iter] = 0;
1788 if (verticesAsFloats[iter] < 0 && verticesAsFloats[iter] > -0.0001) verticesAsFloats[iter] = 0; 2063 if (verticesAsFloats[iter] < 0 && verticesAsFloats[iter] > -0.0001) verticesAsFloats[iter] = 0;
1789 } 2064 }
1790 2065
1791 ObjectArray<int> indicesarr = new ObjectArray<int>(indices); 2066 ObjectArray<int> indicesarr = new ObjectArray<int>(indices);
1792 ObjectArray<float> vertices = new ObjectArray<float>(verticesAsFloats); 2067 ObjectArray<float> vertices = new ObjectArray<float>(verticesAsFloats);
1793 DumpRaw(indicesarr,vertices,pIndicesCount,pVerticesCount); 2068 DumpRaw(indicesarr,vertices,pIndicesCount,pVerticesCount);
@@ -1801,7 +2076,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1801 mesh.m_vertexStride = 3; 2076 mesh.m_vertexStride = 3;
1802 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; 2077 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1803 mesh.m_triangleIndexStride = 3; 2078 mesh.m_triangleIndexStride = 3;
1804 2079
1805 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); 2080 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1806 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); 2081 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1807 BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(tribuilder, true,true); 2082 BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(tribuilder, true,true);
@@ -1810,9 +2085,14 @@ private sealed class BulletConstraintXNA : BulletConstraint
1810 return new BulletShapeXNA(meshShape, BSPhysicsShapeType.SHAPE_MESH); 2085 return new BulletShapeXNA(meshShape, BSPhysicsShapeType.SHAPE_MESH);
1811 2086
1812 } 2087 }
2088 public override BulletShape CreateGImpactShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
2089 {
2090 // TODO:
2091 return null;
2092 }
1813 public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount ) 2093 public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount )
1814 { 2094 {
1815 2095
1816 String fileName = "objTest3.raw"; 2096 String fileName = "objTest3.raw";
1817 String completePath = System.IO.Path.Combine(Util.configDir(), fileName); 2097 String completePath = System.IO.Path.Combine(Util.configDir(), fileName);
1818 StreamWriter sw = new StreamWriter(completePath); 2098 StreamWriter sw = new StreamWriter(completePath);
@@ -1838,7 +2118,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1838 string s = vertices[indices[i * 3]].ToString("0.0000"); 2118 string s = vertices[indices[i * 3]].ToString("0.0000");
1839 s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000"); 2119 s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000");
1840 s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000"); 2120 s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000");
1841 2121
1842 sw.Write(s + "\n"); 2122 sw.Write(s + "\n");
1843 } 2123 }
1844 2124
@@ -1860,7 +2140,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1860 mesh.m_vertexStride = 3; 2140 mesh.m_vertexStride = 3;
1861 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; 2141 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1862 mesh.m_triangleIndexStride = 3; 2142 mesh.m_triangleIndexStride = 3;
1863 2143
1864 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); 2144 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1865 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); 2145 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1866 2146
@@ -1891,7 +2171,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1891 sw.Close(); 2171 sw.Close();
1892 } 2172 }
1893 2173
1894 public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap, 2174 public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
1895 float scaleFactor, float collisionMargin) 2175 float scaleFactor, float collisionMargin)
1896 { 2176 {
1897 const int upAxis = 2; 2177 const int upAxis = 2;
@@ -1899,7 +2179,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1899 heightMap, scaleFactor, 2179 heightMap, scaleFactor,
1900 minHeight, maxHeight, upAxis, 2180 minHeight, maxHeight, upAxis,
1901 false); 2181 false);
1902 terrainShape.SetMargin(collisionMargin + 0.5f); 2182 terrainShape.SetMargin(collisionMargin);
1903 terrainShape.SetUseDiamondSubdivision(true); 2183 terrainShape.SetUseDiamondSubdivision(true);
1904 terrainShape.SetUserPointer(id); 2184 terrainShape.SetUserPointer(id);
1905 return new BulletShapeXNA(terrainShape, BSPhysicsShapeType.SHAPE_TERRAIN); 2185 return new BulletShapeXNA(terrainShape, BSPhysicsShapeType.SHAPE_TERRAIN);
@@ -1933,14 +2213,14 @@ private sealed class BulletConstraintXNA : BulletConstraint
1933 /* TODO */ 2213 /* TODO */
1934 updatedEntityCount = 0; 2214 updatedEntityCount = 0;
1935 collidersCount = 0; 2215 collidersCount = 0;
1936 2216
1937 2217
1938 int ret = PhysicsStep2(world,timeStep,maxSubSteps,fixedTimeStep,out updatedEntityCount,out world.physicsScene.m_updateArray, out collidersCount, out world.physicsScene.m_collisionArray); 2218 int ret = PhysicsStep2(world,timeStep,maxSubSteps,fixedTimeStep,out updatedEntityCount,out world.physicsScene.m_updateArray, out collidersCount, out world.physicsScene.m_collisionArray);
1939 2219
1940 return ret; 2220 return ret;
1941 } 2221 }
1942 2222
1943 private int PhysicsStep2(BulletWorld pWorld, float timeStep, int m_maxSubSteps, float m_fixedTimeStep, 2223 private int PhysicsStep2(BulletWorld pWorld, float timeStep, int m_maxSubSteps, float m_fixedTimeStep,
1944 out int updatedEntityCount, out EntityProperties[] updatedEntities, 2224 out int updatedEntityCount, out EntityProperties[] updatedEntities,
1945 out int collidersCount, out CollisionDesc[] colliders) 2225 out int collidersCount, out CollisionDesc[] colliders)
1946 { 2226 {
@@ -1949,24 +2229,24 @@ private sealed class BulletConstraintXNA : BulletConstraint
1949 return epic; 2229 return epic;
1950 } 2230 }
1951 2231
1952 private int PhysicsStepint(BulletWorld pWorld,float timeStep, int m_maxSubSteps, float m_fixedTimeStep, out int updatedEntityCount, 2232 private int PhysicsStepint(BulletWorld pWorld,float timeStep, int m_maxSubSteps, float m_fixedTimeStep, out int updatedEntityCount,
1953 out EntityProperties[] updatedEntities, out int collidersCount, out CollisionDesc[] colliders, int maxCollisions, int maxUpdates) 2233 out EntityProperties[] updatedEntities, out int collidersCount, out CollisionDesc[] colliders, int maxCollisions, int maxUpdates)
1954 { 2234 {
1955 int numSimSteps = 0; 2235 int numSimSteps = 0;
1956 Array.Clear(UpdatedObjects, 0, UpdatedObjects.Length); 2236 Array.Clear(UpdatedObjects, 0, UpdatedObjects.Length);
1957 Array.Clear(UpdatedCollisions, 0, UpdatedCollisions.Length); 2237 Array.Clear(UpdatedCollisions, 0, UpdatedCollisions.Length);
1958 LastEntityProperty=0; 2238 LastEntityProperty=0;
1959 2239
1960 2240
1961 2241
1962 2242
1963 2243
1964 2244
1965 LastCollisionDesc=0; 2245 LastCollisionDesc=0;
1966 2246
1967 updatedEntityCount = 0; 2247 updatedEntityCount = 0;
1968 collidersCount = 0; 2248 collidersCount = 0;
1969 2249
1970 2250
1971 if (pWorld is BulletWorldXNA) 2251 if (pWorld is BulletWorldXNA)
1972 { 2252 {
@@ -2023,7 +2303,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2023 2303
2024 collidersCount = LastCollisionDesc; 2304 collidersCount = LastCollisionDesc;
2025 colliders = UpdatedCollisions; 2305 colliders = UpdatedCollisions;
2026 2306
2027 2307
2028 } 2308 }
2029 else 2309 else
@@ -2031,15 +2311,15 @@ private sealed class BulletConstraintXNA : BulletConstraint
2031 //if (updatedEntities is null) 2311 //if (updatedEntities is null)
2032 //updatedEntities = new List<BulletXNA.EntityProperties>(); 2312 //updatedEntities = new List<BulletXNA.EntityProperties>();
2033 //updatedEntityCount = 0; 2313 //updatedEntityCount = 0;
2034 2314
2035 2315
2036 //collidersCount = 0; 2316 //collidersCount = 0;
2037 2317
2038 updatedEntities = new EntityProperties[0]; 2318 updatedEntities = new EntityProperties[0];
2039 2319
2040 2320
2041 colliders = new CollisionDesc[0]; 2321 colliders = new CollisionDesc[0];
2042 2322
2043 } 2323 }
2044 return numSimSteps; 2324 return numSimSteps;
2045 } 2325 }
@@ -2047,7 +2327,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2047 { 2327 {
2048 IOverlappingPairCache cache = obj.GetOverlappingPairCache(); 2328 IOverlappingPairCache cache = obj.GetOverlappingPairCache();
2049 ObjectArray<BroadphasePair> pairs = cache.GetOverlappingPairArray(); 2329 ObjectArray<BroadphasePair> pairs = cache.GetOverlappingPairArray();
2050 2330
2051 DiscreteDynamicsWorld world = (PhysicsScene.World as BulletWorldXNA).world; 2331 DiscreteDynamicsWorld world = (PhysicsScene.World as BulletWorldXNA).world;
2052 PersistentManifoldArray manifoldArray = new PersistentManifoldArray(); 2332 PersistentManifoldArray manifoldArray = new PersistentManifoldArray();
2053 BroadphasePair collisionPair; 2333 BroadphasePair collisionPair;
@@ -2059,7 +2339,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2059 ManifoldPoint pt; 2339 ManifoldPoint pt;
2060 2340
2061 int numPairs = pairs.Count; 2341 int numPairs = pairs.Count;
2062 2342
2063 for (int i = 0; i < numPairs; i++) 2343 for (int i = 0; i < numPairs; i++)
2064 { 2344 {
2065 manifoldArray.Clear(); 2345 manifoldArray.Clear();
@@ -2068,7 +2348,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2068 collisionPair = world.GetPairCache().FindPair(pairs[i].m_pProxy0, pairs[i].m_pProxy1); 2348 collisionPair = world.GetPairCache().FindPair(pairs[i].m_pProxy0, pairs[i].m_pProxy1);
2069 if (collisionPair == null) 2349 if (collisionPair == null)
2070 continue; 2350 continue;
2071 2351
2072 collisionPair.m_algorithm.GetAllContactManifolds(manifoldArray); 2352 collisionPair.m_algorithm.GetAllContactManifolds(manifoldArray);
2073 for (int j = 0; j < manifoldArray.Count; j++) 2353 for (int j = 0; j < manifoldArray.Count; j++)
2074 { 2354 {
@@ -2091,7 +2371,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2091 } 2371 }
2092 private static void RecordCollision(BSAPIXNA world, CollisionObject objA, CollisionObject objB, IndexedVector3 contact, IndexedVector3 norm, float penetration) 2372 private static void RecordCollision(BSAPIXNA world, CollisionObject objA, CollisionObject objB, IndexedVector3 contact, IndexedVector3 norm, float penetration)
2093 { 2373 {
2094 2374
2095 IndexedVector3 contactNormal = norm; 2375 IndexedVector3 contactNormal = norm;
2096 if ((objA.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0 && 2376 if ((objA.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0 &&
2097 (objB.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0) 2377 (objB.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0)
@@ -2161,11 +2441,11 @@ private sealed class BulletConstraintXNA : BulletConstraint
2161 if (NotMe is BulletBodyXNA && NotMe.HasPhysicalBody) 2441 if (NotMe is BulletBodyXNA && NotMe.HasPhysicalBody)
2162 { 2442 {
2163 CollisionObject AvoidBody = (NotMe as BulletBodyXNA).body; 2443 CollisionObject AvoidBody = (NotMe as BulletBodyXNA).body;
2164 2444
2165 IndexedVector3 rOrigin = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z); 2445 IndexedVector3 rOrigin = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z);
2166 IndexedVector3 rEnd = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z - pRayHeight); 2446 IndexedVector3 rEnd = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z - pRayHeight);
2167 using ( 2447 using (
2168 ClosestNotMeRayResultCallback rayCallback = 2448 ClosestNotMeRayResultCallback rayCallback =
2169 new ClosestNotMeRayResultCallback(rOrigin, rEnd, AvoidBody) 2449 new ClosestNotMeRayResultCallback(rOrigin, rEnd, AvoidBody)
2170 ) 2450 )
2171 { 2451 {
@@ -2181,9 +2461,9 @@ private sealed class BulletConstraintXNA : BulletConstraint
2181 return false; 2461 return false;
2182 } 2462 }
2183} 2463}
2184
2185 2464
2186 2465
2466
2187 2467
2188 public class SimMotionState : DefaultMotionState 2468 public class SimMotionState : DefaultMotionState
2189 { 2469 {
@@ -2276,12 +2556,12 @@ private sealed class BulletConstraintXNA : BulletConstraint
2276 m_lastProperties = m_properties; 2556 m_lastProperties = m_properties;
2277 if (m_world.LastEntityProperty < m_world.UpdatedObjects.Length) 2557 if (m_world.LastEntityProperty < m_world.UpdatedObjects.Length)
2278 m_world.UpdatedObjects[m_world.LastEntityProperty++]=(m_properties); 2558 m_world.UpdatedObjects[m_world.LastEntityProperty++]=(m_properties);
2279 2559
2280 //(*m_updatesThisFrame)[m_properties.ID] = &m_properties; 2560 //(*m_updatesThisFrame)[m_properties.ID] = &m_properties;
2281 } 2561 }
2282 2562
2283 2563
2284 2564
2285 2565
2286 } 2566 }
2287 public override void SetRigidBody(RigidBody body) 2567 public override void SetRigidBody(RigidBody body)
@@ -2304,7 +2584,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2304 (((v1.Z - nEpsilon) < v2.Z) && (v2.Z < (v1.Z + nEpsilon))) && 2584 (((v1.Z - nEpsilon) < v2.Z) && (v2.Z < (v1.Z + nEpsilon))) &&
2305 (((v1.W - nEpsilon) < v2.W) && (v2.W < (v1.W + nEpsilon))); 2585 (((v1.W - nEpsilon) < v2.W) && (v2.W < (v1.W + nEpsilon)));
2306 } 2586 }
2307 2587
2308 } 2588 }
2309} 2589}
2310 2590
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
new file mode 100755
index 0000000..1bcf879
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
@@ -0,0 +1,411 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorAvatarMove : BSActor
40{
41 BSVMotor m_velocityMotor;
42
43 // Set to true if we think we're going up stairs.
44 // This state is remembered because collisions will turn on and off as we go up stairs.
45 int m_walkingUpStairs;
46 // The amount the step up is applying. Used to smooth stair walking.
47 float m_lastStepUp;
48
49 // Jumping happens over several frames. If use applies up force while colliding, start the
50 // jump and allow the jump to continue for this number of frames.
51 int m_jumpFrames = 0;
52 float m_jumpVelocity = 0f;
53
54 public BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
55 : base(physicsScene, pObj, actorName)
56 {
57 m_velocityMotor = null;
58 m_walkingUpStairs = 0;
59 m_physicsScene.DetailLog("{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID);
60 }
61
62 // BSActor.isActive
63 public override bool isActive
64 {
65 get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
66 }
67
68 // Release any connections and resources used by the actor.
69 // BSActor.Dispose()
70 public override void Dispose()
71 {
72 base.SetEnabled(false);
73 // Now that turned off, remove any state we have in the scene.
74 Refresh();
75 }
76
77 // Called when physical parameters (properties set in Bullet) need to be re-applied.
78 // Called at taint-time.
79 // BSActor.Refresh()
80 public override void Refresh()
81 {
82 m_physicsScene.DetailLog("{0},BSActorAvatarMove,refresh", m_controllingPrim.LocalID);
83
84 // If the object is physically active, add the hoverer prestep action
85 if (isActive)
86 {
87 ActivateAvatarMove();
88 }
89 else
90 {
91 DeactivateAvatarMove();
92 }
93 }
94
95 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
96 // Register a prestep action to restore physical requirements before the next simulation step.
97 // Called at taint-time.
98 // BSActor.RemoveDependencies()
99 public override void RemoveDependencies()
100 {
101 // Nothing to do for the hoverer since it is all software at pre-step action time.
102 }
103
104 // Usually called when target velocity changes to set the current velocity and the target
105 // into the movement motor.
106 public void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime)
107 {
108 m_physicsScene.TaintedObject(inTaintTime, m_controllingPrim.LocalID, "BSActorAvatarMove.setVelocityAndTarget", delegate()
109 {
110 if (m_velocityMotor != null)
111 {
112 m_velocityMotor.Reset();
113 m_velocityMotor.SetTarget(targ);
114 m_velocityMotor.SetCurrent(vel);
115 m_velocityMotor.Enabled = true;
116 }
117 });
118 }
119
120 // If a hover motor has not been created, create one and start the hovering.
121 private void ActivateAvatarMove()
122 {
123 if (m_velocityMotor == null)
124 {
125 // Infinite decay and timescale values so motor only changes current to target values.
126 m_velocityMotor = new BSVMotor("BSCharacter.Velocity",
127 0.2f, // time scale
128 BSMotor.Infinite, // decay time scale
129 1f // efficiency
130 );
131 m_velocityMotor.ErrorZeroThreshold = BSParam.AvatarStopZeroThreshold;
132 // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
133 SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */);
134
135 m_physicsScene.BeforeStep += Mover;
136 m_controllingPrim.OnPreUpdateProperty += Process_OnPreUpdateProperty;
137
138 m_walkingUpStairs = 0;
139 }
140 }
141
142 private void DeactivateAvatarMove()
143 {
144 if (m_velocityMotor != null)
145 {
146 m_controllingPrim.OnPreUpdateProperty -= Process_OnPreUpdateProperty;
147 m_physicsScene.BeforeStep -= Mover;
148 m_velocityMotor = null;
149 }
150 }
151
152 // Called just before the simulation step. Update the vertical position for hoverness.
153 private void Mover(float timeStep)
154 {
155 // Don't do movement while the object is selected.
156 if (!isActive)
157 return;
158
159 // TODO: Decide if the step parameters should be changed depending on the avatar's
160 // state (flying, colliding, ...). There is code in ODE to do this.
161
162 // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity
163 // specified for the avatar is the one that should be used. For falling, if the avatar
164 // is not flying and is not colliding then it is presumed to be falling and the Z
165 // component is not fooled with (thus allowing gravity to do its thing).
166 // When the avatar is standing, though, the user has specified a velocity of zero and
167 // the avatar should be standing. But if the avatar is pushed by something in the world
168 // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to
169 // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity
170 // errors can creap in and the avatar will slowly float off in some direction.
171 // So, the problem is that, when an avatar is standing, we cannot tell creaping error
172 // from real pushing.
173 // The code below uses whether the collider is static or moving to decide whether to zero motion.
174
175 m_velocityMotor.Step(timeStep);
176 m_controllingPrim.IsStationary = false;
177
178 // If we're not supposed to be moving, make sure things are zero.
179 if (m_velocityMotor.ErrorIsZero() && m_velocityMotor.TargetValue == OMV.Vector3.Zero)
180 {
181 // The avatar shouldn't be moving
182 m_velocityMotor.Zero();
183
184 if (m_controllingPrim.IsColliding)
185 {
186 // If we are colliding with a stationary object, presume we're standing and don't move around
187 if (!m_controllingPrim.ColliderIsMoving && !m_controllingPrim.ColliderIsVolumeDetect)
188 {
189 m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID);
190 m_controllingPrim.IsStationary = true;
191 m_controllingPrim.ZeroMotion(true /* inTaintTime */);
192 }
193
194 // Standing has more friction on the ground
195 if (m_controllingPrim.Friction != BSParam.AvatarStandingFriction)
196 {
197 m_controllingPrim.Friction = BSParam.AvatarStandingFriction;
198 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
199 }
200 }
201 else
202 {
203 if (m_controllingPrim.Flying)
204 {
205 // Flying and not colliding and velocity nearly zero.
206 m_controllingPrim.ZeroMotion(true /* inTaintTime */);
207 }
208 }
209
210 m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}",
211 m_controllingPrim.LocalID, m_velocityMotor.TargetValue, m_controllingPrim.IsColliding);
212 }
213 else
214 {
215 // Supposed to be moving.
216 OMV.Vector3 stepVelocity = m_velocityMotor.CurrentValue;
217
218 if (m_controllingPrim.Friction != BSParam.AvatarFriction)
219 {
220 // Probably starting to walk. Set friction to moving friction.
221 m_controllingPrim.Friction = BSParam.AvatarFriction;
222 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
223 }
224
225 if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
226 {
227 stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
228 }
229
230
231 // Colliding and not flying with an upward force. The avatar must be trying to jump.
232 if (!m_controllingPrim.Flying && m_controllingPrim.IsColliding && stepVelocity.Z > 0)
233 {
234 // We allow the upward force to happen for this many frames.
235 m_jumpFrames = BSParam.AvatarJumpFrames;
236 m_jumpVelocity = stepVelocity.Z;
237 }
238
239 // The case where the avatar is not colliding and is not flying is special.
240 // The avatar is either falling or jumping and the user can be applying force to the avatar
241 // (force in some direction or force up or down).
242 // If the avatar has negative Z velocity and is not colliding, presume we're falling and keep the velocity.
243 // If the user is trying to apply upward force but we're not colliding, assume the avatar
244 // is trying to jump and don't apply the upward force if not touching the ground any more.
245 if (!m_controllingPrim.Flying && !m_controllingPrim.IsColliding)
246 {
247 // If upward velocity is being applied, this must be a jump and only allow that to go on so long
248 if (m_jumpFrames > 0)
249 {
250 // Since not touching the ground, only apply upward force for so long.
251 m_jumpFrames--;
252 stepVelocity.Z = m_jumpVelocity;
253 }
254 else
255 {
256 // Since we're not affected by anything, whatever vertical motion the avatar has, continue that.
257 stepVelocity.Z = m_controllingPrim.RawVelocity.Z;
258 }
259 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
260 }
261
262 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
263 OMV.Vector3 moveForce = (stepVelocity - m_controllingPrim.RawVelocity) * m_controllingPrim.Mass;
264
265 // Add special movement force to allow avatars to walk up stepped surfaces.
266 moveForce += WalkUpStairs();
267
268 m_physicsScene.DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}",
269 m_controllingPrim.LocalID, stepVelocity, m_controllingPrim.RawVelocity, m_controllingPrim.Mass, moveForce);
270 m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, moveForce);
271 }
272 }
273
274 // Called just as the property update is received from the physics engine.
275 // Do any mode necessary for avatar movement.
276 private void Process_OnPreUpdateProperty(ref EntityProperties entprop)
277 {
278 // Don't change position if standing on a stationary object.
279 if (m_controllingPrim.IsStationary)
280 {
281 entprop.Position = m_controllingPrim.RawPosition;
282 entprop.Velocity = OMV.Vector3.Zero;
283 m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation);
284 }
285
286 }
287
288 // Decide if the character is colliding with a low object and compute a force to pop the
289 // avatar up so it can walk up and over the low objects.
290 private OMV.Vector3 WalkUpStairs()
291 {
292 OMV.Vector3 ret = OMV.Vector3.Zero;
293
294 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}",
295 m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying,
296 m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z);
297
298 // Check for stairs climbing if colliding, not flying and moving forward
299 if ( m_controllingPrim.IsColliding
300 && !m_controllingPrim.Flying
301 && m_controllingPrim.TargetVelocitySpeed > 0.1f )
302 {
303 // The range near the character's feet where we will consider stairs
304 // float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) + 0.05f;
305 // Note: there is a problem with the computation of the capsule height. Thus RawPosition is off
306 // from the height. Revisit size and this computation when height is scaled properly.
307 float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) - 0.05f;
308 float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
309
310 // Look for a collision point that is near the character's feet and is oriented the same as the charactor is.
311 // Find the highest 'good' collision.
312 OMV.Vector3 highestTouchPosition = OMV.Vector3.Zero;
313 foreach (KeyValuePair<uint, ContactPoint> kvp in m_controllingPrim.CollisionsLastTick.m_objCollisionList)
314 {
315 // Don't care about collisions with the terrain
316 if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID)
317 {
318 BSPhysObject collisionObject;
319 if (m_physicsScene.PhysObjects.TryGetValue(kvp.Key, out collisionObject))
320 {
321 if (!collisionObject.IsVolumeDetect)
322 {
323 OMV.Vector3 touchPosition = kvp.Value.Position;
324 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
325 m_controllingPrim.LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
326 if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
327 {
328 // This contact is within the 'near the feet' range.
329 // The normal should be our contact point to the object so it is pointing away
330 // thus the difference between our facing orientation and the normal should be small.
331 OMV.Vector3 directionFacing = OMV.Vector3.UnitX * m_controllingPrim.RawOrientation;
332 OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
333 float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
334 if (diff < BSParam.AvatarStepApproachFactor)
335 {
336 if (highestTouchPosition.Z < touchPosition.Z)
337 highestTouchPosition = touchPosition;
338 }
339 }
340 }
341 }
342 }
343 }
344 m_walkingUpStairs = 0;
345 // If there is a good step sensing, move the avatar over the step.
346 if (highestTouchPosition != OMV.Vector3.Zero)
347 {
348 // Remember that we are going up stairs. This is needed because collisions
349 // will stop when we move up so this smoothes out that effect.
350 m_walkingUpStairs = BSParam.AvatarStepSmoothingSteps;
351
352 m_lastStepUp = highestTouchPosition.Z - nearFeetHeightMin;
353 ret = ComputeStairCorrection(m_lastStepUp);
354 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},ret={3}",
355 m_controllingPrim.LocalID, highestTouchPosition, nearFeetHeightMin, ret);
356 }
357 }
358 else
359 {
360 // If we used to be going up stairs but are not now, smooth the case where collision goes away while
361 // we are bouncing up the stairs.
362 if (m_walkingUpStairs > 0)
363 {
364 m_walkingUpStairs--;
365 ret = ComputeStairCorrection(m_lastStepUp);
366 }
367 }
368
369 return ret;
370 }
371
372 private OMV.Vector3 ComputeStairCorrection(float stepUp)
373 {
374 OMV.Vector3 ret = OMV.Vector3.Zero;
375 OMV.Vector3 displacement = OMV.Vector3.Zero;
376
377 if (stepUp > 0f)
378 {
379 // Found the stairs contact point. Push up a little to raise the character.
380 if (BSParam.AvatarStepForceFactor > 0f)
381 {
382 float upForce = stepUp * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor;
383 ret = new OMV.Vector3(0f, 0f, upForce);
384 }
385
386 // Also move the avatar up for the new height
387 if (BSParam.AvatarStepUpCorrectionFactor > 0f)
388 {
389 // Move the avatar up related to the height of the collision
390 displacement = new OMV.Vector3(0f, 0f, stepUp * BSParam.AvatarStepUpCorrectionFactor);
391 m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
392 }
393 else
394 {
395 if (BSParam.AvatarStepUpCorrectionFactor < 0f)
396 {
397 // Move the avatar up about the specified step height
398 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight);
399 m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
400 }
401 }
402 m_physicsScene.DetailLog("{0},BSCharacter.WalkUpStairs.ComputeStairCorrection,disp={1},force={2}",
403 m_controllingPrim.LocalID, displacement, ret);
404
405 }
406 return ret;
407 }
408}
409}
410
411
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
new file mode 100755
index 0000000..8a79809
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
@@ -0,0 +1,173 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorHover : BSActor
40{
41 private BSFMotor m_hoverMotor;
42
43 public BSActorHover(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName)
45 {
46 m_hoverMotor = null;
47 m_physicsScene.DetailLog("{0},BSActorHover,constructor", m_controllingPrim.LocalID);
48 }
49
50 // BSActor.isActive
51 public override bool isActive
52 {
53 get { return Enabled; }
54 }
55
56 // Release any connections and resources used by the actor.
57 // BSActor.Dispose()
58 public override void Dispose()
59 {
60 Enabled = false;
61 }
62
63 // Called when physical parameters (properties set in Bullet) need to be re-applied.
64 // Called at taint-time.
65 // BSActor.Refresh()
66 public override void Refresh()
67 {
68 m_physicsScene.DetailLog("{0},BSActorHover,refresh", m_controllingPrim.LocalID);
69
70 // If not active any more, turn me off
71 if (!m_controllingPrim.HoverActive)
72 {
73 SetEnabled(false);
74 }
75
76 // If the object is physically active, add the hoverer prestep action
77 if (isActive)
78 {
79 ActivateHover();
80 }
81 else
82 {
83 DeactivateHover();
84 }
85 }
86
87 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
88 // Register a prestep action to restore physical requirements before the next simulation step.
89 // Called at taint-time.
90 // BSActor.RemoveDependencies()
91 public override void RemoveDependencies()
92 {
93 // Nothing to do for the hoverer since it is all software at pre-step action time.
94 }
95
96 // If a hover motor has not been created, create one and start the hovering.
97 private void ActivateHover()
98 {
99 if (m_hoverMotor == null)
100 {
101 // Turning the target on
102 m_hoverMotor = new BSFMotor("BSActorHover",
103 m_controllingPrim.HoverTau, // timeScale
104 BSMotor.Infinite, // decay time scale
105 1f // efficiency
106 );
107 m_hoverMotor.SetTarget(ComputeCurrentHoverHeight());
108 m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z);
109 m_hoverMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages.
110
111 m_physicsScene.BeforeStep += Hoverer;
112 }
113 }
114
115 private void DeactivateHover()
116 {
117 if (m_hoverMotor != null)
118 {
119 m_physicsScene.BeforeStep -= Hoverer;
120 m_hoverMotor = null;
121 }
122 }
123
124 // Called just before the simulation step. Update the vertical position for hoverness.
125 private void Hoverer(float timeStep)
126 {
127 // Don't do hovering while the object is selected.
128 if (!isActive)
129 return;
130
131 m_hoverMotor.SetCurrent(m_controllingPrim.RawPosition.Z);
132 m_hoverMotor.SetTarget(ComputeCurrentHoverHeight());
133 float targetHeight = m_hoverMotor.Step(timeStep);
134
135 // 'targetHeight' is where we'd like the Z of the prim to be at this moment.
136 // Compute the amount of force to push us there.
137 float moveForce = (targetHeight - m_controllingPrim.RawPosition.Z) * m_controllingPrim.RawMass;
138 // Undo anything the object thinks it's doing at the moment
139 moveForce = -m_controllingPrim.RawVelocity.Z * m_controllingPrim.Mass;
140
141 m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, new OMV.Vector3(0f, 0f, moveForce));
142 m_physicsScene.DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}",
143 m_controllingPrim.LocalID, targetHeight, moveForce, m_controllingPrim.RawMass);
144 }
145
146 // Based on current position, determine what we should be hovering at now.
147 // Must recompute often. What if we walked offa cliff>
148 private float ComputeCurrentHoverHeight()
149 {
150 float ret = m_controllingPrim.HoverHeight;
151 float groundHeight = m_physicsScene.TerrainManager.GetTerrainHeightAtXYZ(m_controllingPrim.RawPosition);
152
153 switch (m_controllingPrim.HoverType)
154 {
155 case PIDHoverType.Ground:
156 ret = groundHeight + m_controllingPrim.HoverHeight;
157 break;
158 case PIDHoverType.GroundAndWater:
159 float waterHeight = m_physicsScene.TerrainManager.GetWaterLevelAtXYZ(m_controllingPrim.RawPosition);
160 if (groundHeight > waterHeight)
161 {
162 ret = groundHeight + m_controllingPrim.HoverHeight;
163 }
164 else
165 {
166 ret = waterHeight + m_controllingPrim.HoverHeight;
167 }
168 break;
169 }
170 return ret;
171 }
172}
173}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
index 7219617..8b0fdeb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
@@ -36,11 +36,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37public class BSActorLockAxis : BSActor 37public class BSActorLockAxis : BSActor
38{ 38{
39 bool TryExperimentalLockAxisCode = true;
40 BSConstraint LockAxisConstraint = null; 39 BSConstraint LockAxisConstraint = null;
41 40
42 public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName) 41 public BSActorLockAxis(BSScene physicsScene, BSPhysObject pObj, string actorName)
43 : base(physicsScene, pObj,actorName) 42 : base(physicsScene, pObj, actorName)
44 { 43 {
45 m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID); 44 m_physicsScene.DetailLog("{0},BSActorLockAxis,constructor", m_controllingPrim.LocalID);
46 LockAxisConstraint = null; 45 LockAxisConstraint = null;
@@ -64,23 +63,18 @@ public class BSActorLockAxis : BSActor
64 // BSActor.Refresh() 63 // BSActor.Refresh()
65 public override void Refresh() 64 public override void Refresh()
66 { 65 {
67 m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,lockedAxis={1},enabled={2},pActive={3}", 66 m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,lockedAxis={1},enabled={2},pActive={3}",
68 m_controllingPrim.LocalID, m_controllingPrim.LockedAxis, Enabled, m_controllingPrim.IsPhysicallyActive); 67 m_controllingPrim.LocalID, m_controllingPrim.LockedAngularAxis, Enabled, m_controllingPrim.IsPhysicallyActive);
69 // If all the axis are free, we don't need to exist 68 // If all the axis are free, we don't need to exist
70 if (m_controllingPrim.LockedAxis == m_controllingPrim.LockedAxisFree) 69 if (m_controllingPrim.LockedAngularAxis == m_controllingPrim.LockedAxisFree)
71 { 70 {
72 m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,allAxisFree,removing={1}", m_controllingPrim.LocalID, ActorName); 71 Enabled = false;
73 m_controllingPrim.PhysicalActors.RemoveAndRelease(ActorName);
74 return;
75 } 72 }
73
76 // If the object is physically active, add the axis locking constraint 74 // If the object is physically active, add the axis locking constraint
77 if (Enabled 75 if (isActive)
78 && m_controllingPrim.IsPhysicallyActive
79 && TryExperimentalLockAxisCode
80 && m_controllingPrim.LockedAxis != m_controllingPrim.LockedAxisFree)
81 { 76 {
82 if (LockAxisConstraint == null) 77 AddAxisLockConstraint();
83 AddAxisLockConstraint();
84 } 78 }
85 else 79 else
86 { 80 {
@@ -91,15 +85,15 @@ public class BSActorLockAxis : BSActor
91 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 85 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
92 // Register a prestep action to restore physical requirements before the next simulation step. 86 // Register a prestep action to restore physical requirements before the next simulation step.
93 // Called at taint-time. 87 // Called at taint-time.
94 // BSActor.RemoveBodyDependencies() 88 // BSActor.RemoveDependencies()
95 public override void RemoveBodyDependencies() 89 public override void RemoveDependencies()
96 { 90 {
97 if (LockAxisConstraint != null) 91 if (LockAxisConstraint != null)
98 { 92 {
99 // If a constraint is set up, remove it from the physical scene 93 // If a constraint is set up, remove it from the physical scene
100 RemoveAxisLockConstraint(); 94 RemoveAxisLockConstraint();
101 // Schedule a call before the next simulation step to restore the constraint. 95 // Schedule a call before the next simulation step to restore the constraint.
102 m_physicsScene.PostTaintObject(m_controllingPrim.LockedAxisActorName, m_controllingPrim.LocalID, delegate() 96 m_physicsScene.PostTaintObject("BSActorLockAxis:" + ActorName, m_controllingPrim.LocalID, delegate()
103 { 97 {
104 Refresh(); 98 Refresh();
105 }); 99 });
@@ -108,58 +102,76 @@ public class BSActorLockAxis : BSActor
108 102
109 private void AddAxisLockConstraint() 103 private void AddAxisLockConstraint()
110 { 104 {
111 // Lock that axis by creating a 6DOF constraint that has one end in the world and 105 if (LockAxisConstraint == null)
112 // the other in the object. 106 {
113 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817 107 // Lock that axis by creating a 6DOF constraint that has one end in the world and
114 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380 108 // the other in the object.
115 109 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=20817
116 // Remove any existing axis constraint (just to be sure) 110 // http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?p=26380
117 RemoveAxisLockConstraint();
118 111
119 BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(m_physicsScene.World, m_controllingPrim.PhysBody, 112 // Remove any existing axis constraint (just to be sure)
120 OMV.Vector3.Zero, OMV.Quaternion.Identity, 113 RemoveAxisLockConstraint();
121 false /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */);
122 LockAxisConstraint = axisConstrainer;
123 m_physicsScene.Constraints.AddConstraint(LockAxisConstraint);
124 114
125 // The constraint is tied to the world and oriented to the prim. 115 BSConstraint6Dof axisConstrainer = new BSConstraint6Dof(m_physicsScene.World, m_controllingPrim.PhysBody,
116 OMV.Vector3.Zero, OMV.Quaternion.Identity,
117 false /* useLinearReferenceFrameB */, true /* disableCollisionsBetweenLinkedBodies */);
118 LockAxisConstraint = axisConstrainer;
119 m_physicsScene.Constraints.AddConstraint(LockAxisConstraint);
126 120
127 // Free to move linearly in the region 121 // The constraint is tied to the world and oriented to the prim.
128 OMV.Vector3 linearLow = OMV.Vector3.Zero;
129 OMV.Vector3 linearHigh = m_physicsScene.TerrainManager.DefaultRegionSize;
130 axisConstrainer.SetLinearLimits(linearLow, linearHigh);
131 122
132 // Angular with some axis locked 123 // Free to move linearly in the region
133 float fPI = (float)Math.PI; 124 OMV.Vector3 linearLow = OMV.Vector3.Zero;
134 OMV.Vector3 angularLow = new OMV.Vector3(-fPI, -fPI, -fPI); 125 OMV.Vector3 linearHigh = m_physicsScene.TerrainManager.DefaultRegionSize;
135 OMV.Vector3 angularHigh = new OMV.Vector3(fPI, fPI, fPI); 126 if (m_controllingPrim.LockedLinearAxis.X != BSPhysObject.FreeAxis)
136 if (m_controllingPrim.LockedAxis.X != 1f) 127 {
137 { 128 linearLow.X = m_controllingPrim.RawPosition.X;
138 angularLow.X = 0f; 129 linearHigh.X = m_controllingPrim.RawPosition.X;
139 angularHigh.X = 0f; 130 }
140 } 131 if (m_controllingPrim.LockedLinearAxis.Y != BSPhysObject.FreeAxis)
141 if (m_controllingPrim.LockedAxis.Y != 1f) 132 {
142 { 133 linearLow.Y = m_controllingPrim.RawPosition.Y;
143 angularLow.Y = 0f; 134 linearHigh.Y = m_controllingPrim.RawPosition.Y;
144 angularHigh.Y = 0f; 135 }
145 } 136 if (m_controllingPrim.LockedLinearAxis.Z != BSPhysObject.FreeAxis)
146 if (m_controllingPrim.LockedAxis.Z != 1f) 137 {
147 { 138 linearLow.Z = m_controllingPrim.RawPosition.Z;
148 angularLow.Z = 0f; 139 linearHigh.Z = m_controllingPrim.RawPosition.Z;
149 angularHigh.Z = 0f; 140 }
150 } 141 axisConstrainer.SetLinearLimits(linearLow, linearHigh);
151 if (!axisConstrainer.SetAngularLimits(angularLow, angularHigh)) 142
152 { 143 // Angular with some axis locked
153 m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,failedSetAngularLimits", m_controllingPrim.LocalID); 144 float fPI = (float)Math.PI;
154 } 145 OMV.Vector3 angularLow = new OMV.Vector3(-fPI, -fPI, -fPI);
146 OMV.Vector3 angularHigh = new OMV.Vector3(fPI, fPI, fPI);
147 if (m_controllingPrim.LockedAngularAxis.X != BSPhysObject.FreeAxis)
148 {
149 angularLow.X = 0f;
150 angularHigh.X = 0f;
151 }
152 if (m_controllingPrim.LockedAngularAxis.Y != BSPhysObject.FreeAxis)
153 {
154 angularLow.Y = 0f;
155 angularHigh.Y = 0f;
156 }
157 if (m_controllingPrim.LockedAngularAxis.Z != BSPhysObject.FreeAxis)
158 {
159 angularLow.Z = 0f;
160 angularHigh.Z = 0f;
161 }
162 if (!axisConstrainer.SetAngularLimits(angularLow, angularHigh))
163 {
164 m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,failedSetAngularLimits", m_controllingPrim.LocalID);
165 }
155 166
156 m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,create,linLow={1},linHi={2},angLow={3},angHi={4}", 167 m_physicsScene.DetailLog("{0},BSActorLockAxis.AddAxisLockConstraint,create,linLow={1},linHi={2},angLow={3},angHi={4}",
157 m_controllingPrim.LocalID, linearLow, linearHigh, angularLow, angularHigh); 168 m_controllingPrim.LocalID, linearLow, linearHigh, angularLow, angularHigh);
158 169
159 // Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo. 170 // Constants from one of the posts mentioned above and used in Bullet's ConstraintDemo.
160 axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f); 171 axisConstrainer.TranslationalLimitMotor(true /* enable */, 5.0f, 0.1f);
161 172
162 axisConstrainer.RecomputeConstraintVariables(m_controllingPrim.RawMass); 173 axisConstrainer.RecomputeConstraintVariables(m_controllingPrim.RawMass);
174 }
163 } 175 }
164 176
165 private void RemoveAxisLockConstraint() 177 private void RemoveAxisLockConstraint()
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
new file mode 100755
index 0000000..bdf4bc0
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
@@ -0,0 +1,219 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorMoveToTarget : BSActor
40{
41 private BSVMotor m_targetMotor;
42
43 public BSActorMoveToTarget(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName)
45 {
46 m_targetMotor = null;
47 m_physicsScene.DetailLog("{0},BSActorMoveToTarget,constructor", m_controllingPrim.LocalID);
48 }
49
50 // BSActor.isActive
51 public override bool isActive
52 {
53 // MoveToTarget only works on physical prims
54 get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
55 }
56
57 // Release any connections and resources used by the actor.
58 // BSActor.Dispose()
59 public override void Dispose()
60 {
61 Enabled = false;
62 }
63
64 // Called when physical parameters (properties set in Bullet) need to be re-applied.
65 // Called at taint-time.
66 // BSActor.Refresh()
67 public override void Refresh()
68 {
69 m_physicsScene.DetailLog("{0},BSActorMoveToTarget,refresh,enabled={1},active={2},target={3},tau={4}",
70 m_controllingPrim.LocalID, Enabled, m_controllingPrim.MoveToTargetActive,
71 m_controllingPrim.MoveToTargetTarget, m_controllingPrim.MoveToTargetTau );
72
73 // If not active any more...
74 if (!m_controllingPrim.MoveToTargetActive)
75 {
76 Enabled = false;
77 }
78
79 if (isActive)
80 {
81 ActivateMoveToTarget();
82 }
83 else
84 {
85 DeactivateMoveToTarget();
86 }
87 }
88
89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
90 // Register a prestep action to restore physical requirements before the next simulation step.
91 // Called at taint-time.
92 // BSActor.RemoveDependencies()
93 public override void RemoveDependencies()
94 {
95 // Nothing to do for the moveToTarget since it is all software at pre-step action time.
96 }
97
98 // If a hover motor has not been created, create one and start the hovering.
99 private void ActivateMoveToTarget()
100 {
101 if (m_targetMotor == null)
102 {
103 // We're taking over after this.
104 m_controllingPrim.ZeroMotion(true);
105
106 /* Someday use the PID controller
107 m_targetMotor = new BSPIDVMotor("BSActorMoveToTarget-" + m_controllingPrim.LocalID.ToString());
108 m_targetMotor.TimeScale = m_controllingPrim.MoveToTargetTau;
109 m_targetMotor.Efficiency = 1f;
110 */
111 m_targetMotor = new BSVMotor("BSActorMoveToTarget-" + m_controllingPrim.LocalID.ToString(),
112 m_controllingPrim.MoveToTargetTau, // timeScale
113 BSMotor.Infinite, // decay time scale
114 1f // efficiency
115 );
116 m_targetMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages.
117 m_targetMotor.SetTarget(m_controllingPrim.MoveToTargetTarget);
118 m_targetMotor.SetCurrent(m_controllingPrim.RawPosition);
119
120 // m_physicsScene.BeforeStep += Mover;
121 m_physicsScene.BeforeStep += Mover2;
122 }
123 else
124 {
125 // If already allocated, make sure the target and other paramters are current
126 m_targetMotor.SetTarget(m_controllingPrim.MoveToTargetTarget);
127 m_targetMotor.SetCurrent(m_controllingPrim.RawPosition);
128 }
129 }
130
131 private void DeactivateMoveToTarget()
132 {
133 if (m_targetMotor != null)
134 {
135 // m_physicsScene.BeforeStep -= Mover;
136 m_physicsScene.BeforeStep -= Mover2;
137 m_targetMotor = null;
138 }
139 }
140
141 // Origional mover that set the objects position to move to the target.
142 // The problem was that gravity would keep trying to push the object down so
143 // the overall downward velocity would increase to infinity.
144 // Called just before the simulation step.
145 private void Mover(float timeStep)
146 {
147 // Don't do hovering while the object is selected.
148 if (!isActive)
149 return;
150
151 OMV.Vector3 origPosition = m_controllingPrim.RawPosition; // DEBUG DEBUG (for printout below)
152
153 // 'movePosition' is where we'd like the prim to be at this moment.
154 OMV.Vector3 movePosition = m_controllingPrim.RawPosition + m_targetMotor.Step(timeStep);
155
156 // If we are very close to our target, turn off the movement motor.
157 if (m_targetMotor.ErrorIsZero())
158 {
159 m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover,zeroMovement,movePos={1},pos={2},mass={3}",
160 m_controllingPrim.LocalID, movePosition, m_controllingPrim.RawPosition, m_controllingPrim.Mass);
161 m_controllingPrim.ForcePosition = m_targetMotor.TargetValue;
162 m_controllingPrim.ForceVelocity = OMV.Vector3.Zero;
163 // Setting the position does not cause the physics engine to generate a property update. Force it.
164 m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
165 }
166 else
167 {
168 m_controllingPrim.ForcePosition = movePosition;
169 // Setting the position does not cause the physics engine to generate a property update. Force it.
170 m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
171 }
172 m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover,move,fromPos={1},movePos={2}",
173 m_controllingPrim.LocalID, origPosition, movePosition);
174 }
175
176 // Version of mover that applies forces to move the physical object to the target.
177 // Also overcomes gravity so the object doesn't just drop to the ground.
178 // Called just before the simulation step.
179 private void Mover2(float timeStep)
180 {
181 // Don't do hovering while the object is selected.
182 if (!isActive)
183 return;
184
185 OMV.Vector3 origPosition = m_controllingPrim.RawPosition; // DEBUG DEBUG (for printout below)
186 OMV.Vector3 addedForce = OMV.Vector3.Zero;
187
188 // CorrectionVector is the movement vector required this step
189 OMV.Vector3 correctionVector = m_targetMotor.Step(timeStep, m_controllingPrim.RawPosition);
190
191 // If we are very close to our target, turn off the movement motor.
192 if (m_targetMotor.ErrorIsZero())
193 {
194 m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover3,zeroMovement,pos={1},mass={2}",
195 m_controllingPrim.LocalID, m_controllingPrim.RawPosition, m_controllingPrim.Mass);
196 m_controllingPrim.ForcePosition = m_targetMotor.TargetValue;
197 m_controllingPrim.ForceVelocity = OMV.Vector3.Zero;
198 // Setting the position does not cause the physics engine to generate a property update. Force it.
199 m_physicsScene.PE.PushUpdate(m_controllingPrim.PhysBody);
200 }
201 else
202 {
203 // First force to move us there -- the motor return a timestep scaled value.
204 addedForce = correctionVector / timeStep;
205 // Remove the existing velocity (only the moveToTarget force counts)
206 addedForce -= m_controllingPrim.RawVelocity;
207 // Overcome gravity.
208 addedForce -= m_controllingPrim.Gravity;
209
210 // Add enough force to overcome the mass of the object
211 addedForce *= m_controllingPrim.Mass;
212
213 m_controllingPrim.AddForce(addedForce, false /* pushForce */, true /* inTaintTime */);
214 }
215 m_physicsScene.DetailLog("{0},BSActorMoveToTarget.Mover3,move,fromPos={1},addedForce={2}",
216 m_controllingPrim.LocalID, origPosition, addedForce);
217 }
218}
219}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
new file mode 100755
index 0000000..96fa0b6
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
@@ -0,0 +1,137 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorSetForce : BSActor
40{
41 BSFMotor m_forceMotor;
42
43 public BSActorSetForce(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName)
45 {
46 m_forceMotor = null;
47 m_physicsScene.DetailLog("{0},BSActorSetForce,constructor", m_controllingPrim.LocalID);
48 }
49
50 // BSActor.isActive
51 public override bool isActive
52 {
53 get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
54 }
55
56 // Release any connections and resources used by the actor.
57 // BSActor.Dispose()
58 public override void Dispose()
59 {
60 Enabled = false;
61 }
62
63 // Called when physical parameters (properties set in Bullet) need to be re-applied.
64 // Called at taint-time.
65 // BSActor.Refresh()
66 public override void Refresh()
67 {
68 m_physicsScene.DetailLog("{0},BSActorSetForce,refresh", m_controllingPrim.LocalID);
69
70 // If not active any more, get rid of me (shouldn't ever happen, but just to be safe)
71 if (m_controllingPrim.RawForce == OMV.Vector3.Zero)
72 {
73 m_physicsScene.DetailLog("{0},BSActorSetForce,refresh,notSetForce,removing={1}", m_controllingPrim.LocalID, ActorName);
74 Enabled = false;
75 return;
76 }
77
78 // If the object is physically active, add the hoverer prestep action
79 if (isActive)
80 {
81 ActivateSetForce();
82 }
83 else
84 {
85 DeactivateSetForce();
86 }
87 }
88
89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
90 // Register a prestep action to restore physical requirements before the next simulation step.
91 // Called at taint-time.
92 // BSActor.RemoveDependencies()
93 public override void RemoveDependencies()
94 {
95 // Nothing to do for the hoverer since it is all software at pre-step action time.
96 }
97
98 // If a hover motor has not been created, create one and start the hovering.
99 private void ActivateSetForce()
100 {
101 if (m_forceMotor == null)
102 {
103 // A fake motor that might be used someday
104 m_forceMotor = new BSFMotor("setForce", 1f, 1f, 1f);
105
106 m_physicsScene.BeforeStep += Mover;
107 }
108 }
109
110 private void DeactivateSetForce()
111 {
112 if (m_forceMotor != null)
113 {
114 m_physicsScene.BeforeStep -= Mover;
115 m_forceMotor = null;
116 }
117 }
118
119 // Called just before the simulation step. Update the vertical position for hoverness.
120 private void Mover(float timeStep)
121 {
122 // Don't do force while the object is selected.
123 if (!isActive)
124 return;
125
126 m_physicsScene.DetailLog("{0},BSActorSetForce,preStep,force={1}", m_controllingPrim.LocalID, m_controllingPrim.RawForce);
127 if (m_controllingPrim.PhysBody.HasPhysicalBody)
128 {
129 m_physicsScene.PE.ApplyCentralForce(m_controllingPrim.PhysBody, m_controllingPrim.RawForce);
130 m_controllingPrim.ActivateIfPhysical(false);
131 }
132
133 // TODO:
134 }
135}
136}
137
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
new file mode 100755
index 0000000..65098e1
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
@@ -0,0 +1,138 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Text;
32
33using OpenSim.Region.Physics.Manager;
34
35using OMV = OpenMetaverse;
36
37namespace OpenSim.Region.Physics.BulletSPlugin
38{
39public class BSActorSetTorque : BSActor
40{
41 BSFMotor m_torqueMotor;
42
43 public BSActorSetTorque(BSScene physicsScene, BSPhysObject pObj, string actorName)
44 : base(physicsScene, pObj, actorName)
45 {
46 m_torqueMotor = null;
47 m_physicsScene.DetailLog("{0},BSActorSetTorque,constructor", m_controllingPrim.LocalID);
48 }
49
50 // BSActor.isActive
51 public override bool isActive
52 {
53 get { return Enabled && m_controllingPrim.IsPhysicallyActive; }
54 }
55
56 // Release any connections and resources used by the actor.
57 // BSActor.Dispose()
58 public override void Dispose()
59 {
60 Enabled = false;
61 }
62
63 // Called when physical parameters (properties set in Bullet) need to be re-applied.
64 // Called at taint-time.
65 // BSActor.Refresh()
66 public override void Refresh()
67 {
68 m_physicsScene.DetailLog("{0},BSActorSetTorque,refresh,torque={1}", m_controllingPrim.LocalID, m_controllingPrim.RawTorque);
69
70 // If not active any more, get rid of me (shouldn't ever happen, but just to be safe)
71 if (m_controllingPrim.RawTorque == OMV.Vector3.Zero)
72 {
73 m_physicsScene.DetailLog("{0},BSActorSetTorque,refresh,notSetTorque,disabling={1}", m_controllingPrim.LocalID, ActorName);
74 Enabled = false;
75 return;
76 }
77
78 // If the object is physically active, add the hoverer prestep action
79 if (isActive)
80 {
81 ActivateSetTorque();
82 }
83 else
84 {
85 DeactivateSetTorque();
86 }
87 }
88
89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
90 // Register a prestep action to restore physical requirements before the next simulation step.
91 // Called at taint-time.
92 // BSActor.RemoveDependencies()
93 public override void RemoveDependencies()
94 {
95 // Nothing to do for the hoverer since it is all software at pre-step action time.
96 }
97
98 // If a hover motor has not been created, create one and start the hovering.
99 private void ActivateSetTorque()
100 {
101 if (m_torqueMotor == null)
102 {
103 // A fake motor that might be used someday
104 m_torqueMotor = new BSFMotor("setTorque", 1f, 1f, 1f);
105
106 m_physicsScene.BeforeStep += Mover;
107 }
108 }
109
110 private void DeactivateSetTorque()
111 {
112 if (m_torqueMotor != null)
113 {
114 m_physicsScene.BeforeStep -= Mover;
115 m_torqueMotor = null;
116 }
117 }
118
119 // Called just before the simulation step. Update the vertical position for hoverness.
120 private void Mover(float timeStep)
121 {
122 // Don't do force while the object is selected.
123 if (!isActive)
124 return;
125
126 m_physicsScene.DetailLog("{0},BSActorSetTorque,preStep,force={1}", m_controllingPrim.LocalID, m_controllingPrim.RawTorque);
127 if (m_controllingPrim.PhysBody.HasPhysicalBody)
128 {
129 m_controllingPrim.AddAngularForce(m_controllingPrim.RawTorque, false, true);
130 m_controllingPrim.ActivateIfPhysical(false);
131 }
132
133 // TODO:
134 }
135}
136}
137
138
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
index 5a19ba4..e0ccc50 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
@@ -32,56 +32,79 @@ namespace OpenSim.Region.Physics.BulletSPlugin
32{ 32{
33public class BSActorCollection 33public class BSActorCollection
34{ 34{
35 private BSScene PhysicsScene { get; set; } 35 private BSScene m_physicsScene { get; set; }
36 private Dictionary<string, BSActor> m_actors; 36 private Dictionary<string, BSActor> m_actors;
37 37
38 public BSActorCollection(BSScene physicsScene) 38 public BSActorCollection(BSScene physicsScene)
39 { 39 {
40 PhysicsScene = physicsScene; 40 m_physicsScene = physicsScene;
41 m_actors = new Dictionary<string, BSActor>(); 41 m_actors = new Dictionary<string, BSActor>();
42 } 42 }
43 public void Add(string name, BSActor actor) 43 public void Add(string name, BSActor actor)
44 { 44 {
45 m_actors[name] = actor; 45 lock (m_actors)
46 {
47 if (!m_actors.ContainsKey(name))
48 {
49 m_actors[name] = actor;
50 }
51 }
46 } 52 }
47 public bool RemoveAndRelease(string name) 53 public bool RemoveAndRelease(string name)
48 { 54 {
49 bool ret = false; 55 bool ret = false;
50 if (m_actors.ContainsKey(name)) 56 lock (m_actors)
51 { 57 {
52 BSActor beingRemoved = m_actors[name]; 58 if (m_actors.ContainsKey(name))
53 beingRemoved.Dispose(); 59 {
54 m_actors.Remove(name); 60 BSActor beingRemoved = m_actors[name];
55 ret = true; 61 m_actors.Remove(name);
62 beingRemoved.Dispose();
63 ret = true;
64 }
56 } 65 }
57 return ret; 66 return ret;
58 } 67 }
59 public void Clear() 68 public void Clear()
60 { 69 {
61 Release(); 70 lock (m_actors)
62 m_actors.Clear(); 71 {
72 ForEachActor(a => a.Dispose());
73 m_actors.Clear();
74 }
75 }
76 public void Dispose()
77 {
78 Clear();
63 } 79 }
64 public bool HasActor(string name) 80 public bool HasActor(string name)
65 { 81 {
66 return m_actors.ContainsKey(name); 82 return m_actors.ContainsKey(name);
67 } 83 }
84 public bool TryGetActor(string actorName, out BSActor theActor)
85 {
86 return m_actors.TryGetValue(actorName, out theActor);
87 }
68 public void ForEachActor(Action<BSActor> act) 88 public void ForEachActor(Action<BSActor> act)
69 { 89 {
70 foreach (KeyValuePair<string, BSActor> kvp in m_actors) 90 lock (m_actors)
71 act(kvp.Value); 91 {
92 foreach (KeyValuePair<string, BSActor> kvp in m_actors)
93 act(kvp.Value);
94 }
72 } 95 }
73 96
74 public void Release() 97 public void Enable(bool enabl)
75 { 98 {
76 ForEachActor(a => a.Dispose()); 99 ForEachActor(a => a.SetEnabled(enabl));
77 } 100 }
78 public void Refresh() 101 public void Refresh()
79 { 102 {
80 ForEachActor(a => a.Refresh()); 103 ForEachActor(a => a.Refresh());
81 } 104 }
82 public void RemoveBodyDependencies() 105 public void RemoveDependencies()
83 { 106 {
84 ForEachActor(a => a.RemoveBodyDependencies()); 107 ForEachActor(a => a.RemoveDependencies());
85 } 108 }
86} 109}
87 110
@@ -90,7 +113,7 @@ public class BSActorCollection
90/// Each physical object can have 'actors' who are pushing the object around. 113/// Each physical object can have 'actors' who are pushing the object around.
91/// This can be used for hover, locking axis, making vehicles, etc. 114/// This can be used for hover, locking axis, making vehicles, etc.
92/// Each physical object can have multiple actors acting on it. 115/// Each physical object can have multiple actors acting on it.
93/// 116///
94/// An actor usually registers itself with physics scene events (pre-step action) 117/// An actor usually registers itself with physics scene events (pre-step action)
95/// and modifies the parameters on the host physical object. 118/// and modifies the parameters on the host physical object.
96/// </summary> 119/// </summary>
@@ -98,7 +121,7 @@ public abstract class BSActor
98{ 121{
99 protected BSScene m_physicsScene { get; private set; } 122 protected BSScene m_physicsScene { get; private set; }
100 protected BSPhysObject m_controllingPrim { get; private set; } 123 protected BSPhysObject m_controllingPrim { get; private set; }
101 protected bool Enabled { get; set; } 124 public virtual bool Enabled { get; set; }
102 public string ActorName { get; private set; } 125 public string ActorName { get; private set; }
103 126
104 public BSActor(BSScene physicsScene, BSPhysObject pObj, string actorName) 127 public BSActor(BSScene physicsScene, BSPhysObject pObj, string actorName)
@@ -114,8 +137,10 @@ public abstract class BSActor
114 { 137 {
115 get { return Enabled; } 138 get { return Enabled; }
116 } 139 }
117 // Turn the actor on an off. 140
118 public virtual void Enable(bool setEnabled) 141 // Turn the actor on an off. Only used by ActorCollection to set all enabled/disabled.
142 // Anyone else should assign true/false to 'Enabled'.
143 public void SetEnabled(bool setEnabled)
119 { 144 {
120 Enabled = setEnabled; 145 Enabled = setEnabled;
121 } 146 }
@@ -125,7 +150,7 @@ public abstract class BSActor
125 public abstract void Refresh(); 150 public abstract void Refresh();
126 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 151 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
127 // Register a prestep action to restore physical requirements before the next simulation step. 152 // Register a prestep action to restore physical requirements before the next simulation step.
128 public abstract void RemoveBodyDependencies(); 153 public abstract void RemoveDependencies();
129 154
130} 155}
131} 156}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
index d0d9f34..be6f152 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
@@ -43,7 +43,9 @@ public enum ConstraintType : int
43 SLIDER_CONSTRAINT_TYPE, 43 SLIDER_CONSTRAINT_TYPE,
44 CONTACT_CONSTRAINT_TYPE, 44 CONTACT_CONSTRAINT_TYPE,
45 D6_SPRING_CONSTRAINT_TYPE, 45 D6_SPRING_CONSTRAINT_TYPE,
46 MAX_CONSTRAINT_TYPE 46 MAX_CONSTRAINT_TYPE, // last type defined by Bullet
47 //
48 FIXED_CONSTRAINT_TYPE = 1234 // BulletSim constraint that is fixed and unmoving
47} 49}
48 50
49// =============================================================================== 51// ===============================================================================
@@ -70,6 +72,8 @@ public enum BSPhysicsShapeType
70 SHAPE_COMPOUND = 22, 72 SHAPE_COMPOUND = 22,
71 SHAPE_HEIGHTMAP = 23, 73 SHAPE_HEIGHTMAP = 23,
72 SHAPE_AVATAR = 24, 74 SHAPE_AVATAR = 24,
75 SHAPE_CONVEXHULL= 25,
76 SHAPE_GIMPACT = 26,
73}; 77};
74 78
75// The native shapes have predefined shape hash keys 79// The native shapes have predefined shape hash keys
@@ -245,7 +249,7 @@ public enum CollisionFlags : uint
245 BS_VEHICLE_COLLISIONS = 1 << 12, // return collisions for vehicle ground checking 249 BS_VEHICLE_COLLISIONS = 1 << 12, // return collisions for vehicle ground checking
246 BS_RETURN_ROOT_COMPOUND_SHAPE = 1 << 13, // return the pos/rot of the root shape in a compound shape 250 BS_RETURN_ROOT_COMPOUND_SHAPE = 1 << 13, // return the pos/rot of the root shape in a compound shape
247 BS_NONE = 0, 251 BS_NONE = 0,
248 BS_ALL = 0xFFFFFFFF 252 BS_ALL = 0x7FFF // collision flags are a signed short
249}; 253};
250 254
251// Values f collisions groups and masks 255// Values f collisions groups and masks
@@ -261,14 +265,14 @@ public enum CollisionFilterGroups : uint
261 BDebrisGroup = 1 << 3, // 0008 265 BDebrisGroup = 1 << 3, // 0008
262 BSensorTrigger = 1 << 4, // 0010 266 BSensorTrigger = 1 << 4, // 0010
263 BCharacterGroup = 1 << 5, // 0020 267 BCharacterGroup = 1 << 5, // 0020
264 BAllGroup = 0x000FFFFF, 268 BAllGroup = 0x0007FFF, // collision flags are a signed short
265 // Filter groups defined by BulletSim 269 // Filter groups defined by BulletSim
266 BGroundPlaneGroup = 1 << 10, // 0400 270 BGroundPlaneGroup = 1 << 8, // 0400
267 BTerrainGroup = 1 << 11, // 0800 271 BTerrainGroup = 1 << 9, // 0800
268 BRaycastGroup = 1 << 12, // 1000 272 BRaycastGroup = 1 << 10, // 1000
269 BSolidGroup = 1 << 13, // 2000 273 BSolidGroup = 1 << 11, // 2000
270 // BLinksetGroup = xx // a linkset proper is either static or dynamic 274 // BLinksetGroup = xx // a linkset proper is either static or dynamic
271 BLinksetChildGroup = 1 << 14, // 4000 275 BLinksetChildGroup = 1 << 12, // 4000
272}; 276};
273 277
274// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 278// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
@@ -288,7 +292,7 @@ public enum ConstraintParamAxis : int
288 AXIS_ANGULAR_X, 292 AXIS_ANGULAR_X,
289 AXIS_ANGULAR_Y, 293 AXIS_ANGULAR_Y,
290 AXIS_ANGULAR_Z, 294 AXIS_ANGULAR_Z,
291 AXIS_LINEAR_ALL = 20, // these last three added by BulletSim so we don't have to do zillions of calls 295 AXIS_LINEAR_ALL = 20, // added by BulletSim so we don't have to do zillions of calls
292 AXIS_ANGULAR_ALL, 296 AXIS_ANGULAR_ALL,
293 AXIS_ALL 297 AXIS_ALL
294}; 298};
@@ -297,7 +301,7 @@ public abstract class BSAPITemplate
297{ 301{
298// Returns the name of the underlying Bullet engine 302// Returns the name of the underlying Bullet engine
299public abstract string BulletEngineName { get; } 303public abstract string BulletEngineName { get; }
300public abstract string BulletEngineVersion { get; protected set;} 304public abstract string BulletEngineVersion { get; protected set;}
301 305
302// Initialization and simulation 306// Initialization and simulation
303public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms, 307public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
@@ -320,11 +324,21 @@ public abstract BulletShape CreateMeshShape(BulletWorld world,
320 int indicesCount, int[] indices, 324 int indicesCount, int[] indices,
321 int verticesCount, float[] vertices ); 325 int verticesCount, float[] vertices );
322 326
327public abstract BulletShape CreateGImpactShape(BulletWorld world,
328 int indicesCount, int[] indices,
329 int verticesCount, float[] vertices );
330
323public abstract BulletShape CreateHullShape(BulletWorld world, 331public abstract BulletShape CreateHullShape(BulletWorld world,
324 int hullCount, float[] hulls); 332 int hullCount, float[] hulls);
325 333
326public abstract BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape, HACDParams parms); 334public abstract BulletShape BuildHullShapeFromMesh(BulletWorld world, BulletShape meshShape, HACDParams parms);
327 335
336public abstract BulletShape BuildConvexHullShapeFromMesh(BulletWorld world, BulletShape meshShape);
337
338public abstract BulletShape CreateConvexHullShape(BulletWorld world,
339 int indicesCount, int[] indices,
340 int verticesCount, float[] vertices );
341
328public abstract BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData); 342public abstract BulletShape BuildNativeShape(BulletWorld world, ShapeData shapeData);
329 343
330public abstract bool IsNativeShape(BulletShape shape); 344public abstract bool IsNativeShape(BulletShape shape);
@@ -366,7 +380,7 @@ public abstract void DestroyObject(BulletWorld sim, BulletBody obj);
366// ===================================================================================== 380// =====================================================================================
367public abstract BulletShape CreateGroundPlaneShape(UInt32 id, float height, float collisionMargin); 381public abstract BulletShape CreateGroundPlaneShape(UInt32 id, float height, float collisionMargin);
368 382
369public abstract BulletShape CreateTerrainShape(UInt32 id, Vector3 size, float minHeight, float maxHeight, float[] heightMap, 383public abstract BulletShape CreateTerrainShape(UInt32 id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
370 float scaleFactor, float collisionMargin); 384 float scaleFactor, float collisionMargin);
371 385
372// ===================================================================================== 386// =====================================================================================
@@ -381,7 +395,7 @@ public abstract BulletConstraint Create6DofConstraintToPoint(BulletWorld world,
381 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); 395 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
382 396
383public abstract BulletConstraint Create6DofConstraintFixed(BulletWorld world, BulletBody obj1, 397public abstract BulletConstraint Create6DofConstraintFixed(BulletWorld world, BulletBody obj1,
384 Vector3 frameInBloc, Quaternion frameInBrot, 398 Vector3 frameInBloc, Quaternion frameInBrot,
385 bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies); 399 bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies);
386 400
387public abstract BulletConstraint Create6DofSpringConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2, 401public abstract BulletConstraint Create6DofSpringConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
@@ -429,6 +443,38 @@ public abstract bool TranslationalLimitMotor(BulletConstraint constrain, float e
429 443
430public abstract bool SetBreakingImpulseThreshold(BulletConstraint constrain, float threshold); 444public abstract bool SetBreakingImpulseThreshold(BulletConstraint constrain, float threshold);
431 445
446public const int HINGE_NOT_SPECIFIED = -1;
447public abstract bool HingeSetLimits(BulletConstraint constrain, float low, float high, float softness, float bias, float relaxation);
448
449public abstract bool SpringEnable(BulletConstraint constrain, int index, float numericTrueFalse);
450
451public const int SPRING_NOT_SPECIFIED = -1;
452public abstract bool SpringSetEquilibriumPoint(BulletConstraint constrain, int index, float equilibriumPoint);
453
454public abstract bool SpringSetStiffness(BulletConstraint constrain, int index, float stiffnesss);
455
456public abstract bool SpringSetDamping(BulletConstraint constrain, int index, float damping);
457
458public const int SLIDER_LOWER_LIMIT = 0;
459public const int SLIDER_UPPER_LIMIT = 1;
460public const int SLIDER_LINEAR = 2;
461public const int SLIDER_ANGULAR = 3;
462public abstract bool SliderSetLimits(BulletConstraint constrain, int lowerUpper, int linAng, float val);
463
464public const int SLIDER_SET_SOFTNESS = 4;
465public const int SLIDER_SET_RESTITUTION = 5;
466public const int SLIDER_SET_DAMPING = 6;
467public const int SLIDER_SET_DIRECTION = 7;
468public const int SLIDER_SET_LIMIT = 8;
469public const int SLIDER_SET_ORTHO = 9;
470public abstract bool SliderSet(BulletConstraint constrain, int softRestDamp, int dirLimOrtho, int linAng, float val);
471
472public abstract bool SliderMotorEnable(BulletConstraint constrain, int linAng, float numericTrueFalse);
473
474public const int SLIDER_MOTOR_VELOCITY = 10;
475public const int SLIDER_MAX_MOTOR_FORCE = 11;
476public abstract bool SliderMotor(BulletConstraint constrain, int forceVel, int linAng, float val);
477
432public abstract bool CalculateTransforms(BulletConstraint constrain); 478public abstract bool CalculateTransforms(BulletConstraint constrain);
433 479
434public abstract bool SetConstraintParam(BulletConstraint constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis); 480public abstract bool SetConstraintParam(BulletConstraint constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
@@ -452,6 +498,8 @@ public abstract bool AddObjectToWorld(BulletWorld world, BulletBody obj);
452 498
453public abstract bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj); 499public abstract bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj);
454 500
501public abstract bool ClearCollisionProxyCache(BulletWorld world, BulletBody obj);
502
455public abstract bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects); 503public abstract bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects);
456 504
457public abstract bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain); 505public abstract bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 25be416..fc18960 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -43,15 +43,10 @@ public sealed class BSCharacter : BSPhysObject
43 private OMV.Vector3 _size; 43 private OMV.Vector3 _size;
44 private bool _grabbed; 44 private bool _grabbed;
45 private bool _selected; 45 private bool _selected;
46 private OMV.Vector3 _position;
47 private float _mass; 46 private float _mass;
48 private float _avatarVolume; 47 private float _avatarVolume;
49 private OMV.Vector3 _force;
50 private OMV.Vector3 _velocity;
51 private OMV.Vector3 _torque;
52 private float _collisionScore; 48 private float _collisionScore;
53 private OMV.Vector3 _acceleration; 49 private OMV.Vector3 _acceleration;
54 private OMV.Quaternion _orientation;
55 private int _physicsActorType; 50 private int _physicsActorType;
56 private bool _isPhysical; 51 private bool _isPhysical;
57 private bool _flying; 52 private bool _flying;
@@ -61,31 +56,26 @@ public sealed class BSCharacter : BSPhysObject
61 private OMV.Vector3 _rotationalVelocity; 56 private OMV.Vector3 _rotationalVelocity;
62 private bool _kinematic; 57 private bool _kinematic;
63 private float _buoyancy; 58 private float _buoyancy;
64 private bool _isStationaryStanding; // true is standing on a stationary object
65 59
66 private BSVMotor _velocityMotor; 60 private BSActorAvatarMove m_moveActor;
61 private const string AvatarMoveActorName = "BSCharacter.AvatarMove";
67 62
68 private OMV.Vector3 _PIDTarget; 63 private OMV.Vector3 _PIDTarget;
69 private bool _usePID; 64 private bool _usePID;
70 private float _PIDTau; 65 private float _PIDTau;
71 private bool _useHoverPID;
72 private float _PIDHoverHeight;
73 private PIDHoverType _PIDHoverType;
74 private float _PIDHoverTao;
75 66
76 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) 67 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
77 : base(parent_scene, localID, avName, "BSCharacter") 68 : base(parent_scene, localID, avName, "BSCharacter")
78 { 69 {
79 _physicsActorType = (int)ActorTypes.Agent; 70 _physicsActorType = (int)ActorTypes.Agent;
80 _position = pos; 71 RawPosition = pos;
81 72
82 _flying = isFlying; 73 _flying = isFlying;
83 _orientation = OMV.Quaternion.Identity; 74 RawOrientation = OMV.Quaternion.Identity;
84 _velocity = OMV.Vector3.Zero; 75 RawVelocity = OMV.Vector3.Zero;
85 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 76 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
86 Friction = BSParam.AvatarStandingFriction; 77 Friction = BSParam.AvatarStandingFriction;
87 Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor; 78 Density = BSParam.AvatarDensity;
88 _isStationaryStanding = false;
89 79
90 // Old versions of ScenePresence passed only the height. If width and/or depth are zero, 80 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
91 // replace with the default values. 81 // replace with the default values.
@@ -99,19 +89,26 @@ public sealed class BSCharacter : BSPhysObject
99 // set _avatarVolume and _mass based on capsule size, _density and Scale 89 // set _avatarVolume and _mass based on capsule size, _density and Scale
100 ComputeAvatarVolumeAndMass(); 90 ComputeAvatarVolumeAndMass();
101 91
102 SetupMovementMotor(); 92 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5},pos={6}",
103 93 LocalID, _size, Scale, Density, _avatarVolume, RawMass, pos);
104 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
105 LocalID, _size, Scale, Density, _avatarVolume, RawMass);
106 94
107 // do actual creation in taint time 95 // do actual creation in taint time
108 PhysicsScene.TaintedObject("BSCharacter.create", delegate() 96 PhysScene.TaintedObject(LocalID, "BSCharacter.create", delegate()
109 { 97 {
110 DetailLog("{0},BSCharacter.create,taint", LocalID); 98 DetailLog("{0},BSCharacter.create,taint", LocalID);
111 // New body and shape into PhysBody and PhysShape 99 // New body and shape into PhysBody and PhysShape
112 PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this); 100 PhysScene.Shapes.GetBodyAndShape(true, PhysScene.World, this);
101
102 // The avatar's movement is controlled by this motor that speeds up and slows down
103 // the avatar seeking to reach the motor's target speed.
104 // This motor runs as a prestep action for the avatar so it will keep the avatar
105 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
106 m_moveActor = new BSActorAvatarMove(PhysScene, this, AvatarMoveActorName);
107 PhysicalActors.Add(AvatarMoveActorName, m_moveActor);
113 108
114 SetPhysicalProperties(); 109 SetPhysicalProperties();
110
111 IsInitialized = true;
115 }); 112 });
116 return; 113 return;
117 } 114 }
@@ -119,219 +116,68 @@ public sealed class BSCharacter : BSPhysObject
119 // called when this character is being destroyed and the resources should be released 116 // called when this character is being destroyed and the resources should be released
120 public override void Destroy() 117 public override void Destroy()
121 { 118 {
119 IsInitialized = false;
120
122 base.Destroy(); 121 base.Destroy();
123 122
124 DetailLog("{0},BSCharacter.Destroy", LocalID); 123 DetailLog("{0},BSCharacter.Destroy", LocalID);
125 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() 124 PhysScene.TaintedObject(LocalID, "BSCharacter.destroy", delegate()
126 { 125 {
127 PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */); 126 PhysScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */);
128 PhysBody.Clear(); 127 PhysBody.Clear();
129 PhysicsScene.Shapes.DereferenceShape(PhysShape, null /* bodyCallback */); 128 PhysShape.Dereference(PhysScene);
130 PhysShape.Clear(); 129 PhysShape = new BSShapeNull();
131 }); 130 });
132 } 131 }
133 132
134 private void SetPhysicalProperties() 133 private void SetPhysicalProperties()
135 { 134 {
136 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 135 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
137 136
138 ZeroMotion(true); 137 ZeroMotion(true);
139 ForcePosition = _position; 138 ForcePosition = RawPosition;
140 139
141 // Set the velocity 140 // Set the velocity
142 _velocityMotor.Reset(); 141 if (m_moveActor != null)
143 _velocityMotor.SetTarget(_velocity); 142 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, false);
144 _velocityMotor.SetCurrent(_velocity); 143
145 ForceVelocity = _velocity; 144 ForceVelocity = RawVelocity;
146 145
147 // This will enable or disable the flying buoyancy of the avatar. 146 // This will enable or disable the flying buoyancy of the avatar.
148 // Needs to be reset especially when an avatar is recreated after crossing a region boundry. 147 // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
149 Flying = _flying; 148 Flying = _flying;
150 149
151 PhysicsScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution); 150 PhysScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution);
152 PhysicsScene.PE.SetMargin(PhysShape, PhysicsScene.Params.collisionMargin); 151 PhysScene.PE.SetMargin(PhysShape.physShapeInfo, PhysScene.Params.collisionMargin);
153 PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); 152 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
154 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 153 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
155 if (BSParam.CcdMotionThreshold > 0f) 154 if (BSParam.CcdMotionThreshold > 0f)
156 { 155 {
157 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 156 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
158 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 157 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
159 } 158 }
160 159
161 UpdatePhysicalMassProperties(RawMass, false); 160 UpdatePhysicalMassProperties(RawMass, false);
162 161
163 // Make so capsule does not fall over 162 // Make so capsule does not fall over
164 PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero); 163 PhysScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero);
164
165 // The avatar mover sets some parameters.
166 PhysicalActors.Refresh();
165 167
166 PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT); 168 PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT);
167 169
168 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); 170 PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody);
169 171
170 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); 172 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
171 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION); 173 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION);
172 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); 174 PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody);
173 175
174 // Do this after the object has been added to the world 176 // Do this after the object has been added to the world
175 PhysBody.collisionType = CollisionType.Avatar; 177 PhysBody.collisionType = CollisionType.Avatar;
176 PhysBody.ApplyCollisionMask(PhysicsScene); 178 PhysBody.ApplyCollisionMask(PhysScene);
177 }
178
179 // The avatar's movement is controlled by this motor that speeds up and slows down
180 // the avatar seeking to reach the motor's target speed.
181 // This motor runs as a prestep action for the avatar so it will keep the avatar
182 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
183 private void SetupMovementMotor()
184 {
185 // Infinite decay and timescale values so motor only changes current to target values.
186 _velocityMotor = new BSVMotor("BSCharacter.Velocity",
187 0.2f, // time scale
188 BSMotor.Infinite, // decay time scale
189 BSMotor.InfiniteVector, // friction timescale
190 1f // efficiency
191 );
192 // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
193
194 RegisterPreStepAction("BSCharactor.Movement", LocalID, delegate(float timeStep)
195 {
196 // TODO: Decide if the step parameters should be changed depending on the avatar's
197 // state (flying, colliding, ...). There is code in ODE to do this.
198
199 // COMMENTARY: when the user is making the avatar walk, except for falling, the velocity
200 // specified for the avatar is the one that should be used. For falling, if the avatar
201 // is not flying and is not colliding then it is presumed to be falling and the Z
202 // component is not fooled with (thus allowing gravity to do its thing).
203 // When the avatar is standing, though, the user has specified a velocity of zero and
204 // the avatar should be standing. But if the avatar is pushed by something in the world
205 // (raising elevator platform, moving vehicle, ...) the avatar should be allowed to
206 // move. Thus, the velocity cannot be forced to zero. The problem is that small velocity
207 // errors can creap in and the avatar will slowly float off in some direction.
208 // So, the problem is that, when an avatar is standing, we cannot tell creaping error
209 // from real pushing.
210 // The code below uses whether the collider is static or moving to decide whether to zero motion.
211
212 _velocityMotor.Step(timeStep);
213 _isStationaryStanding = false;
214
215 // If we're not supposed to be moving, make sure things are zero.
216 if (_velocityMotor.ErrorIsZero() && _velocityMotor.TargetValue == OMV.Vector3.Zero)
217 {
218 // The avatar shouldn't be moving
219 _velocityMotor.Zero();
220
221 if (IsColliding)
222 {
223 // If we are colliding with a stationary object, presume we're standing and don't move around
224 if (!ColliderIsMoving)
225 {
226 DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", LocalID);
227 _isStationaryStanding = true;
228 ZeroMotion(true /* inTaintTime */);
229 }
230
231 // Standing has more friction on the ground
232 if (Friction != BSParam.AvatarStandingFriction)
233 {
234 Friction = BSParam.AvatarStandingFriction;
235 PhysicsScene.PE.SetFriction(PhysBody, Friction);
236 }
237 }
238 else
239 {
240 if (Flying)
241 {
242 // Flying and not collising and velocity nearly zero.
243 ZeroMotion(true /* inTaintTime */);
244 }
245 }
246
247 DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding);
248 }
249 else
250 {
251 // Supposed to be moving.
252 OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue;
253
254 if (Friction != BSParam.AvatarFriction)
255 {
256 // Probably starting up walking. Set friction to moving friction.
257 Friction = BSParam.AvatarFriction;
258 PhysicsScene.PE.SetFriction(PhysBody, Friction);
259 }
260
261 // If falling, we keep the world's downward vector no matter what the other axis specify.
262 // The check for _velocity.Z < 0 makes jumping work (temporary upward force).
263 if (!Flying && !IsColliding)
264 {
265 if (_velocity.Z < 0)
266 stepVelocity.Z = _velocity.Z;
267 // DetailLog("{0},BSCharacter.MoveMotor,taint,overrideStepZWithWorldZ,stepVel={1}", LocalID, stepVelocity);
268 }
269
270 // 'stepVelocity' is now the speed we'd like the avatar to move in. Turn that into an instantanous force.
271 OMV.Vector3 moveForce = (stepVelocity - _velocity) * Mass;
272
273 // Should we check for move force being small and forcing velocity to zero?
274
275 // Add special movement force to allow avatars to walk up stepped surfaces.
276 moveForce += WalkUpStairs();
277
278 DetailLog("{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}", LocalID, stepVelocity, _velocity, Mass, moveForce);
279 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, moveForce);
280 }
281 });
282 } 179 }
283 180
284 // Decide if the character is colliding with a low object and compute a force to pop the
285 // avatar up so it can walk up and over the low objects.
286 private OMV.Vector3 WalkUpStairs()
287 {
288 OMV.Vector3 ret = OMV.Vector3.Zero;
289
290 // This test is done if moving forward, not flying and is colliding with something.
291 // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
292 // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
293 if (IsColliding && !Flying && TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */)
294 {
295 // The range near the character's feet where we will consider stairs
296 float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f;
297 float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
298
299 // Look for a collision point that is near the character's feet and is oriented the same as the charactor is
300 foreach (KeyValuePair<uint, ContactPoint> kvp in CollisionsLastTick.m_objCollisionList)
301 {
302 // Don't care about collisions with the terrain
303 if (kvp.Key > PhysicsScene.TerrainManager.HighestTerrainID)
304 {
305 OMV.Vector3 touchPosition = kvp.Value.Position;
306 // DetailLog("{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
307 // LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
308 if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
309 {
310 // This contact is within the 'near the feet' range.
311 // The normal should be our contact point to the object so it is pointing away
312 // thus the difference between our facing orientation and the normal should be small.
313 OMV.Vector3 directionFacing = OMV.Vector3.UnitX * RawOrientation;
314 OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
315 float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
316 if (diff < BSParam.AvatarStepApproachFactor)
317 {
318 // Found the stairs contact point. Push up a little to raise the character.
319 float upForce = (touchPosition.Z - nearFeetHeightMin) * Mass * BSParam.AvatarStepForceFactor;
320 ret = new OMV.Vector3(0f, 0f, upForce);
321
322 // Also move the avatar up for the new height
323 OMV.Vector3 displacement = new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight / 2f);
324 ForcePosition = RawPosition + displacement;
325 }
326 DetailLog("{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},faceDir={3},norm={4},diff={5},ret={6}",
327 LocalID, touchPosition, nearFeetHeightMin, directionFacing, touchNormal, diff, ret);
328 }
329 }
330 }
331 }
332
333 return ret;
334 }
335 181
336 public override void RequestPhysicsterseUpdate() 182 public override void RequestPhysicsterseUpdate()
337 { 183 {
@@ -348,6 +194,10 @@ public sealed class BSCharacter : BSPhysObject
348 } 194 }
349 195
350 set { 196 set {
197 // This is how much the avatar size is changing. Positive means getting bigger.
198 // The avatar altitude must be adjusted for this change.
199 float heightChange = value.Z - _size.Z;
200
351 _size = value; 201 _size = value;
352 // Old versions of ScenePresence passed only the height. If width and/or depth are zero, 202 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
353 // replace with the default values. 203 // replace with the default values.
@@ -359,14 +209,18 @@ public sealed class BSCharacter : BSPhysObject
359 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", 209 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
360 LocalID, _size, Scale, Density, _avatarVolume, RawMass); 210 LocalID, _size, Scale, Density, _avatarVolume, RawMass);
361 211
362 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() 212 PhysScene.TaintedObject(LocalID, "BSCharacter.setSize", delegate()
363 { 213 {
364 if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape) 214 if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape)
365 { 215 {
366 PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); 216 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
367 UpdatePhysicalMassProperties(RawMass, true); 217 UpdatePhysicalMassProperties(RawMass, true);
218
219 // Adjust the avatar's position to account for the increase/decrease in size
220 ForcePosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, RawPosition.Z + heightChange / 2f);
221
368 // Make sure this change appears as a property update event 222 // Make sure this change appears as a property update event
369 PhysicsScene.PE.PushUpdate(PhysBody); 223 PhysScene.PE.PushUpdate(PhysBody);
370 } 224 }
371 }); 225 });
372 226
@@ -377,11 +231,6 @@ public sealed class BSCharacter : BSPhysObject
377 { 231 {
378 set { BaseShape = value; } 232 set { BaseShape = value; }
379 } 233 }
380 // I want the physics engine to make an avatar capsule
381 public override BSPhysicsShapeType PreferredPhysicalShape
382 {
383 get {return BSPhysicsShapeType.SHAPE_CAPSULE; }
384 }
385 234
386 public override bool Grabbed { 235 public override bool Grabbed {
387 set { _grabbed = value; } 236 set { _grabbed = value; }
@@ -403,29 +252,29 @@ public sealed class BSCharacter : BSPhysObject
403 // Called at taint time! 252 // Called at taint time!
404 public override void ZeroMotion(bool inTaintTime) 253 public override void ZeroMotion(bool inTaintTime)
405 { 254 {
406 _velocity = OMV.Vector3.Zero; 255 RawVelocity = OMV.Vector3.Zero;
407 _acceleration = OMV.Vector3.Zero; 256 _acceleration = OMV.Vector3.Zero;
408 _rotationalVelocity = OMV.Vector3.Zero; 257 _rotationalVelocity = OMV.Vector3.Zero;
409 258
410 // Zero some other properties directly into the physics engine 259 // Zero some other properties directly into the physics engine
411 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() 260 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate()
412 { 261 {
413 if (PhysBody.HasPhysicalBody) 262 if (PhysBody.HasPhysicalBody)
414 PhysicsScene.PE.ClearAllForces(PhysBody); 263 PhysScene.PE.ClearAllForces(PhysBody);
415 }); 264 });
416 } 265 }
417 public override void ZeroAngularMotion(bool inTaintTime) 266 public override void ZeroAngularMotion(bool inTaintTime)
418 { 267 {
419 _rotationalVelocity = OMV.Vector3.Zero; 268 _rotationalVelocity = OMV.Vector3.Zero;
420 269
421 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() 270 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate()
422 { 271 {
423 if (PhysBody.HasPhysicalBody) 272 if (PhysBody.HasPhysicalBody)
424 { 273 {
425 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero); 274 PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero);
426 PhysicsScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero); 275 PhysScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero);
427 // The next also get rid of applied linear force but the linear velocity is untouched. 276 // The next also get rid of applied linear force but the linear velocity is untouched.
428 PhysicsScene.PE.ClearForces(PhysBody); 277 PhysScene.PE.ClearForces(PhysBody);
429 } 278 }
430 }); 279 });
431 } 280 }
@@ -433,38 +282,33 @@ public sealed class BSCharacter : BSPhysObject
433 282
434 public override void LockAngularMotion(OMV.Vector3 axis) { return; } 283 public override void LockAngularMotion(OMV.Vector3 axis) { return; }
435 284
436 public override OMV.Vector3 RawPosition
437 {
438 get { return _position; }
439 set { _position = value; }
440 }
441 public override OMV.Vector3 Position { 285 public override OMV.Vector3 Position {
442 get { 286 get {
443 // Don't refetch the position because this function is called a zillion times 287 // Don't refetch the position because this function is called a zillion times
444 // _position = PhysicsScene.PE.GetObjectPosition(Scene.World, LocalID); 288 // RawPosition = PhysicsScene.PE.GetObjectPosition(Scene.World, LocalID);
445 return _position; 289 return RawPosition;
446 } 290 }
447 set { 291 set {
448 _position = value; 292 RawPosition = value;
449 293
450 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() 294 PhysScene.TaintedObject(LocalID, "BSCharacter.setPosition", delegate()
451 { 295 {
452 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 296 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
453 PositionSanityCheck(); 297 PositionSanityCheck();
454 ForcePosition = _position; 298 ForcePosition = RawPosition;
455 }); 299 });
456 } 300 }
457 } 301 }
458 public override OMV.Vector3 ForcePosition { 302 public override OMV.Vector3 ForcePosition {
459 get { 303 get {
460 _position = PhysicsScene.PE.GetPosition(PhysBody); 304 RawPosition = PhysScene.PE.GetPosition(PhysBody);
461 return _position; 305 return RawPosition;
462 } 306 }
463 set { 307 set {
464 _position = value; 308 RawPosition = value;
465 if (PhysBody.HasPhysicalBody) 309 if (PhysBody.HasPhysicalBody)
466 { 310 {
467 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 311 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
468 } 312 }
469 } 313 }
470 } 314 }
@@ -478,30 +322,30 @@ public sealed class BSCharacter : BSPhysObject
478 bool ret = false; 322 bool ret = false;
479 323
480 // TODO: check for out of bounds 324 // TODO: check for out of bounds
481 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) 325 if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
482 { 326 {
483 // The character is out of the known/simulated area. 327 // The character is out of the known/simulated area.
484 // Force the avatar position to be within known. ScenePresence will use the position 328 // Force the avatar position to be within known. ScenePresence will use the position
485 // plus the velocity to decide if the avatar is moving out of the region. 329 // plus the velocity to decide if the avatar is moving out of the region.
486 RawPosition = PhysicsScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition); 330 RawPosition = PhysScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition);
487 DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition); 331 DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition);
488 return true; 332 return true;
489 } 333 }
490 334
491 // If below the ground, move the avatar up 335 // If below the ground, move the avatar up
492 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); 336 float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
493 if (Position.Z < terrainHeight) 337 if (Position.Z < terrainHeight)
494 { 338 {
495 DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, _position, terrainHeight); 339 DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, RawPosition, terrainHeight);
496 _position.Z = terrainHeight + BSParam.AvatarBelowGroundUpCorrectionMeters; 340 RawPosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, terrainHeight + BSParam.AvatarBelowGroundUpCorrectionMeters);
497 ret = true; 341 ret = true;
498 } 342 }
499 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 343 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
500 { 344 {
501 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); 345 float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
502 if (Position.Z < waterHeight) 346 if (Position.Z < waterHeight)
503 { 347 {
504 _position.Z = waterHeight; 348 RawPosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, waterHeight);
505 ret = true; 349 ret = true;
506 } 350 }
507 } 351 }
@@ -519,10 +363,10 @@ public sealed class BSCharacter : BSPhysObject
519 { 363 {
520 // The new position value must be pushed into the physics engine but we can't 364 // The new position value must be pushed into the physics engine but we can't
521 // just assign to "Position" because of potential call loops. 365 // just assign to "Position" because of potential call loops.
522 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() 366 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.PositionSanityCheck", delegate()
523 { 367 {
524 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 368 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
525 ForcePosition = _position; 369 ForcePosition = RawPosition;
526 }); 370 });
527 ret = true; 371 ret = true;
528 } 372 }
@@ -532,25 +376,25 @@ public sealed class BSCharacter : BSPhysObject
532 public override float Mass { get { return _mass; } } 376 public override float Mass { get { return _mass; } }
533 377
534 // used when we only want this prim's mass and not the linkset thing 378 // used when we only want this prim's mass and not the linkset thing
535 public override float RawMass { 379 public override float RawMass {
536 get {return _mass; } 380 get {return _mass; }
537 } 381 }
538 public override void UpdatePhysicalMassProperties(float physMass, bool inWorld) 382 public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
539 { 383 {
540 OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); 384 OMV.Vector3 localInertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
541 PhysicsScene.PE.SetMassProps(PhysBody, physMass, localInertia); 385 PhysScene.PE.SetMassProps(PhysBody, physMass, localInertia);
542 } 386 }
543 387
544 public override OMV.Vector3 Force { 388 public override OMV.Vector3 Force {
545 get { return _force; } 389 get { return RawForce; }
546 set { 390 set {
547 _force = value; 391 RawForce = value;
548 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 392 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
549 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() 393 PhysScene.TaintedObject(LocalID, "BSCharacter.SetForce", delegate()
550 { 394 {
551 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); 395 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce);
552 if (PhysBody.HasPhysicalBody) 396 if (PhysBody.HasPhysicalBody)
553 PhysicsScene.PE.SetObjectForce(PhysBody, _force); 397 PhysScene.PE.SetObjectForce(PhysBody, RawForce);
554 }); 398 });
555 } 399 }
556 } 400 }
@@ -564,6 +408,7 @@ public sealed class BSCharacter : BSPhysObject
564 408
565 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 409 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
566 public override void SetVolumeDetect(int param) { return; } 410 public override void SetVolumeDetect(int param) { return; }
411 public override bool IsVolumeDetect { get { return false; } }
567 412
568 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } 413 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
569 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } 414 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
@@ -573,61 +418,49 @@ public sealed class BSCharacter : BSPhysObject
573 { 418 {
574 get 419 get
575 { 420 {
576 return m_targetVelocity; 421 return base.m_targetVelocity;
577 } 422 }
578 set 423 set
579 { 424 {
580 DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value); 425 DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value);
581 m_targetVelocity = value; 426 m_targetVelocity = value;
582 OMV.Vector3 targetVel = value; 427 OMV.Vector3 targetVel = value;
583 if (_setAlwaysRun) 428 if (_setAlwaysRun && !_flying)
584 targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f); 429 targetVel *= new OMV.Vector3(BSParam.AvatarAlwaysRunFactor, BSParam.AvatarAlwaysRunFactor, 0f);
585 430
586 PhysicsScene.TaintedObject("BSCharacter.setTargetVelocity", delegate() 431 if (m_moveActor != null)
587 { 432 m_moveActor.SetVelocityAndTarget(RawVelocity, targetVel, false /* inTaintTime */);
588 _velocityMotor.Reset();
589 _velocityMotor.SetTarget(targetVel);
590 _velocityMotor.SetCurrent(_velocity);
591 _velocityMotor.Enabled = true;
592 });
593 } 433 }
594 } 434 }
595 public override OMV.Vector3 RawVelocity
596 {
597 get { return _velocity; }
598 set { _velocity = value; }
599 }
600 // Directly setting velocity means this is what the user really wants now. 435 // Directly setting velocity means this is what the user really wants now.
601 public override OMV.Vector3 Velocity { 436 public override OMV.Vector3 Velocity {
602 get { return _velocity; } 437 get { return RawVelocity; }
603 set { 438 set {
604 _velocity = value; 439 RawVelocity = value;
605 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 440 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity);
606 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() 441 PhysScene.TaintedObject(LocalID, "BSCharacter.setVelocity", delegate()
607 { 442 {
608 _velocityMotor.Reset(); 443 if (m_moveActor != null)
609 _velocityMotor.SetCurrent(_velocity); 444 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */);
610 _velocityMotor.SetTarget(_velocity);
611 _velocityMotor.Enabled = false;
612 445
613 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); 446 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, RawVelocity);
614 ForceVelocity = _velocity; 447 ForceVelocity = RawVelocity;
615 }); 448 });
616 } 449 }
617 } 450 }
618 public override OMV.Vector3 ForceVelocity { 451 public override OMV.Vector3 ForceVelocity {
619 get { return _velocity; } 452 get { return RawVelocity; }
620 set { 453 set {
621 PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); 454 PhysScene.AssertInTaintTime("BSCharacter.ForceVelocity");
622 455
623 _velocity = value; 456 RawVelocity = value;
624 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); 457 PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
625 PhysicsScene.PE.Activate(PhysBody, true); 458 PhysScene.PE.Activate(PhysBody, true);
626 } 459 }
627 } 460 }
628 public override OMV.Vector3 Torque { 461 public override OMV.Vector3 Torque {
629 get { return _torque; } 462 get { return RawTorque; }
630 set { _torque = value; 463 set { RawTorque = value;
631 } 464 }
632 } 465 }
633 public override float CollisionScore { 466 public override float CollisionScore {
@@ -639,22 +472,27 @@ public sealed class BSCharacter : BSPhysObject
639 get { return _acceleration; } 472 get { return _acceleration; }
640 set { _acceleration = value; } 473 set { _acceleration = value; }
641 } 474 }
642 public override OMV.Quaternion RawOrientation
643 {
644 get { return _orientation; }
645 set { _orientation = value; }
646 }
647 public override OMV.Quaternion Orientation { 475 public override OMV.Quaternion Orientation {
648 get { return _orientation; } 476 get { return RawOrientation; }
649 set { 477 set {
650 // Orientation is set zillions of times when an avatar is walking. It's like 478 // Orientation is set zillions of times when an avatar is walking. It's like
651 // the viewer doesn't trust us. 479 // the viewer doesn't trust us.
652 if (_orientation != value) 480 if (RawOrientation != value)
653 { 481 {
654 _orientation = value; 482 RawOrientation = value;
655 PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() 483 PhysScene.TaintedObject(LocalID, "BSCharacter.setOrientation", delegate()
656 { 484 {
657 ForceOrientation = _orientation; 485 // Bullet assumes we know what we are doing when forcing orientation
486 // so it lets us go against all the rules and just compensates for them later.
487 // This forces rotation to be only around the Z axis and doesn't change any of the other axis.
488 // This keeps us from flipping the capsule over which the veiwer does not understand.
489 float oRoll, oPitch, oYaw;
490 RawOrientation.GetEulerAngles(out oRoll, out oPitch, out oYaw);
491 OMV.Quaternion trimmedOrientation = OMV.Quaternion.CreateFromEulers(0f, 0f, oYaw);
492 // DetailLog("{0},BSCharacter.setOrientation,taint,val={1},valDir={2},conv={3},convDir={4}",
493 // LocalID, RawOrientation, OMV.Vector3.UnitX * RawOrientation,
494 // trimmedOrientation, OMV.Vector3.UnitX * trimmedOrientation);
495 ForceOrientation = trimmedOrientation;
658 }); 496 });
659 } 497 }
660 } 498 }
@@ -664,16 +502,16 @@ public sealed class BSCharacter : BSPhysObject
664 { 502 {
665 get 503 get
666 { 504 {
667 _orientation = PhysicsScene.PE.GetOrientation(PhysBody); 505 RawOrientation = PhysScene.PE.GetOrientation(PhysBody);
668 return _orientation; 506 return RawOrientation;
669 } 507 }
670 set 508 set
671 { 509 {
672 _orientation = value; 510 RawOrientation = value;
673 if (PhysBody.HasPhysicalBody) 511 if (PhysBody.HasPhysicalBody)
674 { 512 {
675 // _position = PhysicsScene.PE.GetPosition(BSBody); 513 // RawPosition = PhysicsScene.PE.GetPosition(BSBody);
676 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 514 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
677 } 515 }
678 } 516 }
679 } 517 }
@@ -722,14 +560,14 @@ public sealed class BSCharacter : BSPhysObject
722 public override bool FloatOnWater { 560 public override bool FloatOnWater {
723 set { 561 set {
724 _floatOnWater = value; 562 _floatOnWater = value;
725 PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() 563 PhysScene.TaintedObject(LocalID, "BSCharacter.setFloatOnWater", delegate()
726 { 564 {
727 if (PhysBody.HasPhysicalBody) 565 if (PhysBody.HasPhysicalBody)
728 { 566 {
729 if (_floatOnWater) 567 if (_floatOnWater)
730 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 568 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
731 else 569 else
732 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 570 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
733 } 571 }
734 }); 572 });
735 } 573 }
@@ -750,7 +588,7 @@ public sealed class BSCharacter : BSPhysObject
750 public override float Buoyancy { 588 public override float Buoyancy {
751 get { return _buoyancy; } 589 get { return _buoyancy; }
752 set { _buoyancy = value; 590 set { _buoyancy = value;
753 PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() 591 PhysScene.TaintedObject(LocalID, "BSCharacter.setBuoyancy", delegate()
754 { 592 {
755 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 593 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
756 ForceBuoyancy = _buoyancy; 594 ForceBuoyancy = _buoyancy;
@@ -759,8 +597,8 @@ public sealed class BSCharacter : BSPhysObject
759 } 597 }
760 public override float ForceBuoyancy { 598 public override float ForceBuoyancy {
761 get { return _buoyancy; } 599 get { return _buoyancy; }
762 set { 600 set {
763 PhysicsScene.AssertInTaintTime("BSCharacter.ForceBuoyancy"); 601 PhysScene.AssertInTaintTime("BSCharacter.ForceBuoyancy");
764 602
765 _buoyancy = value; 603 _buoyancy = value;
766 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 604 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
@@ -768,7 +606,7 @@ public sealed class BSCharacter : BSPhysObject
768 float grav = BSParam.Gravity * (1f - _buoyancy); 606 float grav = BSParam.Gravity * (1f - _buoyancy);
769 Gravity = new OMV.Vector3(0f, 0f, grav); 607 Gravity = new OMV.Vector3(0f, 0f, grav);
770 if (PhysBody.HasPhysicalBody) 608 if (PhysBody.HasPhysicalBody)
771 PhysicsScene.PE.SetGravity(PhysBody, Gravity); 609 PhysScene.PE.SetGravity(PhysBody, Gravity);
772 } 610 }
773 } 611 }
774 612
@@ -783,46 +621,25 @@ public sealed class BSCharacter : BSPhysObject
783 set { _PIDTau = value; } 621 set { _PIDTau = value; }
784 } 622 }
785 623
786 // Used for llSetHoverHeight and maybe vehicle height
787 // Hover Height will override MoveTo target's Z
788 public override bool PIDHoverActive {
789 set { _useHoverPID = value; }
790 }
791 public override float PIDHoverHeight {
792 set { _PIDHoverHeight = value; }
793 }
794 public override PIDHoverType PIDHoverType {
795 set { _PIDHoverType = value; }
796 }
797 public override float PIDHoverTau {
798 set { _PIDHoverTao = value; }
799 }
800
801 // For RotLookAt
802 public override OMV.Quaternion APIDTarget { set { return; } }
803 public override bool APIDActive { set { return; } }
804 public override float APIDStrength { set { return; } }
805 public override float APIDDamping { set { return; } }
806
807 public override void AddForce(OMV.Vector3 force, bool pushforce) 624 public override void AddForce(OMV.Vector3 force, bool pushforce)
808 { 625 {
809 // Since this force is being applied in only one step, make this a force per second. 626 // Since this force is being applied in only one step, make this a force per second.
810 OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep; 627 OMV.Vector3 addForce = force / PhysScene.LastTimeStep;
811 AddForce(addForce, pushforce, false); 628 AddForce(addForce, pushforce, false);
812 } 629 }
813 private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 630 public override void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
814 if (force.IsFinite()) 631 if (force.IsFinite())
815 { 632 {
816 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 633 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
817 // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); 634 // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce);
818 635
819 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate() 636 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.AddForce", delegate()
820 { 637 {
821 // Bullet adds this central force to the total force for this tick 638 // Bullet adds this central force to the total force for this tick
822 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce); 639 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce);
823 if (PhysBody.HasPhysicalBody) 640 if (PhysBody.HasPhysicalBody)
824 { 641 {
825 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); 642 PhysScene.PE.ApplyCentralForce(PhysBody, addForce);
826 } 643 }
827 }); 644 });
828 } 645 }
@@ -833,7 +650,7 @@ public sealed class BSCharacter : BSPhysObject
833 } 650 }
834 } 651 }
835 652
836 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 653 public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
837 } 654 }
838 public override void SetMomentum(OMV.Vector3 momentum) { 655 public override void SetMomentum(OMV.Vector3 momentum) {
839 } 656 }
@@ -841,14 +658,14 @@ public sealed class BSCharacter : BSPhysObject
841 private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size) 658 private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size)
842 { 659 {
843 OMV.Vector3 newScale; 660 OMV.Vector3 newScale;
844 661
845 // Bullet's capsule total height is the "passed height + radius * 2"; 662 // Bullet's capsule total height is the "passed height + radius * 2";
846 // The base capsule is 1 diameter and 2 height (passed radius=0.5, passed height = 1) 663 // The base capsule is 1 unit in diameter and 2 units in height (passed radius=0.5, passed height = 1)
847 // The number we pass in for 'scaling' is the multiplier to get that base 664 // The number we pass in for 'scaling' is the multiplier to get that base
848 // shape to be the size desired. 665 // shape to be the size desired.
849 // So, when creating the scale for the avatar height, we take the passed height 666 // So, when creating the scale for the avatar height, we take the passed height
850 // (size.Z) and remove the caps. 667 // (size.Z) and remove the caps.
851 // Another oddity of the Bullet capsule implementation is that it presumes the Y 668 // An oddity of the Bullet capsule implementation is that it presumes the Y
852 // dimension is the radius of the capsule. Even though some of the code allows 669 // dimension is the radius of the capsule. Even though some of the code allows
853 // for a asymmetrical capsule, other parts of the code presume it is cylindrical. 670 // for a asymmetrical capsule, other parts of the code presume it is cylindrical.
854 671
@@ -856,12 +673,36 @@ public sealed class BSCharacter : BSPhysObject
856 newScale.X = size.X / 2f; 673 newScale.X = size.X / 2f;
857 newScale.Y = size.Y / 2f; 674 newScale.Y = size.Y / 2f;
858 675
676 float heightAdjust = BSParam.AvatarHeightMidFudge;
677 if (BSParam.AvatarHeightLowFudge != 0f || BSParam.AvatarHeightHighFudge != 0f)
678 {
679 const float AVATAR_LOW = 1.1f;
680 const float AVATAR_MID = 1.775f; // 1.87f
681 const float AVATAR_HI = 2.45f;
682 // An avatar is between 1.1 and 2.45 meters. Midpoint is 1.775m.
683 float midHeightOffset = size.Z - AVATAR_MID;
684 if (midHeightOffset < 0f)
685 {
686 // Small avatar. Add the adjustment based on the distance from midheight
687 heightAdjust += ((-1f * midHeightOffset) / (AVATAR_MID - AVATAR_LOW)) * BSParam.AvatarHeightLowFudge;
688 }
689 else
690 {
691 // Large avatar. Add the adjustment based on the distance from midheight
692 heightAdjust += ((midHeightOffset) / (AVATAR_HI - AVATAR_MID)) * BSParam.AvatarHeightHighFudge;
693 }
694 }
859 // The total scale height is the central cylindar plus the caps on the two ends. 695 // The total scale height is the central cylindar plus the caps on the two ends.
860 newScale.Z = (size.Z + (Math.Min(size.X, size.Y) * 2)) / 2f; 696 newScale.Z = (size.Z + (Math.Min(size.X, size.Y) * 2) + heightAdjust) / 2f;
697 // m_log.DebugFormat("{0} ComputeAvatarScale: size={1},adj={2},scale={3}", LogHeader, size, heightAdjust, newScale);
698
861 // If smaller than the endcaps, just fake like we're almost that small 699 // If smaller than the endcaps, just fake like we're almost that small
862 if (newScale.Z < 0) 700 if (newScale.Z < 0)
863 newScale.Z = 0.1f; 701 newScale.Z = 0.1f;
864 702
703 DetailLog("{0},BSCharacter.ComputerAvatarScale,size={1},lowF={2},midF={3},hiF={4},adj={5},newScale={6}",
704 LocalID, size, BSParam.AvatarHeightLowFudge, BSParam.AvatarHeightMidFudge, BSParam.AvatarHeightHighFudge, heightAdjust, newScale);
705
865 return newScale; 706 return newScale;
866 } 707 }
867 708
@@ -886,18 +727,18 @@ public sealed class BSCharacter : BSPhysObject
886 // the world that things have changed. 727 // the world that things have changed.
887 public override void UpdateProperties(EntityProperties entprop) 728 public override void UpdateProperties(EntityProperties entprop)
888 { 729 {
889 // Don't change position if standing on a stationary object. 730 // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator.
890 if (!_isStationaryStanding) 731 TriggerPreUpdatePropertyAction(ref entprop);
891 _position = entprop.Position;
892 732
893 _orientation = entprop.Rotation; 733 RawPosition = entprop.Position;
734 RawOrientation = entprop.Rotation;
894 735
895 // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar 736 // Smooth velocity. OpenSimulator is VERY sensitive to changes in velocity of the avatar
896 // and will send agent updates to the clients if velocity changes by more than 737 // and will send agent updates to the clients if velocity changes by more than
897 // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many 738 // 0.001m/s. Bullet introduces a lot of jitter in the velocity which causes many
898 // extra updates. 739 // extra updates.
899 if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f)) 740 if (!entprop.Velocity.ApproxEquals(RawVelocity, 0.1f))
900 _velocity = entprop.Velocity; 741 RawVelocity = entprop.Velocity;
901 742
902 _acceleration = entprop.Acceleration; 743 _acceleration = entprop.Acceleration;
903 _rotationalVelocity = entprop.RotationalVelocity; 744 _rotationalVelocity = entprop.RotationalVelocity;
@@ -905,8 +746,8 @@ public sealed class BSCharacter : BSPhysObject
905 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. 746 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
906 if (PositionSanityCheck(true)) 747 if (PositionSanityCheck(true))
907 { 748 {
908 DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, _position); 749 DetailLog("{0},BSCharacter.UpdateProperties,updatePosForSanity,pos={1}", LocalID, RawPosition);
909 entprop.Position = _position; 750 entprop.Position = RawPosition;
910 } 751 }
911 752
912 // remember the current and last set values 753 // remember the current and last set values
@@ -917,10 +758,10 @@ public sealed class BSCharacter : BSPhysObject
917 // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); 758 // Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
918 759
919 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. 760 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
920 // base.RequestPhysicsterseUpdate(); 761 // PhysScene.PostUpdate(this);
921 762
922 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 763 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
923 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 764 LocalID, RawPosition, RawOrientation, RawVelocity, _acceleration, _rotationalVelocity);
924 } 765 }
925} 766}
926} 767}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index 42b5c49..b47e9a8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -64,7 +64,7 @@ public abstract class BSConstraint : IDisposable
64 { 64 {
65 bool success = PhysicsScene.PE.DestroyConstraint(m_world, m_constraint); 65 bool success = PhysicsScene.PE.DestroyConstraint(m_world, m_constraint);
66 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", 66 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
67 BSScene.DetailLogZero, 67 m_body1.ID,
68 m_body1.ID, m_body1.AddrString, 68 m_body1.ID, m_body1.AddrString,
69 m_body2.ID, m_body2.AddrString, 69 m_body2.ID, m_body2.AddrString,
70 success); 70 success);
@@ -77,7 +77,10 @@ public abstract class BSConstraint : IDisposable
77 { 77 {
78 bool ret = false; 78 bool ret = false;
79 if (m_enabled) 79 if (m_enabled)
80 {
81 m_world.physicsScene.DetailLog("{0},BSConstraint.SetLinearLimits,taint,low={1},high={2}", m_body1.ID, low, high);
80 ret = PhysicsScene.PE.SetLinearLimits(m_constraint, low, high); 82 ret = PhysicsScene.PE.SetLinearLimits(m_constraint, low, high);
83 }
81 return ret; 84 return ret;
82 } 85 }
83 86
@@ -86,6 +89,7 @@ public abstract class BSConstraint : IDisposable
86 bool ret = false; 89 bool ret = false;
87 if (m_enabled) 90 if (m_enabled)
88 { 91 {
92 m_world.physicsScene.DetailLog("{0},BSConstraint.SetAngularLimits,taint,low={1},high={2}", m_body1.ID, low, high);
89 ret = PhysicsScene.PE.SetAngularLimits(m_constraint, low, high); 93 ret = PhysicsScene.PE.SetAngularLimits(m_constraint, low, high);
90 } 94 }
91 return ret; 95 return ret;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
index d0949f5..7fcb75c 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
@@ -32,12 +32,19 @@ using OpenMetaverse;
32namespace OpenSim.Region.Physics.BulletSPlugin 32namespace OpenSim.Region.Physics.BulletSPlugin
33{ 33{
34 34
35public sealed class BSConstraint6Dof : BSConstraint 35public class BSConstraint6Dof : BSConstraint
36{ 36{
37 private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; 37 private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]";
38 38
39 public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } 39 public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } }
40 40
41 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2) :base(world)
42 {
43 m_body1 = obj1;
44 m_body2 = obj2;
45 m_enabled = false;
46 }
47
41 // Create a btGeneric6DofConstraint 48 // Create a btGeneric6DofConstraint
42 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2, 49 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
43 Vector3 frame1, Quaternion frame1rot, 50 Vector3 frame1, Quaternion frame1rot,
@@ -52,9 +59,11 @@ public sealed class BSConstraint6Dof : BSConstraint
52 frame2, frame2rot, 59 frame2, frame2rot,
53 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies); 60 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
54 m_enabled = true; 61 m_enabled = true;
55 world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", 62 PhysicsScene.DetailLog("{0},BS6DofConstraint,create,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
56 BSScene.DetailLogZero, world.worldID, 63 m_body1.ID, world.worldID,
57 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString); 64 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
65 PhysicsScene.DetailLog("{0},BS6DofConstraint,create, f1Loc={1},f1Rot={2},f2Loc={3},f2Rot={4},usefA={5},disCol={6}",
66 m_body1.ID, frame1, frame1rot, frame2, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
58 } 67 }
59 68
60 // 6 Dof constraint based on a midpoint between the two constrained bodies 69 // 6 Dof constraint based on a midpoint between the two constrained bodies
@@ -79,9 +88,11 @@ public sealed class BSConstraint6Dof : BSConstraint
79 m_constraint = PhysicsScene.PE.Create6DofConstraintToPoint(m_world, m_body1, m_body2, 88 m_constraint = PhysicsScene.PE.Create6DofConstraintToPoint(m_world, m_body1, m_body2,
80 joinPoint, 89 joinPoint,
81 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies); 90 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
91
82 PhysicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", 92 PhysicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}",
83 BSScene.DetailLogZero, world.worldID, m_constraint.AddrString, 93 m_body1.ID, world.worldID, m_constraint.AddrString,
84 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString); 94 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
95
85 if (!m_constraint.HasPhysicalConstraint) 96 if (!m_constraint.HasPhysicalConstraint)
86 { 97 {
87 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", 98 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}",
@@ -106,8 +117,10 @@ public sealed class BSConstraint6Dof : BSConstraint
106 frameInBloc, frameInBrot, 117 frameInBloc, frameInBrot,
107 useLinearReferenceFrameB, disableCollisionsBetweenLinkedBodies); 118 useLinearReferenceFrameB, disableCollisionsBetweenLinkedBodies);
108 m_enabled = true; 119 m_enabled = true;
109 world.physicsScene.DetailLog("{0},BS6DofConstraint,createFixed,wID={1},rID={2},rBody={3}", 120 PhysicsScene.DetailLog("{0},BS6DofConstraint,createFixed,wID={1},rID={2},rBody={3}",
110 BSScene.DetailLogZero, world.worldID, obj1.ID, obj1.AddrString); 121 m_body1.ID, world.worldID, obj1.ID, obj1.AddrString);
122 PhysicsScene.DetailLog("{0},BS6DofConstraint,createFixed, fBLoc={1},fBRot={2},usefA={3},disCol={4}",
123 m_body1.ID, frameInBloc, frameInBrot, useLinearReferenceFrameB, disableCollisionsBetweenLinkedBodies);
111 } 124 }
112 125
113 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) 126 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs
new file mode 100755
index 0000000..7a76a9a
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs
@@ -0,0 +1,54 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public sealed class BSConstraintConeTwist : BSConstraint
36{
37 public override ConstraintType Type { get { return ConstraintType.CONETWIST_CONSTRAINT_TYPE; } }
38
39 public BSConstraintConeTwist(BulletWorld world, BulletBody obj1, BulletBody obj2,
40 Vector3 frameInAloc, Quaternion frameInArot,
41 Vector3 frameInBloc, Quaternion frameInBrot,
42 bool disableCollisionsBetweenLinkedBodies)
43 : base(world)
44 {
45 m_body1 = obj1;
46 m_body2 = obj2;
47 m_constraint = PhysicsScene.PE.CreateConeTwistConstraint(world, obj1, obj2,
48 frameInAloc, frameInArot, frameInBloc, frameInBrot,
49 disableCollisionsBetweenLinkedBodies);
50 m_enabled = true;
51 }
52}
53
54}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
index 7714a03..ed89f63 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
@@ -45,7 +45,7 @@ public sealed class BSConstraintHinge : BSConstraint
45 m_body1 = obj1; 45 m_body1 = obj1;
46 m_body2 = obj2; 46 m_body2 = obj2;
47 m_constraint = PhysicsScene.PE.CreateHingeConstraint(world, obj1, obj2, 47 m_constraint = PhysicsScene.PE.CreateHingeConstraint(world, obj1, obj2,
48 pivotInA, pivotInB, axisInA, axisInB, 48 pivotInA, pivotInB, axisInA, axisInB,
49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies); 49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
50 m_enabled = true; 50 m_enabled = true;
51 } 51 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs
new file mode 100755
index 0000000..37cfa07
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs
@@ -0,0 +1,55 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public sealed class BSConstraintSlider : BSConstraint
36{
37 public override ConstraintType Type { get { return ConstraintType.SLIDER_CONSTRAINT_TYPE; } }
38
39 public BSConstraintSlider(BulletWorld world, BulletBody obj1, BulletBody obj2,
40 Vector3 frameInAloc, Quaternion frameInArot,
41 Vector3 frameInBloc, Quaternion frameInBrot,
42 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
43 : base(world)
44 {
45 m_body1 = obj1;
46 m_body2 = obj2;
47 m_constraint = PhysicsScene.PE.CreateSliderConstraint(world, obj1, obj2,
48 frameInAloc, frameInArot, frameInBloc, frameInBrot,
49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
50 m_enabled = true;
51 }
52
53}
54
55}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs
new file mode 100755
index 0000000..8e7ddff
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs
@@ -0,0 +1,103 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public sealed class BSConstraintSpring : BSConstraint6Dof
36{
37 public override ConstraintType Type { get { return ConstraintType.D6_SPRING_CONSTRAINT_TYPE; } }
38
39 public BSConstraintSpring(BulletWorld world, BulletBody obj1, BulletBody obj2,
40 Vector3 frame1Loc, Quaternion frame1Rot,
41 Vector3 frame2Loc, Quaternion frame2Rot,
42 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
43 :base(world, obj1, obj2)
44 {
45 m_constraint = PhysicsScene.PE.Create6DofSpringConstraint(world, obj1, obj2,
46 frame1Loc, frame1Rot, frame2Loc, frame2Rot,
47 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
48 m_enabled = true;
49
50 PhysicsScene.DetailLog("{0},BSConstraintSpring,create,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
51 obj1.ID, world.worldID, obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
52 PhysicsScene.DetailLog("{0},BSConstraintSpring,create, f1Loc={1},f1Rot={2},f2Loc={3},f2Rot={4},usefA={5},disCol={6}",
53 m_body1.ID, frame1Loc, frame1Rot, frame2Loc, frame2Rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
54 }
55
56 public bool SetAxisEnable(int pIndex, bool pAxisEnable)
57 {
58 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetEnable,obj1ID={1},obj2ID={2},indx={3},enable={4}",
59 m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pAxisEnable);
60 PhysicsScene.PE.SpringEnable(m_constraint, pIndex, BSParam.NumericBool(pAxisEnable));
61 return true;
62 }
63
64 public bool SetStiffness(int pIndex, float pStiffness)
65 {
66 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetStiffness,obj1ID={1},obj2ID={2},indx={3},stiff={4}",
67 m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pStiffness);
68 PhysicsScene.PE.SpringSetStiffness(m_constraint, pIndex, pStiffness);
69 return true;
70 }
71
72 public bool SetDamping(int pIndex, float pDamping)
73 {
74 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetDamping,obj1ID={1},obj2ID={2},indx={3},damp={4}",
75 m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pDamping);
76 PhysicsScene.PE.SpringSetDamping(m_constraint, pIndex, pDamping);
77 return true;
78 }
79
80 public bool SetEquilibriumPoint(int pIndex, float pEqPoint)
81 {
82 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetEquilibriumPoint,obj1ID={1},obj2ID={2},indx={3},eqPoint={4}",
83 m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pEqPoint);
84 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, pIndex, pEqPoint);
85 return true;
86 }
87
88 public bool SetEquilibriumPoint(Vector3 linearEq, Vector3 angularEq)
89 {
90 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetEquilibriumPoint,obj1ID={1},obj2ID={2},linearEq={3},angularEq={4}",
91 m_body1.ID, m_body1.ID, m_body2.ID, linearEq, angularEq);
92 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 0, linearEq.X);
93 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 1, linearEq.Y);
94 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 2, linearEq.Z);
95 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 3, angularEq.X);
96 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 4, angularEq.Y);
97 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 5, angularEq.Z);
98 return true;
99 }
100
101}
102
103} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 0fd1f73..7b98f9d 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
45 private static string LogHeader = "[BULLETSIM VEHICLE]"; 45 private static string LogHeader = "[BULLETSIM VEHICLE]";
46 46
47 // the prim this dynamic controller belongs to 47 // the prim this dynamic controller belongs to
48 private BSPrim ControllingPrim { get; set; } 48 private BSPrimLinkable ControllingPrim { get; set; }
49 49
50 private bool m_haveRegisteredForSceneEvents; 50 private bool m_haveRegisteredForSceneEvents;
51 51
@@ -125,33 +125,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
125 static readonly float PIOverFour = ((float)Math.PI) / 4f; 125 static readonly float PIOverFour = ((float)Math.PI) / 4f;
126 static readonly float PIOverTwo = ((float)Math.PI) / 2f; 126 static readonly float PIOverTwo = ((float)Math.PI) / 2f;
127 127
128 // For debugging, flags to turn on and off individual corrections.
129 public bool enableAngularVerticalAttraction;
130 public bool enableAngularDeflection;
131 public bool enableAngularBanking;
132
133 public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName) 128 public BSDynamics(BSScene myScene, BSPrim myPrim, string actorName)
134 : base(myScene, myPrim, actorName) 129 : base(myScene, myPrim, actorName)
135 { 130 {
136 ControllingPrim = myPrim;
137 Type = Vehicle.TYPE_NONE; 131 Type = Vehicle.TYPE_NONE;
138 m_haveRegisteredForSceneEvents = false; 132 m_haveRegisteredForSceneEvents = false;
139 SetupVehicleDebugging();
140 }
141 133
142 // Stopgap debugging enablement. Allows source level debugging but still checking 134 ControllingPrim = myPrim as BSPrimLinkable;
143 // in changes by making enablement of debugging flags from INI file. 135 if (ControllingPrim == null)
144 public void SetupVehicleDebugging()
145 {
146 enableAngularVerticalAttraction = true;
147 enableAngularDeflection = false;
148 enableAngularBanking = true;
149 if (BSParam.VehicleDebuggingEnabled)
150 { 136 {
151 enableAngularVerticalAttraction = true; 137 // THIS CANNOT HAPPEN!!
152 enableAngularDeflection = false;
153 enableAngularBanking = false;
154 } 138 }
139 VDetailLog("{0},Creation", ControllingPrim.LocalID);
155 } 140 }
156 141
157 // Return 'true' if this vehicle is doing vehicle things 142 // Return 'true' if this vehicle is doing vehicle things
@@ -173,7 +158,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
173 switch (pParam) 158 switch (pParam)
174 { 159 {
175 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: 160 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
176 m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); 161 m_angularDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
177 break; 162 break;
178 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: 163 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
179 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); 164 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
@@ -209,7 +194,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
209 m_VhoverTimescale = Math.Max(pValue, 0.01f); 194 m_VhoverTimescale = Math.Max(pValue, 0.01f);
210 break; 195 break;
211 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: 196 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
212 m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); 197 m_linearDeflectionEfficiency = ClampInRange(0f, pValue, 1f);
213 break; 198 break;
214 case Vehicle.LINEAR_DEFLECTION_TIMESCALE: 199 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
215 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); 200 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
@@ -235,7 +220,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
235 // set all of the components to the same value 220 // set all of the components to the same value
236 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 221 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
237 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); 222 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
238 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
239 break; 223 break;
240 case Vehicle.ANGULAR_MOTOR_DIRECTION: 224 case Vehicle.ANGULAR_MOTOR_DIRECTION:
241 m_angularMotorDirection = new Vector3(pValue, pValue, pValue); 225 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
@@ -244,7 +228,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
244 break; 228 break;
245 case Vehicle.LINEAR_FRICTION_TIMESCALE: 229 case Vehicle.LINEAR_FRICTION_TIMESCALE:
246 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); 230 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
247 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
248 break; 231 break;
249 case Vehicle.LINEAR_MOTOR_DIRECTION: 232 case Vehicle.LINEAR_MOTOR_DIRECTION:
250 m_linearMotorDirection = new Vector3(pValue, pValue, pValue); 233 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
@@ -265,7 +248,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
265 { 248 {
266 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 249 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
267 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 250 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
268 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
269 break; 251 break;
270 case Vehicle.ANGULAR_MOTOR_DIRECTION: 252 case Vehicle.ANGULAR_MOTOR_DIRECTION:
271 // Limit requested angular speed to 2 rps= 4 pi rads/sec 253 // Limit requested angular speed to 2 rps= 4 pi rads/sec
@@ -278,7 +260,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
278 break; 260 break;
279 case Vehicle.LINEAR_FRICTION_TIMESCALE: 261 case Vehicle.LINEAR_FRICTION_TIMESCALE:
280 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 262 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
281 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
282 break; 263 break;
283 case Vehicle.LINEAR_MOTOR_DIRECTION: 264 case Vehicle.LINEAR_MOTOR_DIRECTION:
284 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); 265 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
@@ -559,25 +540,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
559 break; 540 break;
560 } 541 }
561 542
562 // Update any physical parameters based on this type. 543 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, 1f);
563 Refresh(); 544 // m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
564
565 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale,
566 m_linearMotorDecayTimescale, m_linearFrictionTimescale,
567 1f);
568 m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
569 545
570 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, 546 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f);
571 m_angularMotorDecayTimescale, m_angularFrictionTimescale, 547 // m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
572 1f);
573 m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
574 548
575 /* Not implemented 549 /* Not implemented
576 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale, 550 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
577 BSMotor.Infinite, BSMotor.InfiniteVector, 551 BSMotor.Infinite, BSMotor.InfiniteVector,
578 m_verticalAttractionEfficiency); 552 m_verticalAttractionEfficiency);
579 // Z goes away and we keep X and Y 553 // Z goes away and we keep X and Y
580 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
581 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging) 554 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
582 */ 555 */
583 556
@@ -589,6 +562,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
589 { 562 {
590 RegisterForSceneEvents(); 563 RegisterForSceneEvents();
591 } 564 }
565
566 // Update any physical parameters based on this type.
567 Refresh();
592 } 568 }
593 #endregion // Vehicle parameter setting 569 #endregion // Vehicle parameter setting
594 570
@@ -596,6 +572,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
596 public override void Refresh() 572 public override void Refresh()
597 { 573 {
598 // If asking for a refresh, reset the physical parameters before the next simulation step. 574 // If asking for a refresh, reset the physical parameters before the next simulation step.
575 // Called whether active or not since the active state may be updated before the next step.
599 m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate() 576 m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate()
600 { 577 {
601 SetPhysicalParameters(); 578 SetPhysicalParameters();
@@ -612,8 +589,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
612 m_vehicleMass = ControllingPrim.TotalMass; 589 m_vehicleMass = ControllingPrim.TotalMass;
613 590
614 // Friction affects are handled by this vehicle code 591 // Friction affects are handled by this vehicle code
615 m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction); 592 // m_physicsScene.PE.SetFriction(ControllingPrim.PhysBody, BSParam.VehicleFriction);
616 m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution); 593 // m_physicsScene.PE.SetRestitution(ControllingPrim.PhysBody, BSParam.VehicleRestitution);
594 ControllingPrim.Linkset.SetPhysicalFriction(BSParam.VehicleFriction);
595 ControllingPrim.Linkset.SetPhysicalRestitution(BSParam.VehicleRestitution);
617 596
618 // Moderate angular movement introduced by Bullet. 597 // Moderate angular movement introduced by Bullet.
619 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle. 598 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
@@ -623,17 +602,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin
623 m_physicsScene.PE.SetAngularFactorV(ControllingPrim.PhysBody, BSParam.VehicleAngularFactor); 602 m_physicsScene.PE.SetAngularFactorV(ControllingPrim.PhysBody, BSParam.VehicleAngularFactor);
624 603
625 // Vehicles report collision events so we know when it's on the ground 604 // Vehicles report collision events so we know when it's on the ground
626 m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); 605 // m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
606 ControllingPrim.Linkset.AddToPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS);
627 607
628 ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape, m_vehicleMass); 608 // Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass);
629 m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); 609 // ControllingPrim.Inertia = inertia * BSParam.VehicleInertiaFactor;
630 m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody); 610 // m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia);
611 // m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody);
612 ControllingPrim.Linkset.ComputeAndSetLocalInertia(BSParam.VehicleInertiaFactor, m_vehicleMass);
631 613
632 // Set the gravity for the vehicle depending on the buoyancy 614 // Set the gravity for the vehicle depending on the buoyancy
633 // TODO: what should be done if prim and vehicle buoyancy differ? 615 // TODO: what should be done if prim and vehicle buoyancy differ?
634 m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy); 616 m_VehicleGravity = ControllingPrim.ComputeGravity(m_VehicleBuoyancy);
635 // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same. 617 // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same.
636 m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero); 618 // m_physicsScene.PE.SetGravity(ControllingPrim.PhysBody, Vector3.Zero);
619 ControllingPrim.Linkset.SetPhysicalGravity(Vector3.Zero);
637 620
638 VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}", 621 VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}",
639 ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity, 622 ControllingPrim.LocalID, m_vehicleMass, ControllingPrim.Inertia, m_VehicleGravity,
@@ -645,11 +628,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
645 { 628 {
646 if (ControllingPrim.PhysBody.HasPhysicalBody) 629 if (ControllingPrim.PhysBody.HasPhysicalBody)
647 m_physicsScene.PE.RemoveFromCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); 630 m_physicsScene.PE.RemoveFromCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
631 // ControllingPrim.Linkset.RemoveFromPhysicalCollisionFlags(CollisionFlags.BS_VEHICLE_COLLISIONS);
648 } 632 }
649 } 633 }
650 634
651 // BSActor.RemoveBodyDependencies 635 // BSActor.RemoveBodyDependencies
652 public override void RemoveBodyDependencies() 636 public override void RemoveDependencies()
653 { 637 {
654 Refresh(); 638 Refresh();
655 } 639 }
@@ -657,6 +641,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
657 // BSActor.Release() 641 // BSActor.Release()
658 public override void Dispose() 642 public override void Dispose()
659 { 643 {
644 VDetailLog("{0},Dispose", ControllingPrim.LocalID);
660 UnregisterForSceneEvents(); 645 UnregisterForSceneEvents();
661 Type = Vehicle.TYPE_NONE; 646 Type = Vehicle.TYPE_NONE;
662 Enabled = false; 647 Enabled = false;
@@ -714,7 +699,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
714 private Vector3 m_knownRotationalVelocity; 699 private Vector3 m_knownRotationalVelocity;
715 private Vector3 m_knownRotationalForce; 700 private Vector3 m_knownRotationalForce;
716 private Vector3 m_knownRotationalImpulse; 701 private Vector3 m_knownRotationalImpulse;
717 private Vector3 m_knownForwardVelocity; // vehicle relative forward speed
718 702
719 private const int m_knownChangedPosition = 1 << 0; 703 private const int m_knownChangedPosition = 1 << 0;
720 private const int m_knownChangedVelocity = 1 << 1; 704 private const int m_knownChangedVelocity = 1 << 1;
@@ -726,7 +710,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
726 private const int m_knownChangedRotationalImpulse = 1 << 7; 710 private const int m_knownChangedRotationalImpulse = 1 << 7;
727 private const int m_knownChangedTerrainHeight = 1 << 8; 711 private const int m_knownChangedTerrainHeight = 1 << 8;
728 private const int m_knownChangedWaterLevel = 1 << 9; 712 private const int m_knownChangedWaterLevel = 1 << 9;
729 private const int m_knownChangedForwardVelocity = 1 <<10;
730 713
731 public void ForgetKnownVehicleProperties() 714 public void ForgetKnownVehicleProperties()
732 { 715 {
@@ -783,13 +766,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
783 766
784 // Since the computation of terrain height can be a little involved, this routine 767 // Since the computation of terrain height can be a little involved, this routine
785 // is used to fetch the height only once for each vehicle simulation step. 768 // is used to fetch the height only once for each vehicle simulation step.
786 Vector3 lastRememberedHeightPos; 769 Vector3 lastRememberedHeightPos = new Vector3(-1, -1, -1);
787 private float GetTerrainHeight(Vector3 pos) 770 private float GetTerrainHeight(Vector3 pos)
788 { 771 {
789 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos) 772 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos)
790 { 773 {
791 lastRememberedHeightPos = pos; 774 lastRememberedHeightPos = pos;
792 m_knownTerrainHeight = ControllingPrim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); 775 m_knownTerrainHeight = ControllingPrim.PhysScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
793 m_knownHas |= m_knownChangedTerrainHeight; 776 m_knownHas |= m_knownChangedTerrainHeight;
794 } 777 }
795 return m_knownTerrainHeight; 778 return m_knownTerrainHeight;
@@ -797,14 +780,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
797 780
798 // Since the computation of water level can be a little involved, this routine 781 // Since the computation of water level can be a little involved, this routine
799 // is used ot fetch the level only once for each vehicle simulation step. 782 // is used ot fetch the level only once for each vehicle simulation step.
783 Vector3 lastRememberedWaterHeightPos = new Vector3(-1, -1, -1);
800 private float GetWaterLevel(Vector3 pos) 784 private float GetWaterLevel(Vector3 pos)
801 { 785 {
802 if ((m_knownHas & m_knownChangedWaterLevel) == 0) 786 if ((m_knownHas & m_knownChangedWaterLevel) == 0 || pos != lastRememberedWaterHeightPos)
803 { 787 {
804 m_knownWaterLevel = ControllingPrim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); 788 lastRememberedWaterHeightPos = pos;
789 m_knownWaterLevel = ControllingPrim.PhysScene.TerrainManager.GetWaterLevelAtXYZ(pos);
805 m_knownHas |= m_knownChangedWaterLevel; 790 m_knownHas |= m_knownChangedWaterLevel;
806 } 791 }
807 return (float)m_knownWaterLevel; 792 return m_knownWaterLevel;
808 } 793 }
809 794
810 private Vector3 VehiclePosition 795 private Vector3 VehiclePosition
@@ -930,14 +915,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
930 { 915 {
931 get 916 get
932 { 917 {
933 if ((m_knownHas & m_knownChangedForwardVelocity) == 0) 918 return VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
934 {
935 m_knownForwardVelocity = VehicleVelocity * Quaternion.Inverse(Quaternion.Normalize(VehicleOrientation));
936 m_knownHas |= m_knownChangedForwardVelocity;
937 }
938 return m_knownForwardVelocity;
939 } 919 }
940 } 920 }
921
941 private float VehicleForwardSpeed 922 private float VehicleForwardSpeed
942 { 923 {
943 get 924 get
@@ -988,6 +969,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
988 { 969 {
989 ComputeLinearVelocity(pTimestep); 970 ComputeLinearVelocity(pTimestep);
990 971
972 ComputeLinearDeflection(pTimestep);
973
991 ComputeLinearTerrainHeightCorrection(pTimestep); 974 ComputeLinearTerrainHeightCorrection(pTimestep);
992 975
993 ComputeLinearHover(pTimestep); 976 ComputeLinearHover(pTimestep);
@@ -1003,11 +986,17 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1003 { 986 {
1004 Vector3 vel = VehicleVelocity; 987 Vector3 vel = VehicleVelocity;
1005 if ((m_flags & (VehicleFlag.NO_X)) != 0) 988 if ((m_flags & (VehicleFlag.NO_X)) != 0)
989 {
1006 vel.X = 0; 990 vel.X = 0;
991 }
1007 if ((m_flags & (VehicleFlag.NO_Y)) != 0) 992 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
993 {
1008 vel.Y = 0; 994 vel.Y = 0;
995 }
1009 if ((m_flags & (VehicleFlag.NO_Z)) != 0) 996 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
997 {
1010 vel.Z = 0; 998 vel.Z = 0;
999 }
1011 VehicleVelocity = vel; 1000 VehicleVelocity = vel;
1012 } 1001 }
1013 1002
@@ -1019,13 +1008,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1019 Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG 1008 Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG
1020 VehicleVelocity /= VehicleVelocity.Length(); 1009 VehicleVelocity /= VehicleVelocity.Length();
1021 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity; 1010 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity;
1022 VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}", 1011 VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}",
1023 ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity); 1012 ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity);
1024 } 1013 }
1025 else if (newVelocityLengthSq < 0.001f) 1014 else if (newVelocityLengthSq < 0.001f)
1026 VehicleVelocity = Vector3.Zero; 1015 VehicleVelocity = Vector3.Zero;
1027 1016
1028 VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", ControllingPrim.LocalID, ControllingPrim.IsColliding, VehicleVelocity ); 1017 VDetailLog("{0}, MoveLinear,done,isColl={1},newVel={2}", ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, VehicleVelocity );
1029 1018
1030 } // end MoveLinear() 1019 } // end MoveLinear()
1031 1020
@@ -1033,9 +1022,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1033 { 1022 {
1034 // Step the motor from the current value. Get the correction needed this step. 1023 // Step the motor from the current value. Get the correction needed this step.
1035 Vector3 origVelW = VehicleVelocity; // DEBUG 1024 Vector3 origVelW = VehicleVelocity; // DEBUG
1036 Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); 1025 Vector3 currentVelV = VehicleForwardVelocity;
1037 Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); 1026 Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV);
1038 1027
1028 // Friction reduces vehicle motion based on absolute speed. Slow vehicle down by friction.
1029 Vector3 frictionFactorV = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep);
1030 linearMotorCorrectionV -= (currentVelV * frictionFactorV);
1031
1039 // Motor is vehicle coordinates. Rotate it to world coordinates 1032 // Motor is vehicle coordinates. Rotate it to world coordinates
1040 Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; 1033 Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation;
1041 1034
@@ -1049,8 +1042,49 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1049 // Add this correction to the velocity to make it faster/slower. 1042 // Add this correction to the velocity to make it faster/slower.
1050 VehicleVelocity += linearMotorVelocityW; 1043 VehicleVelocity += linearMotorVelocityW;
1051 1044
1052 VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5}", 1045 VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},tgt={3},correctV={4},correctW={5},newVelW={6},fricFact={7}",
1053 ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, linearMotorVelocityW, VehicleVelocity); 1046 ControllingPrim.LocalID, origVelW, currentVelV, m_linearMotor.TargetValue, linearMotorCorrectionV,
1047 linearMotorVelocityW, VehicleVelocity, frictionFactorV);
1048 }
1049
1050 //Given a Deflection Effiency and a Velocity, Returns a Velocity that is Partially Deflected onto the X Axis
1051 //Clamped so that a DeflectionTimescale of less then 1 does not increase force over original velocity
1052 private void ComputeLinearDeflection(float pTimestep)
1053 {
1054 Vector3 linearDeflectionV = Vector3.Zero;
1055 Vector3 velocityV = VehicleForwardVelocity;
1056
1057 if (BSParam.VehicleEnableLinearDeflection)
1058 {
1059 // Velocity in Y and Z dimensions is movement to the side or turning.
1060 // Compute deflection factor from the to the side and rotational velocity
1061 linearDeflectionV.Y = SortedClampInRange(0, (velocityV.Y * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Y);
1062 linearDeflectionV.Z = SortedClampInRange(0, (velocityV.Z * m_linearDeflectionEfficiency) / m_linearDeflectionTimescale, velocityV.Z);
1063
1064 // Velocity to the side and around is corrected and moved into the forward direction
1065 linearDeflectionV.X += Math.Abs(linearDeflectionV.Y);
1066 linearDeflectionV.X += Math.Abs(linearDeflectionV.Z);
1067
1068 // Scale the deflection to the fractional simulation time
1069 linearDeflectionV *= pTimestep;
1070
1071 // Subtract the sideways and rotational velocity deflection factors while adding the correction forward
1072 linearDeflectionV *= new Vector3(1, -1, -1);
1073
1074 // Correction is vehicle relative. Convert to world coordinates.
1075 Vector3 linearDeflectionW = linearDeflectionV * VehicleOrientation;
1076
1077 // Optionally, if not colliding, don't effect world downward velocity. Let falling things fall.
1078 if (BSParam.VehicleLinearDeflectionNotCollidingNoZ && !m_controllingPrim.HasSomeCollision)
1079 {
1080 linearDeflectionW.Z = 0f;
1081 }
1082
1083 VehicleVelocity += linearDeflectionW;
1084
1085 VDetailLog("{0}, MoveLinear,LinearDeflection,linDefEff={1},linDefTS={2},linDeflectionV={3}",
1086 ControllingPrim.LocalID, m_linearDeflectionEfficiency, m_linearDeflectionTimescale, linearDeflectionV);
1087 }
1054 } 1088 }
1055 1089
1056 public void ComputeLinearTerrainHeightCorrection(float pTimestep) 1090 public void ComputeLinearTerrainHeightCorrection(float pTimestep)
@@ -1087,14 +1121,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1087 { 1121 {
1088 m_VhoverTargetHeight = m_VhoverHeight; 1122 m_VhoverTargetHeight = m_VhoverHeight;
1089 } 1123 }
1090
1091 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) 1124 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
1092 { 1125 {
1093 // If body is already heigher, use its height as target height 1126 // If body is already heigher, use its height as target height
1094 if (VehiclePosition.Z > m_VhoverTargetHeight) 1127 if (VehiclePosition.Z > m_VhoverTargetHeight)
1128 {
1095 m_VhoverTargetHeight = VehiclePosition.Z; 1129 m_VhoverTargetHeight = VehiclePosition.Z;
1130
1131 // A 'misfeature' of this flag is that if the vehicle is above it's hover height,
1132 // the vehicle's buoyancy goes away. This is an SL bug that got used by so many
1133 // scripts that it could not be changed.
1134 // So, if above the height, reapply gravity if buoyancy had it turned off.
1135 if (m_VehicleBuoyancy != 0)
1136 {
1137 Vector3 appliedGravity = ControllingPrim.ComputeGravity(ControllingPrim.Buoyancy) * m_vehicleMass;
1138 VehicleAddForce(appliedGravity);
1139 }
1140 }
1096 } 1141 }
1097 1142
1098 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 1143 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
1099 { 1144 {
1100 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) 1145 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f)
@@ -1136,7 +1181,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1136 m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight, 1181 m_VhoverTimescale, m_VhoverHeight, m_VhoverTargetHeight,
1137 verticalError, verticalCorrection); 1182 verticalError, verticalCorrection);
1138 } 1183 }
1139
1140 } 1184 }
1141 } 1185 }
1142 1186
@@ -1188,7 +1232,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1188 // used with conjunction with banking: the strength of the banking will decay when the 1232 // used with conjunction with banking: the strength of the banking will decay when the
1189 // vehicle no longer experiences collisions. The decay timescale is the same as 1233 // vehicle no longer experiences collisions. The decay timescale is the same as
1190 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering 1234 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
1191 // when they are in mid jump. 1235 // when they are in mid jump.
1192 // TODO: this code is wrong. Also, what should it do for boats (height from water)? 1236 // TODO: this code is wrong. Also, what should it do for boats (height from water)?
1193 // This is just using the ground and a general collision check. Should really be using 1237 // This is just using the ground and a general collision check. Should really be using
1194 // a downward raycast to find what is below. 1238 // a downward raycast to find what is below.
@@ -1201,7 +1245,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1201 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition); 1245 float targetHeight = Type == Vehicle.TYPE_BOAT ? GetWaterLevel(VehiclePosition) : GetTerrainHeight(VehiclePosition);
1202 distanceAboveGround = VehiclePosition.Z - targetHeight; 1246 distanceAboveGround = VehiclePosition.Z - targetHeight;
1203 // Not colliding if the vehicle is off the ground 1247 // Not colliding if the vehicle is off the ground
1204 if (!Prim.IsColliding) 1248 if (!Prim.HasSomeCollision)
1205 { 1249 {
1206 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 1250 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
1207 VehicleVelocity += new Vector3(0, 0, -distanceAboveGround); 1251 VehicleVelocity += new Vector3(0, 0, -distanceAboveGround);
@@ -1212,12 +1256,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1212 // be computed with a motor. 1256 // be computed with a motor.
1213 // TODO: add interaction with banking. 1257 // TODO: add interaction with banking.
1214 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}", 1258 VDetailLog("{0}, MoveLinear,limitMotorUp,distAbove={1},colliding={2},ret={3}",
1215 Prim.LocalID, distanceAboveGround, Prim.IsColliding, ret); 1259 Prim.LocalID, distanceAboveGround, Prim.HasSomeCollision, ret);
1216 */ 1260 */
1217 1261
1218 // Another approach is to measure if we're going up. If going up and not colliding, 1262 // Another approach is to measure if we're going up. If going up and not colliding,
1219 // the vehicle is in the air. Fix that by pushing down. 1263 // the vehicle is in the air. Fix that by pushing down.
1220 if (!ControllingPrim.IsColliding && VehicleVelocity.Z > 0.1) 1264 if (!ControllingPrim.HasSomeCollision && VehicleVelocity.Z > 0.1)
1221 { 1265 {
1222 // Get rid of any of the velocity vector that is pushing us up. 1266 // Get rid of any of the velocity vector that is pushing us up.
1223 float upVelocity = VehicleVelocity.Z; 1267 float upVelocity = VehicleVelocity.Z;
@@ -1239,7 +1283,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1239 } 1283 }
1240 */ 1284 */
1241 VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}", 1285 VDetailLog("{0}, MoveLinear,limitMotorUp,collide={1},upVel={2},newVel={3}",
1242 ControllingPrim.LocalID, ControllingPrim.IsColliding, upVelocity, VehicleVelocity); 1286 ControllingPrim.LocalID, ControllingPrim.HasSomeCollision, upVelocity, VehicleVelocity);
1243 } 1287 }
1244 } 1288 }
1245 } 1289 }
@@ -1249,14 +1293,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1249 Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass; 1293 Vector3 appliedGravity = m_VehicleGravity * m_vehicleMass;
1250 1294
1251 // Hack to reduce downward force if the vehicle is probably sitting on the ground 1295 // Hack to reduce downward force if the vehicle is probably sitting on the ground
1252 if (ControllingPrim.IsColliding && IsGroundVehicle) 1296 if (ControllingPrim.HasSomeCollision && IsGroundVehicle)
1253 appliedGravity *= BSParam.VehicleGroundGravityFudge; 1297 appliedGravity *= BSParam.VehicleGroundGravityFudge;
1254 1298
1255 VehicleAddForce(appliedGravity); 1299 VehicleAddForce(appliedGravity);
1256 1300
1257 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={3}", 1301 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={5}",
1258 ControllingPrim.LocalID, m_VehicleGravity, 1302 ControllingPrim.LocalID, m_VehicleGravity,
1259 ControllingPrim.IsColliding, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity); 1303 ControllingPrim.HasSomeCollision, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity);
1260 } 1304 }
1261 1305
1262 // ======================================================================= 1306 // =======================================================================
@@ -1323,6 +1367,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1323 private void ComputeAngularTurning(float pTimestep) 1367 private void ComputeAngularTurning(float pTimestep)
1324 { 1368 {
1325 // The user wants this many radians per second angular change? 1369 // The user wants this many radians per second angular change?
1370 Vector3 origVehicleRotationalVelocity = VehicleRotationalVelocity; // DEBUG DEBUG
1326 Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation); 1371 Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation);
1327 Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV); 1372 Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV);
1328 1373
@@ -1330,18 +1375,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1330 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : 1375 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
1331 // This flag prevents linear deflection parallel to world z-axis. This is useful 1376 // This flag prevents linear deflection parallel to world z-axis. This is useful
1332 // for preventing ground vehicles with large linear deflection, like bumper cars, 1377 // for preventing ground vehicles with large linear deflection, like bumper cars,
1333 // from climbing their linear deflection into the sky. 1378 // from climbing their linear deflection into the sky.
1334 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement 1379 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
1335 // TODO: This is here because this is where ODE put it but documentation says it 1380 // TODO: This is here because this is where ODE put it but documentation says it
1336 // is a linear effect. Where should this check go? 1381 // is a linear effect. Where should this check go?
1337 //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) 1382 //if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
1338 // { 1383 // {
1339 // angularMotorContributionV.X = 0f; 1384 // angularMotorContributionV.X = 0f;
1340 // angularMotorContributionV.Y = 0f; 1385 // angularMotorContributionV.Y = 0f;
1341 // } 1386 // }
1387
1388 // Reduce any velocity by friction.
1389 Vector3 frictionFactorW = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep);
1390 angularMotorContributionV -= (currentAngularV * frictionFactorW);
1391
1392 Vector3 angularMotorContributionW = angularMotorContributionV * VehicleOrientation;
1393 VehicleRotationalVelocity += angularMotorContributionW;
1342 1394
1343 VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; 1395 VDetailLog("{0}, MoveAngular,angularTurning,curAngVelV={1},origVehRotVel={2},vehRotVel={3},frictFact={4}, angContribV={5},angContribW={6}",
1344 VDetailLog("{0}, MoveAngular,angularTurning,angularMotorContrib={1}", ControllingPrim.LocalID, angularMotorContributionV); 1396 ControllingPrim.LocalID, currentAngularV, origVehicleRotationalVelocity, VehicleRotationalVelocity, frictionFactorW, angularMotorContributionV, angularMotorContributionW);
1345 } 1397 }
1346 1398
1347 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: 1399 // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial:
@@ -1356,86 +1408,136 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1356 { 1408 {
1357 1409
1358 // If vertical attaction timescale is reasonable 1410 // If vertical attaction timescale is reasonable
1359 if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1411 if (BSParam.VehicleEnableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1360 { 1412 {
1361 // Possible solution derived from a discussion at: 1413 Vector3 vehicleUpAxis = Vector3.UnitZ * VehicleOrientation;
1362 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no 1414 switch (BSParam.VehicleAngularVerticalAttractionAlgorithm)
1363
1364 // Create a rotation that is only the vehicle's rotation around Z
1365 Vector3 currentEuler = Vector3.Zero;
1366 VehicleOrientation.GetEulerAngles(out currentEuler.X, out currentEuler.Y, out currentEuler.Z);
1367 Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEuler.Z);
1368
1369 // Create the axis that is perpendicular to the up vector and the rotated up vector.
1370 Vector3 differenceAxis = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
1371 // Compute the angle between those to vectors.
1372 double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
1373 // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
1374
1375 // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
1376 // TODO: add 'efficiency'.
1377 differenceAngle /= m_verticalAttractionTimescale;
1378
1379 // Create the quaterian representing the correction angle
1380 Quaternion correctionRotation = Quaternion.CreateFromAxisAngle(differenceAxis, (float)differenceAngle);
1381
1382 // Turn that quaternion into Euler values to make it into velocities to apply.
1383 Vector3 vertContributionV = Vector3.Zero;
1384 correctionRotation.GetEulerAngles(out vertContributionV.X, out vertContributionV.Y, out vertContributionV.Z);
1385 vertContributionV *= -1f;
1386
1387 VehicleRotationalVelocity += vertContributionV;
1388
1389 VDetailLog("{0}, MoveAngular,verticalAttraction,diffAxis={1},diffAng={2},corrRot={3},contrib={4}",
1390 ControllingPrim.LocalID,
1391 differenceAxis,
1392 differenceAngle,
1393 correctionRotation,
1394 vertContributionV);
1395
1396 // ===================================================================
1397 /*
1398 Vector3 vertContributionV = Vector3.Zero;
1399 Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
1400
1401 // Take a vector pointing up and convert it from world to vehicle relative coords.
1402 Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
1403
1404 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
1405 // is now:
1406 // leaning to one side: rotated around the X axis with the Y value going
1407 // from zero (nearly straight up) to one (completely to the side)) or
1408 // leaning front-to-back: rotated around the Y axis with the value of X being between
1409 // zero and one.
1410 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1411
1412 // Y error means needed rotation around X axis and visa versa.
1413 // Since the error goes from zero to one, the asin is the corresponding angle.
1414 vertContributionV.X = (float)Math.Asin(verticalError.Y);
1415 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1416 vertContributionV.Y = -(float)Math.Asin(verticalError.X);
1417
1418 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1419 if (verticalError.Z < 0f)
1420 { 1415 {
1421 vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour; 1416 case 0:
1422 // vertContribution.Y -= PIOverFour; 1417 {
1418 //Another formula to try got from :
1419 //http://answers.unity3d.com/questions/10425/how-to-stabilize-angular-motion-alignment-of-hover.html
1420
1421 // Flipping what was originally a timescale into a speed variable and then multiplying it by 2
1422 // since only computing half the distance between the angles.
1423 float verticalAttractionSpeed = (1 / m_verticalAttractionTimescale) * 2.0f;
1424
1425 // Make a prediction of where the up axis will be when this is applied rather then where it is now as
1426 // this makes for a smoother adjustment and less fighting between the various forces.
1427 Vector3 predictedUp = vehicleUpAxis * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
1428
1429 // This is only half the distance to the target so it will take 2 seconds to complete the turn.
1430 Vector3 torqueVector = Vector3.Cross(predictedUp, Vector3.UnitZ);
1431
1432 // Scale vector by our timescale since it is an acceleration it is r/s^2 or radians a timescale squared
1433 Vector3 vertContributionV = torqueVector * verticalAttractionSpeed * verticalAttractionSpeed;
1434
1435 VehicleRotationalVelocity += vertContributionV;
1436
1437 VDetailLog("{0}, MoveAngular,verticalAttraction,vertAttrSpeed={1},upAxis={2},PredictedUp={3},torqueVector={4},contrib={5}",
1438 ControllingPrim.LocalID,
1439 verticalAttractionSpeed,
1440 vehicleUpAxis,
1441 predictedUp,
1442 torqueVector,
1443 vertContributionV);
1444 break;
1445 }
1446 case 1:
1447 {
1448 // Possible solution derived from a discussion at:
1449 // http://stackoverflow.com/questions/14939657/computing-vector-from-quaternion-works-computing-quaternion-from-vector-does-no
1450
1451 // Create a rotation that is only the vehicle's rotation around Z
1452 Vector3 currentEulerW = Vector3.Zero;
1453 VehicleOrientation.GetEulerAngles(out currentEulerW.X, out currentEulerW.Y, out currentEulerW.Z);
1454 Quaternion justZOrientation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, currentEulerW.Z);
1455
1456 // Create the axis that is perpendicular to the up vector and the rotated up vector.
1457 Vector3 differenceAxisW = Vector3.Cross(Vector3.UnitZ * justZOrientation, Vector3.UnitZ * VehicleOrientation);
1458 // Compute the angle between those to vectors.
1459 double differenceAngle = Math.Acos((double)Vector3.Dot(Vector3.UnitZ, Vector3.Normalize(Vector3.UnitZ * VehicleOrientation)));
1460 // 'differenceAngle' is the angle to rotate and 'differenceAxis' is the plane to rotate in to get the vehicle vertical
1461
1462 // Reduce the change by the time period it is to change in. Timestep is handled when velocity is applied.
1463 // TODO: add 'efficiency'.
1464 // differenceAngle /= m_verticalAttractionTimescale;
1465
1466 // Create the quaterian representing the correction angle
1467 Quaternion correctionRotationW = Quaternion.CreateFromAxisAngle(differenceAxisW, (float)differenceAngle);
1468
1469 // Turn that quaternion into Euler values to make it into velocities to apply.
1470 Vector3 vertContributionW = Vector3.Zero;
1471 correctionRotationW.GetEulerAngles(out vertContributionW.X, out vertContributionW.Y, out vertContributionW.Z);
1472 vertContributionW *= -1f;
1473 vertContributionW /= m_verticalAttractionTimescale;
1474
1475 VehicleRotationalVelocity += vertContributionW;
1476
1477 VDetailLog("{0}, MoveAngular,verticalAttraction,upAxis={1},diffAxis={2},diffAng={3},corrRot={4},contrib={5}",
1478 ControllingPrim.LocalID,
1479 vehicleUpAxis,
1480 differenceAxisW,
1481 differenceAngle,
1482 correctionRotationW,
1483 vertContributionW);
1484 break;
1485 }
1486 case 2:
1487 {
1488 Vector3 vertContributionV = Vector3.Zero;
1489 Vector3 origRotVelW = VehicleRotationalVelocity; // DEBUG DEBUG
1490
1491 // Take a vector pointing up and convert it from world to vehicle relative coords.
1492 Vector3 verticalError = Vector3.Normalize(Vector3.UnitZ * VehicleOrientation);
1493
1494 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
1495 // is now:
1496 // leaning to one side: rotated around the X axis with the Y value going
1497 // from zero (nearly straight up) to one (completely to the side)) or
1498 // leaning front-to-back: rotated around the Y axis with the value of X being between
1499 // zero and one.
1500 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
1501
1502 // Y error means needed rotation around X axis and visa versa.
1503 // Since the error goes from zero to one, the asin is the corresponding angle.
1504 vertContributionV.X = (float)Math.Asin(verticalError.Y);
1505 // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.)
1506 vertContributionV.Y = -(float)Math.Asin(verticalError.X);
1507
1508 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
1509 if (verticalError.Z < 0f)
1510 {
1511 vertContributionV.X += Math.Sign(vertContributionV.X) * PIOverFour;
1512 // vertContribution.Y -= PIOverFour;
1513 }
1514
1515 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
1516 // Correction happens over a number of seconds.
1517 Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
1518
1519 // The correction happens over the user's time period
1520 vertContributionV /= m_verticalAttractionTimescale;
1521
1522 // Rotate the vehicle rotation to the world coordinates.
1523 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
1524
1525 VDetailLog("{0}, MoveAngular,verticalAttraction,,upAxis={1},origRotVW={2},vertError={3},unscaledV={4},eff={5},ts={6},vertContribV={7}",
1526 ControllingPrim.LocalID,
1527 vehicleUpAxis,
1528 origRotVelW,
1529 verticalError,
1530 unscaledContribVerticalErrorV,
1531 m_verticalAttractionEfficiency,
1532 m_verticalAttractionTimescale,
1533 vertContributionV);
1534 break;
1535 }
1536 default:
1537 {
1538 break;
1539 }
1423 } 1540 }
1424
1425 // 'vertContrbution' is now the necessary angular correction to correct tilt in one second.
1426 // Correction happens over a number of seconds.
1427 Vector3 unscaledContribVerticalErrorV = vertContributionV; // DEBUG DEBUG
1428
1429 // The correction happens over the user's time period
1430 vertContributionV /= m_verticalAttractionTimescale;
1431
1432 // Rotate the vehicle rotation to the world coordinates.
1433 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
1434
1435 VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}",
1436 Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
1437 m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
1438 */
1439 } 1541 }
1440 } 1542 }
1441 1543
@@ -1445,13 +1547,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1445 // in that direction. 1547 // in that direction.
1446 // TODO: implement reference frame. 1548 // TODO: implement reference frame.
1447 public void ComputeAngularDeflection() 1549 public void ComputeAngularDeflection()
1448 { 1550 {
1449 // Since angularMotorUp and angularDeflection are computed independently, they will calculate
1450 // approximately the same X or Y correction. When added together (when contributions are combined)
1451 // this creates an over-correction and then wabbling as the target is overshot.
1452 // TODO: rethink how the different correction computations inter-relate.
1453 1551
1454 if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2) 1552 if (BSParam.VehicleEnableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
1455 { 1553 {
1456 Vector3 deflectContributionV = Vector3.Zero; 1554 Vector3 deflectContributionV = Vector3.Zero;
1457 1555
@@ -1464,10 +1562,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1464 1562
1465 // The direction the vehicle is pointing 1563 // The direction the vehicle is pointing
1466 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation; 1564 Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
1467 pointingDirection.Normalize(); 1565 //Predict where the Vehicle will be pointing after AngularVelocity change is applied. This will keep
1566 // from overshooting and allow this correction to merge with the Vertical Attraction peacefully.
1567 Vector3 predictedPointingDirection = pointingDirection * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
1568 predictedPointingDirection.Normalize();
1468 1569
1469 // The difference between what is and what should be. 1570 // The difference between what is and what should be.
1470 Vector3 deflectionError = movingDirection - pointingDirection; 1571 // Vector3 deflectionError = movingDirection - predictedPointingDirection;
1572 Vector3 deflectionError = Vector3.Cross(movingDirection, predictedPointingDirection);
1471 1573
1472 // Don't try to correct very large errors (not our job) 1574 // Don't try to correct very large errors (not our job)
1473 // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X); 1575 // if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X);
@@ -1480,15 +1582,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1480 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); 1582 // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError);
1481 1583
1482 // Scale the correction by recovery timescale and efficiency 1584 // Scale the correction by recovery timescale and efficiency
1483 deflectContributionV = (-deflectionError) * m_angularDeflectionEfficiency; 1585 // Not modeling a spring so clamp the scale to no more then the arc
1484 deflectContributionV /= m_angularDeflectionTimescale; 1586 deflectContributionV = (-deflectionError) * ClampInRange(0, m_angularDeflectionEfficiency/m_angularDeflectionTimescale,1f);
1485 1587 //deflectContributionV /= m_angularDeflectionTimescale;
1486 VehicleRotationalVelocity += deflectContributionV * VehicleOrientation;
1487 1588
1589 // VehicleRotationalVelocity += deflectContributionV * VehicleOrientation;
1590 VehicleRotationalVelocity += deflectContributionV;
1488 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", 1591 VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
1489 ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV); 1592 ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV);
1490 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", 1593 VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3},PredictedPointingDir={4}",
1491 ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); 1594 ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale, predictedPointingDirection);
1492 } 1595 }
1493 } 1596 }
1494 1597
@@ -1500,13 +1603,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1500 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude 1603 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude
1501 // of the yaw effect will be proportional to the 1604 // of the yaw effect will be proportional to the
1502 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's 1605 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's
1503 // velocity along its preferred axis of motion. 1606 // velocity along its preferred axis of motion.
1504 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any 1607 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any
1505 // positive rotation (by the right-hand rule) about the roll-axis will effect a 1608 // positive rotation (by the right-hand rule) about the roll-axis will effect a
1506 // (negative) torque around the yaw-axis, making it turn to the right--that is the 1609 // (negative) torque around the yaw-axis, making it turn to the right--that is the
1507 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work. 1610 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work.
1508 // Negating the banking coefficient will make it so that the vehicle leans to the 1611 // Negating the banking coefficient will make it so that the vehicle leans to the
1509 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?). 1612 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?).
1510 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making 1613 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making
1511 // banking vehicles do what you want rather than what the laws of physics allow. 1614 // banking vehicles do what you want rather than what the laws of physics allow.
1512 // For example, consider a real motorcycle...it must be moving forward in order for 1615 // For example, consider a real motorcycle...it must be moving forward in order for
@@ -1518,14 +1621,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1518 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the 1621 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the
1519 // banking effect depends only on the vehicle's rotation about its roll-axis compared 1622 // banking effect depends only on the vehicle's rotation about its roll-axis compared
1520 // to "dynamic" where the banking is also proportional to its velocity along its 1623 // to "dynamic" where the banking is also proportional to its velocity along its
1521 // roll-axis. Finding the best value of the "mixture" will probably require trial and error. 1624 // roll-axis. Finding the best value of the "mixture" will probably require trial and error.
1522 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the 1625 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the
1523 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to 1626 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to
1524 // bank quickly then give it a banking timescale of about a second or less, otherwise you can 1627 // bank quickly then give it a banking timescale of about a second or less, otherwise you can
1525 // make a sluggish vehicle by giving it a timescale of several seconds. 1628 // make a sluggish vehicle by giving it a timescale of several seconds.
1526 public void ComputeAngularBanking() 1629 public void ComputeAngularBanking()
1527 { 1630 {
1528 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1631 if (BSParam.VehicleEnableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
1529 { 1632 {
1530 Vector3 bankingContributionV = Vector3.Zero; 1633 Vector3 bankingContributionV = Vector3.Zero;
1531 1634
@@ -1551,7 +1654,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1551 1654
1552 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; 1655 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation;
1553 VehicleRotationalVelocity += bankingContributionV; 1656 VehicleRotationalVelocity += bankingContributionV;
1554 1657
1555 1658
1556 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", 1659 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}",
1557 ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); 1660 ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV);
@@ -1598,6 +1701,35 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1598 1701
1599 } 1702 }
1600 1703
1704 // Given a friction vector (reduction in seconds) and a timestep, return the factor to reduce
1705 // some value by to apply this friction.
1706 private Vector3 ComputeFrictionFactor(Vector3 friction, float pTimestep)
1707 {
1708 Vector3 frictionFactor = Vector3.Zero;
1709 if (friction != BSMotor.InfiniteVector)
1710 {
1711 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
1712 // Individual friction components can be 'infinite' so compute each separately.
1713 frictionFactor.X = (friction.X == BSMotor.Infinite) ? 0f : (1f / friction.X);
1714 frictionFactor.Y = (friction.Y == BSMotor.Infinite) ? 0f : (1f / friction.Y);
1715 frictionFactor.Z = (friction.Z == BSMotor.Infinite) ? 0f : (1f / friction.Z);
1716 frictionFactor *= pTimestep;
1717 }
1718 return frictionFactor;
1719 }
1720
1721 private float SortedClampInRange(float clampa, float val, float clampb)
1722 {
1723 if (clampa > clampb)
1724 {
1725 float temp = clampa;
1726 clampa = clampb;
1727 clampb = temp;
1728 }
1729 return ClampInRange(clampa, val, clampb);
1730
1731 }
1732
1601 private float ClampInRange(float low, float val, float high) 1733 private float ClampInRange(float low, float val, float high)
1602 { 1734 {
1603 return Math.Max(low, Math.Min(val, high)); 1735 return Math.Max(low, Math.Min(val, high));
@@ -1607,8 +1739,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1607 // Invoke the detailed logger and output something if it's enabled. 1739 // Invoke the detailed logger and output something if it's enabled.
1608 private void VDetailLog(string msg, params Object[] args) 1740 private void VDetailLog(string msg, params Object[] args)
1609 { 1741 {
1610 if (ControllingPrim.PhysicsScene.VehicleLoggingEnabled) 1742 if (ControllingPrim.PhysScene.VehicleLoggingEnabled)
1611 ControllingPrim.PhysicsScene.DetailLog(msg, args); 1743 ControllingPrim.PhysScene.DetailLog(msg, args);
1612 } 1744 }
1613 } 1745 }
1614} 1746}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 4ece1eb..77f69a5 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -33,14 +33,6 @@ using OMV = OpenMetaverse;
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35 35
36// A BSPrim can get individual information about its linkedness attached
37// to it through an instance of a subclass of LinksetInfo.
38// Each type of linkset will define the information needed for its type.
39public abstract class BSLinksetInfo
40{
41 public virtual void Clear() { }
42}
43
44public abstract class BSLinkset 36public abstract class BSLinkset
45{ 37{
46 // private static string LogHeader = "[BULLETSIM LINKSET]"; 38 // private static string LogHeader = "[BULLETSIM LINKSET]";
@@ -56,15 +48,15 @@ public abstract class BSLinkset
56 { 48 {
57 BSLinkset ret = null; 49 BSLinkset ret = null;
58 50
59 switch ((int)BSParam.LinksetImplementation) 51 switch (parent.LinksetType)
60 { 52 {
61 case (int)LinksetImplementation.Constraint: 53 case LinksetImplementation.Constraint:
62 ret = new BSLinksetConstraints(physScene, parent); 54 ret = new BSLinksetConstraints(physScene, parent);
63 break; 55 break;
64 case (int)LinksetImplementation.Compound: 56 case LinksetImplementation.Compound:
65 ret = new BSLinksetCompound(physScene, parent); 57 ret = new BSLinksetCompound(physScene, parent);
66 break; 58 break;
67 case (int)LinksetImplementation.Manual: 59 case LinksetImplementation.Manual:
68 // ret = new BSLinksetManual(physScene, parent); 60 // ret = new BSLinksetManual(physScene, parent);
69 break; 61 break;
70 default: 62 default:
@@ -78,28 +70,37 @@ public abstract class BSLinkset
78 return ret; 70 return ret;
79 } 71 }
80 72
73 public class BSLinkInfo
74 {
75 public BSPrimLinkable member;
76 public BSLinkInfo(BSPrimLinkable pMember)
77 {
78 member = pMember;
79 }
80 public virtual void ResetLink() { }
81 public virtual void SetLinkParameters(BSConstraint constrain) { }
82 // Returns 'true' if physical property updates from the child should be reported to the simulator
83 public virtual bool ShouldUpdateChildProperties() { return false; }
84 }
85
86 public LinksetImplementation LinksetImpl { get; protected set; }
87
81 public BSPrimLinkable LinksetRoot { get; protected set; } 88 public BSPrimLinkable LinksetRoot { get; protected set; }
82 89
83 public BSScene PhysicsScene { get; private set; } 90 protected BSScene m_physicsScene { get; private set; }
84 91
85 static int m_nextLinksetID = 1; 92 static int m_nextLinksetID = 1;
86 public int LinksetID { get; private set; } 93 public int LinksetID { get; private set; }
87 94
88 // The children under the root in this linkset. 95 // The children under the root in this linkset.
89 protected HashSet<BSPrimLinkable> m_children; 96 // protected HashSet<BSPrimLinkable> m_children;
97 protected Dictionary<BSPrimLinkable, BSLinkInfo> m_children;
90 98
91 // We lock the diddling of linkset classes to prevent any badness. 99 // We lock the diddling of linkset classes to prevent any badness.
92 // This locks the modification of the instances of this class. Changes 100 // This locks the modification of the instances of this class. Changes
93 // to the physical representation is done via the tainting mechenism. 101 // to the physical representation is done via the tainting mechenism.
94 protected object m_linksetActivityLock = new Object(); 102 protected object m_linksetActivityLock = new Object();
95 103
96 // Some linksets have a preferred physical shape.
97 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
98 public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor)
99 {
100 return BSPhysicsShapeType.SHAPE_UNKNOWN;
101 }
102
103 // We keep the prim's mass in the linkset structure since it could be dependent on other prims 104 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
104 public float LinksetMass { get; protected set; } 105 public float LinksetMass { get; protected set; }
105 106
@@ -122,9 +123,9 @@ public abstract class BSLinkset
122 // We create LOTS of linksets. 123 // We create LOTS of linksets.
123 if (m_nextLinksetID <= 0) 124 if (m_nextLinksetID <= 0)
124 m_nextLinksetID = 1; 125 m_nextLinksetID = 1;
125 PhysicsScene = scene; 126 m_physicsScene = scene;
126 LinksetRoot = parent; 127 LinksetRoot = parent;
127 m_children = new HashSet<BSPrimLinkable>(); 128 m_children = new Dictionary<BSPrimLinkable, BSLinkInfo>();
128 LinksetMass = parent.RawMass; 129 LinksetMass = parent.RawMass;
129 Rebuilding = false; 130 Rebuilding = false;
130 131
@@ -151,7 +152,7 @@ public abstract class BSLinkset
151 // Returns a new linkset for the child which is a linkset of one (just the 152 // Returns a new linkset for the child which is a linkset of one (just the
152 // orphened child). 153 // orphened child).
153 // Called at runtime. 154 // Called at runtime.
154 public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child) 155 public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child, bool inTaintTime)
155 { 156 {
156 lock (m_linksetActivityLock) 157 lock (m_linksetActivityLock)
157 { 158 {
@@ -160,12 +161,12 @@ public abstract class BSLinkset
160 // Cannot remove the root from a linkset. 161 // Cannot remove the root from a linkset.
161 return this; 162 return this;
162 } 163 }
163 RemoveChildFromLinkset(child); 164 RemoveChildFromLinkset(child, inTaintTime);
164 LinksetMass = ComputeLinksetMass(); 165 LinksetMass = ComputeLinksetMass();
165 } 166 }
166 167
167 // The child is down to a linkset of just itself 168 // The child is down to a linkset of just itself
168 return BSLinkset.Factory(PhysicsScene, child); 169 return BSLinkset.Factory(m_physicsScene, child);
169 } 170 }
170 171
171 // Return 'true' if the passed object is the root object of this linkset 172 // Return 'true' if the passed object is the root object of this linkset
@@ -185,17 +186,7 @@ public abstract class BSLinkset
185 bool ret = false; 186 bool ret = false;
186 lock (m_linksetActivityLock) 187 lock (m_linksetActivityLock)
187 { 188 {
188 ret = m_children.Contains(child); 189 ret = m_children.ContainsKey(child);
189 /* Safer version but the above should work
190 foreach (BSPrimLinkable bp in m_children)
191 {
192 if (child.LocalID == bp.LocalID)
193 {
194 ret = true;
195 break;
196 }
197 }
198 */
199 } 190 }
200 return ret; 191 return ret;
201 } 192 }
@@ -209,7 +200,35 @@ public abstract class BSLinkset
209 lock (m_linksetActivityLock) 200 lock (m_linksetActivityLock)
210 { 201 {
211 action(LinksetRoot); 202 action(LinksetRoot);
212 foreach (BSPrimLinkable po in m_children) 203 foreach (BSPrimLinkable po in m_children.Keys)
204 {
205 if (action(po))
206 break;
207 }
208 }
209 return ret;
210 }
211
212 public bool TryGetLinkInfo(BSPrimLinkable child, out BSLinkInfo foundInfo)
213 {
214 bool ret = false;
215 BSLinkInfo found = null;
216 lock (m_linksetActivityLock)
217 {
218 ret = m_children.TryGetValue(child, out found);
219 }
220 foundInfo = found;
221 return ret;
222 }
223 // Perform an action on each member of the linkset including root prim.
224 // Depends on the action on whether this should be done at taint time.
225 public delegate bool ForEachLinkInfoAction(BSLinkInfo obj);
226 public virtual bool ForEachLinkInfo(ForEachLinkInfoAction action)
227 {
228 bool ret = false;
229 lock (m_linksetActivityLock)
230 {
231 foreach (BSLinkInfo po in m_children.Values)
213 { 232 {
214 if (action(po)) 233 if (action(po))
215 break; 234 break;
@@ -218,13 +237,55 @@ public abstract class BSLinkset
218 return ret; 237 return ret;
219 } 238 }
220 239
240 // Check the type of the link and return 'true' if the link is flexible and the
241 // updates from the child should be sent to the simulator so things change.
242 public virtual bool ShouldReportPropertyUpdates(BSPrimLinkable child)
243 {
244 bool ret = false;
245
246 BSLinkInfo linkInfo;
247 if (m_children.TryGetValue(child, out linkInfo))
248 {
249 ret = linkInfo.ShouldUpdateChildProperties();
250 }
251
252 return ret;
253 }
254
255 // Called after a simulation step to post a collision with this object.
256 // Return 'true' if linkset processed the collision. 'false' says the linkset didn't have
257 // anything to add for the collision and it should be passed through normal processing.
258 // Default processing for a linkset.
259 public virtual bool HandleCollide(uint collidingWith, BSPhysObject collidee,
260 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
261 {
262 bool ret = false;
263
264 // prims in the same linkset cannot collide with each other
265 BSPrimLinkable convCollidee = collidee as BSPrimLinkable;
266 if (convCollidee != null && (LinksetID == convCollidee.Linkset.LinksetID))
267 {
268 // By returning 'true', we tell the caller the collision has been 'handled' so it won't
269 // do anything about this collision and thus, effectivily, ignoring the collision.
270 ret = true;
271 }
272 else
273 {
274 // Not a collision between members of the linkset. Must be a real collision.
275 // So the linkset root can know if there is a collision anywhere in the linkset.
276 LinksetRoot.SomeCollisionSimulationStep = m_physicsScene.SimulationStep;
277 }
278
279 return ret;
280 }
281
221 // I am the root of a linkset and a new child is being added 282 // I am the root of a linkset and a new child is being added
222 // Called while LinkActivity is locked. 283 // Called while LinkActivity is locked.
223 protected abstract void AddChildToLinkset(BSPrimLinkable child); 284 protected abstract void AddChildToLinkset(BSPrimLinkable child);
224 285
225 // I am the root of a linkset and one of my children is being removed. 286 // I am the root of a linkset and one of my children is being removed.
226 // Safe to call even if the child is not really in my linkset. 287 // Safe to call even if the child is not really in my linkset.
227 protected abstract void RemoveChildFromLinkset(BSPrimLinkable child); 288 protected abstract void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime);
228 289
229 // When physical properties are changed the linkset needs to recalculate 290 // When physical properties are changed the linkset needs to recalculate
230 // its internal properties. 291 // its internal properties.
@@ -263,9 +324,88 @@ public abstract class BSLinkset
263 // This is called when the root body is changing. 324 // This is called when the root body is changing.
264 // Returns 'true' of something was actually removed and would need restoring 325 // Returns 'true' of something was actually removed and would need restoring
265 // Called at taint-time!! 326 // Called at taint-time!!
266 public abstract bool RemoveBodyDependencies(BSPrimLinkable child); 327 public abstract bool RemoveDependencies(BSPrimLinkable child);
267 328
268 // ================================================================ 329 // ================================================================
330 // Some physical setting happen to all members of the linkset
331 public virtual void SetPhysicalFriction(float friction)
332 {
333 ForEachMember((member) =>
334 {
335 if (member.PhysBody.HasPhysicalBody)
336 m_physicsScene.PE.SetFriction(member.PhysBody, friction);
337 return false; // 'false' says to continue looping
338 }
339 );
340 }
341 public virtual void SetPhysicalRestitution(float restitution)
342 {
343 ForEachMember((member) =>
344 {
345 if (member.PhysBody.HasPhysicalBody)
346 m_physicsScene.PE.SetRestitution(member.PhysBody, restitution);
347 return false; // 'false' says to continue looping
348 }
349 );
350 }
351 public virtual void SetPhysicalGravity(OMV.Vector3 gravity)
352 {
353 ForEachMember((member) =>
354 {
355 if (member.PhysBody.HasPhysicalBody)
356 m_physicsScene.PE.SetGravity(member.PhysBody, gravity);
357 return false; // 'false' says to continue looping
358 }
359 );
360 }
361 public virtual void ComputeAndSetLocalInertia(OMV.Vector3 inertiaFactor, float linksetMass)
362 {
363 ForEachMember((member) =>
364 {
365 if (member.PhysBody.HasPhysicalBody)
366 {
367 OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(member.PhysShape.physShapeInfo, linksetMass);
368 member.Inertia = inertia * inertiaFactor;
369 m_physicsScene.PE.SetMassProps(member.PhysBody, linksetMass, member.Inertia);
370 m_physicsScene.PE.UpdateInertiaTensor(member.PhysBody);
371 DetailLog("{0},BSLinkset.ComputeAndSetLocalInertia,m.mass={1}, inertia={2}", member.LocalID, linksetMass, member.Inertia);
372
373 }
374 return false; // 'false' says to continue looping
375 }
376 );
377 }
378 public virtual void SetPhysicalCollisionFlags(CollisionFlags collFlags)
379 {
380 ForEachMember((member) =>
381 {
382 if (member.PhysBody.HasPhysicalBody)
383 m_physicsScene.PE.SetCollisionFlags(member.PhysBody, collFlags);
384 return false; // 'false' says to continue looping
385 }
386 );
387 }
388 public virtual void AddToPhysicalCollisionFlags(CollisionFlags collFlags)
389 {
390 ForEachMember((member) =>
391 {
392 if (member.PhysBody.HasPhysicalBody)
393 m_physicsScene.PE.AddToCollisionFlags(member.PhysBody, collFlags);
394 return false; // 'false' says to continue looping
395 }
396 );
397 }
398 public virtual void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags)
399 {
400 ForEachMember((member) =>
401 {
402 if (member.PhysBody.HasPhysicalBody)
403 m_physicsScene.PE.RemoveFromCollisionFlags(member.PhysBody, collFlags);
404 return false; // 'false' says to continue looping
405 }
406 );
407 }
408 // ================================================================
269 protected virtual float ComputeLinksetMass() 409 protected virtual float ComputeLinksetMass()
270 { 410 {
271 float mass = LinksetRoot.RawMass; 411 float mass = LinksetRoot.RawMass;
@@ -273,7 +413,7 @@ public abstract class BSLinkset
273 { 413 {
274 lock (m_linksetActivityLock) 414 lock (m_linksetActivityLock)
275 { 415 {
276 foreach (BSPrimLinkable bp in m_children) 416 foreach (BSPrimLinkable bp in m_children.Keys)
277 { 417 {
278 mass += bp.RawMass; 418 mass += bp.RawMass;
279 } 419 }
@@ -291,7 +431,7 @@ public abstract class BSLinkset
291 com = LinksetRoot.Position * LinksetRoot.RawMass; 431 com = LinksetRoot.Position * LinksetRoot.RawMass;
292 float totalMass = LinksetRoot.RawMass; 432 float totalMass = LinksetRoot.RawMass;
293 433
294 foreach (BSPrimLinkable bp in m_children) 434 foreach (BSPrimLinkable bp in m_children.Keys)
295 { 435 {
296 com += bp.Position * bp.RawMass; 436 com += bp.Position * bp.RawMass;
297 totalMass += bp.RawMass; 437 totalMass += bp.RawMass;
@@ -310,7 +450,7 @@ public abstract class BSLinkset
310 { 450 {
311 com = LinksetRoot.Position; 451 com = LinksetRoot.Position;
312 452
313 foreach (BSPrimLinkable bp in m_children) 453 foreach (BSPrimLinkable bp in m_children.Keys)
314 { 454 {
315 com += bp.Position; 455 com += bp.Position;
316 } 456 }
@@ -320,12 +460,18 @@ public abstract class BSLinkset
320 return com; 460 return com;
321 } 461 }
322 462
463 #region Extension
464 public virtual object Extension(string pFunct, params object[] pParams)
465 {
466 return null;
467 }
468 #endregion // Extension
469
323 // Invoke the detailed logger and output something if it's enabled. 470 // Invoke the detailed logger and output something if it's enabled.
324 protected void DetailLog(string msg, params Object[] args) 471 protected void DetailLog(string msg, params Object[] args)
325 { 472 {
326 if (PhysicsScene.PhysicsLogging.Enabled) 473 if (m_physicsScene.PhysicsLogging.Enabled)
327 PhysicsScene.DetailLog(msg, args); 474 m_physicsScene.DetailLog(msg, args);
328 } 475 }
329
330} 476}
331} 477}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index e05562a..8f12189 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -35,103 +35,78 @@ using OMV = OpenMetaverse;
35namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37 37
38// When a child is linked, the relationship position of the child to the parent 38public sealed class BSLinksetCompound : BSLinkset
39// is remembered so the child's world position can be recomputed when it is
40// removed from the linkset.
41sealed class BSLinksetCompoundInfo : BSLinksetInfo
42{ 39{
43 public int Index; 40 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
44 public OMV.Vector3 OffsetFromRoot; 41
45 public OMV.Vector3 OffsetFromCenterOfMass; 42 public BSLinksetCompound(BSScene scene, BSPrimLinkable parent)
46 public OMV.Quaternion OffsetRot; 43 : base(scene, parent)
47 public BSLinksetCompoundInfo(int indx, OMV.Vector3 p, OMV.Quaternion r)
48 { 44 {
49 Index = indx; 45 LinksetImpl = LinksetImplementation.Compound;
50 OffsetFromRoot = p;
51 OffsetFromCenterOfMass = p;
52 OffsetRot = r;
53 } 46 }
54 // 'centerDisplacement' is the distance from the root the the center-of-mass (Bullet 'zero' of the shape) 47
55 public BSLinksetCompoundInfo(int indx, BSPrimLinkable root, BSPrimLinkable child, OMV.Vector3 centerDisplacement) 48 // ================================================================
49 // Changing the physical property of the linkset only needs to change the root
50 public override void SetPhysicalFriction(float friction)
56 { 51 {
57 // Each child position and rotation is given relative to the center-of-mass. 52 if (LinksetRoot.PhysBody.HasPhysicalBody)
58 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(root.RawOrientation); 53 m_physicsScene.PE.SetFriction(LinksetRoot.PhysBody, friction);
59 OMV.Vector3 displacementFromRoot = (child.RawPosition - root.RawPosition) * invRootOrientation;
60 OMV.Vector3 displacementFromCOM = displacementFromRoot - centerDisplacement;
61 OMV.Quaternion displacementRot = child.RawOrientation * invRootOrientation;
62
63 // Save relative position for recomputing child's world position after moving linkset.
64 Index = indx;
65 OffsetFromRoot = displacementFromRoot;
66 OffsetFromCenterOfMass = displacementFromCOM;
67 OffsetRot = displacementRot;
68 } 54 }
69 public override void Clear() 55 public override void SetPhysicalRestitution(float restitution)
70 { 56 {
71 Index = 0; 57 if (LinksetRoot.PhysBody.HasPhysicalBody)
72 OffsetFromRoot = OMV.Vector3.Zero; 58 m_physicsScene.PE.SetRestitution(LinksetRoot.PhysBody, restitution);
73 OffsetFromCenterOfMass = OMV.Vector3.Zero;
74 OffsetRot = OMV.Quaternion.Identity;
75 } 59 }
76 public override string ToString() 60 public override void SetPhysicalGravity(OMV.Vector3 gravity)
77 { 61 {
78 StringBuilder buff = new StringBuilder(); 62 if (LinksetRoot.PhysBody.HasPhysicalBody)
79 buff.Append("<i="); 63 m_physicsScene.PE.SetGravity(LinksetRoot.PhysBody, gravity);
80 buff.Append(Index.ToString());
81 buff.Append(",p=");
82 buff.Append(OffsetFromRoot.ToString());
83 buff.Append(",m=");
84 buff.Append(OffsetFromCenterOfMass.ToString());
85 buff.Append(",r=");
86 buff.Append(OffsetRot.ToString());
87 buff.Append(">");
88 return buff.ToString();
89 } 64 }
90}; 65 public override void ComputeAndSetLocalInertia(OMV.Vector3 inertiaFactor, float linksetMass)
91
92public sealed class BSLinksetCompound : BSLinkset
93{
94 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
95
96 public BSLinksetCompound(BSScene scene, BSPrimLinkable parent)
97 : base(scene, parent)
98 { 66 {
67 OMV.Vector3 inertia = m_physicsScene.PE.CalculateLocalInertia(LinksetRoot.PhysShape.physShapeInfo, linksetMass);
68 LinksetRoot.Inertia = inertia * inertiaFactor;
69 m_physicsScene.PE.SetMassProps(LinksetRoot.PhysBody, linksetMass, LinksetRoot.Inertia);
70 m_physicsScene.PE.UpdateInertiaTensor(LinksetRoot.PhysBody);
99 } 71 }
100 72 public override void SetPhysicalCollisionFlags(CollisionFlags collFlags)
101 // For compound implimented linksets, if there are children, use compound shape for the root. 73 {
102 public override BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor) 74 if (LinksetRoot.PhysBody.HasPhysicalBody)
103 { 75 m_physicsScene.PE.SetCollisionFlags(LinksetRoot.PhysBody, collFlags);
104 // Returning 'unknown' means we don't have a preference. 76 }
105 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN; 77 public override void AddToPhysicalCollisionFlags(CollisionFlags collFlags)
106 if (IsRoot(requestor) && HasAnyChildren) 78 {
107 { 79 if (LinksetRoot.PhysBody.HasPhysicalBody)
108 ret = BSPhysicsShapeType.SHAPE_COMPOUND; 80 m_physicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, collFlags);
109 }
110 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
111 return ret;
112 } 81 }
82 public override void RemoveFromPhysicalCollisionFlags(CollisionFlags collFlags)
83 {
84 if (LinksetRoot.PhysBody.HasPhysicalBody)
85 m_physicsScene.PE.RemoveFromCollisionFlags(LinksetRoot.PhysBody, collFlags);
86 }
87 // ================================================================
113 88
114 // When physical properties are changed the linkset needs to recalculate 89 // When physical properties are changed the linkset needs to recalculate
115 // its internal properties. 90 // its internal properties.
116 public override void Refresh(BSPrimLinkable requestor) 91 public override void Refresh(BSPrimLinkable requestor)
117 { 92 {
118 base.Refresh(requestor);
119
120 // Something changed so do the rebuilding thing 93 // Something changed so do the rebuilding thing
121 // ScheduleRebuild(); 94 ScheduleRebuild(requestor);
95 base.Refresh(requestor);
122 } 96 }
123 97
124 // Schedule a refresh to happen after all the other taint processing. 98 // Schedule a refresh to happen after all the other taint processing.
125 private void ScheduleRebuild(BSPrimLinkable requestor) 99 private void ScheduleRebuild(BSPrimLinkable requestor)
126 { 100 {
127 DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}", 101 DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}",
128 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren)); 102 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren));
103
129 // When rebuilding, it is possible to set properties that would normally require a rebuild. 104 // When rebuilding, it is possible to set properties that would normally require a rebuild.
130 // If already rebuilding, don't request another rebuild. 105 // If already rebuilding, don't request another rebuild.
131 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding. 106 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding.
132 if (!Rebuilding && HasAnyChildren) 107 if (!Rebuilding && HasAnyChildren)
133 { 108 {
134 PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate() 109 m_physicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate()
135 { 110 {
136 if (HasAnyChildren) 111 if (HasAnyChildren)
137 RecomputeLinksetCompound(); 112 RecomputeLinksetCompound();
@@ -151,47 +126,24 @@ public sealed class BSLinksetCompound : BSLinkset
151 if (IsRoot(child)) 126 if (IsRoot(child))
152 { 127 {
153 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly. 128 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
154 ScheduleRebuild(LinksetRoot); 129 Refresh(LinksetRoot);
155 }
156 else
157 {
158 // The origional prims are removed from the world as the shape of the root compound
159 // shape takes over.
160 PhysicsScene.PE.AddToCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
161 PhysicsScene.PE.ForceActivationState(child.PhysBody, ActivationState.DISABLE_SIMULATION);
162 // We don't want collisions from the old linkset children.
163 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
164
165 child.PhysBody.collisionType = CollisionType.LinksetChild;
166
167 ret = true;
168 } 130 }
169 return ret; 131 return ret;
170 } 132 }
171 133
172 // The object is going static (non-physical). Do any setup necessary for a static linkset. 134 // The object is going static (non-physical). We do not do anything for static linksets.
173 // Return 'true' if any properties updated on the passed object. 135 // Return 'true' if any properties updated on the passed object.
174 // This doesn't normally happen -- OpenSim removes the objects from the physical
175 // world if it is a static linkset.
176 // Called at taint-time! 136 // Called at taint-time!
177 public override bool MakeStatic(BSPrimLinkable child) 137 public override bool MakeStatic(BSPrimLinkable child)
178 { 138 {
179 bool ret = false; 139 bool ret = false;
140
180 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); 141 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
142 child.ClearDisplacement();
181 if (IsRoot(child)) 143 if (IsRoot(child))
182 { 144 {
183 ScheduleRebuild(LinksetRoot); 145 // Schedule a rebuild to verify that the root shape is set to the real shape.
184 } 146 Refresh(LinksetRoot);
185 else
186 {
187 // The non-physical children can come back to life.
188 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
189
190 child.PhysBody.collisionType = CollisionType.LinksetChild;
191
192 // Don't force activation so setting of DISABLE_SIMULATION can stay if used.
193 PhysicsScene.PE.Activate(child.PhysBody, false);
194 ret = true;
195 } 147 }
196 return ret; 148 return ret;
197 } 149 }
@@ -200,13 +152,20 @@ public sealed class BSLinksetCompound : BSLinkset
200 // Called at taint-time. 152 // Called at taint-time.
201 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable updated) 153 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable updated)
202 { 154 {
155 if (!LinksetRoot.IsPhysicallyActive)
156 {
157 // No reason to do this physical stuff for static linksets.
158 DetailLog("{0},BSLinksetCompound.UpdateProperties,notPhysical", LinksetRoot.LocalID);
159 return;
160 }
161
203 // The user moving a child around requires the rebuilding of the linkset compound shape 162 // The user moving a child around requires the rebuilding of the linkset compound shape
204 // One problem is this happens when a border is crossed -- the simulator implementation 163 // One problem is this happens when a border is crossed -- the simulator implementation
205 // stores the position into the group which causes the move of the object 164 // stores the position into the group which causes the move of the object
206 // but it also means all the child positions get updated. 165 // but it also means all the child positions get updated.
207 // What would cause an unnecessary rebuild so we make sure the linkset is in a 166 // What would cause an unnecessary rebuild so we make sure the linkset is in a
208 // region before bothering to do a rebuild. 167 // region before bothering to do a rebuild.
209 if (!IsRoot(updated) && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition)) 168 if (!IsRoot(updated) && m_physicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
210 { 169 {
211 // If a child of the linkset is updating only the position or rotation, that can be done 170 // If a child of the linkset is updating only the position or rotation, that can be done
212 // without rebuilding the linkset. 171 // without rebuilding the linkset.
@@ -218,22 +177,22 @@ public sealed class BSLinksetCompound : BSLinkset
218 // and that is caused by us updating the object. 177 // and that is caused by us updating the object.
219 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0) 178 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
220 { 179 {
221 // Find the physical instance of the child 180 // Find the physical instance of the child
222 if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) 181 if (LinksetRoot.PhysShape.HasPhysicalShape && m_physicsScene.PE.IsCompound(LinksetRoot.PhysShape.physShapeInfo))
223 { 182 {
224 // It is possible that the linkset is still under construction and the child is not yet 183 // It is possible that the linkset is still under construction and the child is not yet
225 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will 184 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will
226 // build the whole thing with the new position or rotation. 185 // build the whole thing with the new position or rotation.
227 // The index must be checked because Bullet references the child array but does no validity 186 // The index must be checked because Bullet references the child array but does no validity
228 // checking of the child index passed. 187 // checking of the child index passed.
229 int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape); 188 int numLinksetChildren = m_physicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape.physShapeInfo);
230 if (updated.LinksetChildIndex < numLinksetChildren) 189 if (updated.LinksetChildIndex < numLinksetChildren)
231 { 190 {
232 BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex); 191 BulletShape linksetChildShape = m_physicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex);
233 if (linksetChildShape.HasPhysicalShape) 192 if (linksetChildShape.HasPhysicalShape)
234 { 193 {
235 // Found the child shape within the compound shape 194 // Found the child shape within the compound shape
236 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex, 195 m_physicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex,
237 updated.RawPosition - LinksetRoot.RawPosition, 196 updated.RawPosition - LinksetRoot.RawPosition,
238 updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation), 197 updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation),
239 true /* shouldRecalculateLocalAabb */); 198 true /* shouldRecalculateLocalAabb */);
@@ -267,83 +226,29 @@ public sealed class BSLinksetCompound : BSLinkset
267 // there will already be a rebuild scheduled. 226 // there will already be a rebuild scheduled.
268 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}", 227 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}",
269 updated.LocalID, whichUpdated); 228 updated.LocalID, whichUpdated);
270 updated.LinksetInfo = null; // setting to 'null' causes relative position to be recomputed. 229 Refresh(updated);
271 ScheduleRebuild(updated);
272 } 230 }
273 } 231 }
274 } 232 }
275 } 233 }
276 234
277 // Routine called when rebuilding the body of some member of the linkset. 235 // Routine called when rebuilding the body of some member of the linkset.
278 // Since we don't keep in world relationships, do nothing unless it's a child changing. 236 // If one of the bodies is being changed, the linkset needs rebuilding.
237 // For instance, a linkset is built and then a mesh asset is read in and the mesh is recreated.
279 // Returns 'true' of something was actually removed and would need restoring 238 // Returns 'true' of something was actually removed and would need restoring
280 // Called at taint-time!! 239 // Called at taint-time!!
281 public override bool RemoveBodyDependencies(BSPrimLinkable child) 240 public override bool RemoveDependencies(BSPrimLinkable child)
282 { 241 {
283 bool ret = false; 242 bool ret = false;
284 243
285 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", 244 DetailLog("{0},BSLinksetCompound.RemoveDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
286 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child)); 245 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child));
287 246
288 if (!IsRoot(child)) 247 Refresh(child);
289 {
290 // Because it is a convenient time, recompute child world position and rotation based on
291 // its position in the linkset.
292 RecomputeChildWorldPosition(child, true /* inTaintTime */);
293 child.LinksetInfo = null;
294 }
295
296 // Cannot schedule a refresh/rebuild here because this routine is called when
297 // the linkset is being rebuilt.
298 // InternalRefresh(LinksetRoot);
299 248
300 return ret; 249 return ret;
301 } 250 }
302 251
303 // When the linkset is built, the child shape is added to the compound shape relative to the
304 // root shape. The linkset then moves around but this does not move the actual child
305 // prim. The child prim's location must be recomputed based on the location of the root shape.
306 private void RecomputeChildWorldPosition(BSPrimLinkable child, bool inTaintTime)
307 {
308 // For the moment (20130201), disable this computation (converting the child physical addr back to
309 // a region address) until we have a good handle on center-of-mass offsets and what the physics
310 // engine moving a child actually means.
311 // The simulator keeps track of where children should be as the linkset moves. Setting
312 // the pos/rot here does not effect that knowledge as there is no good way for the
313 // physics engine to send the simulator an update for a child.
314
315 /*
316 BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo;
317 if (lci != null)
318 {
319 if (inTaintTime)
320 {
321 OMV.Vector3 oldPos = child.RawPosition;
322 child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetFromRoot;
323 child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
324 DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
325 child.LocalID, oldPos, lci, child.RawPosition);
326 }
327 else
328 {
329 // TaintedObject is not used here so the raw position is set now and not at taint-time.
330 child.Position = LinksetRoot.RawPosition + lci.OffsetFromRoot;
331 child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
332 }
333 }
334 else
335 {
336 // This happens when children have been added to the linkset but the linkset
337 // has not been constructed yet. So like, at taint time, adding children to a linkset
338 // and then changing properties of the children (makePhysical, for instance)
339 // but the post-print action of actually rebuilding the linkset has not yet happened.
340 // PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}",
341 // LogHeader, child.LocalID);
342 DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID);
343 }
344 */
345 }
346
347 // ================================================================ 252 // ================================================================
348 253
349 // Add a new child to the linkset. 254 // Add a new child to the linkset.
@@ -352,19 +257,19 @@ public sealed class BSLinksetCompound : BSLinkset
352 { 257 {
353 if (!HasChild(child)) 258 if (!HasChild(child))
354 { 259 {
355 m_children.Add(child); 260 m_children.Add(child, new BSLinkInfo(child));
356 261
357 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); 262 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
358 263
359 // Rebuild the compound shape with the new child shape included 264 // Rebuild the compound shape with the new child shape included
360 ScheduleRebuild(child); 265 Refresh(child);
361 } 266 }
362 return; 267 return;
363 } 268 }
364 269
365 // Remove the specified child from the linkset. 270 // Remove the specified child from the linkset.
366 // Safe to call even if the child is not really in the linkset. 271 // Safe to call even if the child is not really in the linkset.
367 protected override void RemoveChildFromLinkset(BSPrimLinkable child) 272 protected override void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime)
368 { 273 {
369 child.ClearDisplacement(); 274 child.ClearDisplacement();
370 275
@@ -376,19 +281,17 @@ public sealed class BSLinksetCompound : BSLinkset
376 child.LocalID, child.PhysBody.AddrString); 281 child.LocalID, child.PhysBody.AddrString);
377 282
378 // Cause the child's body to be rebuilt and thus restored to normal operation 283 // Cause the child's body to be rebuilt and thus restored to normal operation
379 RecomputeChildWorldPosition(child, false); 284 child.ForceBodyShapeRebuild(inTaintTime);
380 child.LinksetInfo = null;
381 child.ForceBodyShapeRebuild(false);
382 285
383 if (!HasAnyChildren) 286 if (!HasAnyChildren)
384 { 287 {
385 // The linkset is now empty. The root needs rebuilding. 288 // The linkset is now empty. The root needs rebuilding.
386 LinksetRoot.ForceBodyShapeRebuild(false); 289 LinksetRoot.ForceBodyShapeRebuild(inTaintTime);
387 } 290 }
388 else 291 else
389 { 292 {
390 // Rebuild the compound shape with the child removed 293 // Rebuild the compound shape with the child removed
391 ScheduleRebuild(LinksetRoot); 294 Refresh(LinksetRoot);
392 } 295 }
393 } 296 }
394 return; 297 return;
@@ -399,108 +302,118 @@ public sealed class BSLinksetCompound : BSLinkset
399 // Constraint linksets are rebuilt every time. 302 // Constraint linksets are rebuilt every time.
400 // Note that this works for rebuilding just the root after a linkset is taken apart. 303 // Note that this works for rebuilding just the root after a linkset is taken apart.
401 // Called at taint time!! 304 // Called at taint time!!
402 private bool disableCOM = true; // DEBUG DEBUG: disable until we get this debugged 305 private bool UseBulletSimRootOffsetHack = false; // Attempt to have Bullet track the coords of root compound shape
403 private void RecomputeLinksetCompound() 306 private void RecomputeLinksetCompound()
404 { 307 {
405 try 308 try
406 { 309 {
407 // Suppress rebuilding while rebuilding. (We know rebuilding is on only one thread.)
408 Rebuilding = true; 310 Rebuilding = true;
409 311
410 // Cause the root shape to be rebuilt as a compound object with just the root in it 312 // No matter what is being done, force the root prim's PhysBody and PhysShape to get set
411 LinksetRoot.ForceBodyShapeRebuild(true /* inTaintTime */); 313 // to what they should be as if the root was not in a linkset.
314 // Not that bad since we only get into this routine if there are children in the linkset and
315 // something has been updated/changed.
316 // Have to do the rebuild before checking for physical because this might be a linkset
317 // being destructed and going non-physical.
318 LinksetRoot.ForceBodyShapeRebuild(true);
412 319
413 // The center of mass for the linkset is the geometric center of the group. 320 // There is no reason to build all this physical stuff for a non-physical or empty linkset.
414 // Compute a displacement for each component so it is relative to the center-of-mass. 321 if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren)
415 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
416 OMV.Vector3 centerOfMassW = LinksetRoot.RawPosition;
417 if (!disableCOM) // DEBUG DEBUG
418 { 322 {
419 // Compute a center-of-mass in world coordinates. 323 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysicalOrNoChildren", LinksetRoot.LocalID);
420 centerOfMassW = ComputeLinksetCenterOfMass(); 324 return; // Note the 'finally' clause at the botton which will get executed.
421 } 325 }
422 326
423 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); 327 // Get a new compound shape to build the linkset shape in.
424 328 BSShape linksetShape = BSShapeCompound.GetReference(m_physicsScene);
425 // 'centerDisplacement' is the value to subtract from children to give physical offset position
426 OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation;
427 LinksetRoot.SetEffectiveCenterOfMassW(centerDisplacement);
428 329
429 // This causes the physical position of the root prim to be offset to accomodate for the displacements 330 // Compute a displacement for each component so it is relative to the center-of-mass.
430 LinksetRoot.ForcePosition = LinksetRoot.RawPosition; 331 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
332 OMV.Vector3 centerOfMassW = ComputeLinksetCenterOfMass();
431 333
432 // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM 334 OMV.Quaternion invRootOrientation = OMV.Quaternion.Normalize(OMV.Quaternion.Inverse(LinksetRoot.RawOrientation));
433 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0 /* childIndex */, 335 OMV.Vector3 origRootPosition = LinksetRoot.RawPosition;
434 -centerDisplacement,
435 OMV.Quaternion.Identity, // LinksetRoot.RawOrientation,
436 false /* shouldRecalculateLocalAabb (is done later after linkset built) */);
437 336
438 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}", 337 // 'centerDisplacementV' is the vehicle relative distance from the simulator root position to the center-of-mass
439 LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement); 338 OMV.Vector3 centerDisplacementV = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation;
339 if (UseBulletSimRootOffsetHack || !BSParam.LinksetOffsetCenterOfMass)
340 {
341 // Zero everything if center-of-mass displacement is not being done.
342 centerDisplacementV = OMV.Vector3.Zero;
343 LinksetRoot.ClearDisplacement();
344 }
345 else
346 {
347 // The actual center-of-mass could have been set by the user.
348 centerDisplacementV = LinksetRoot.SetEffectiveCenterOfMassDisplacement(centerDisplacementV);
349 }
440 350
441 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", 351 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,rootPos={1},com={2},comDisp={3}",
442 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); 352 LinksetRoot.LocalID, origRootPosition, centerOfMassW, centerDisplacementV);
443 353
444 // Add a shape for each of the other children in the linkset 354 // Add the shapes of all the components of the linkset
445 int memberIndex = 1; 355 int memberIndex = 1;
446 ForEachMember(delegate(BSPrimLinkable cPrim) 356 ForEachMember((cPrim) =>
447 { 357 {
448 if (IsRoot(cPrim)) 358 if (IsRoot(cPrim))
449 { 359 {
360 // Root shape is always index zero.
450 cPrim.LinksetChildIndex = 0; 361 cPrim.LinksetChildIndex = 0;
451 } 362 }
452 else 363 else
453 { 364 {
454 cPrim.LinksetChildIndex = memberIndex; 365 cPrim.LinksetChildIndex = memberIndex;
366 memberIndex++;
367 }
455 368
456 if (cPrim.PhysShape.isNativeShape) 369 // Get a reference to the shape of the child for adding of that shape to the linkset compound shape
457 { 370 BSShape childShape = cPrim.PhysShape.GetReference(m_physicsScene, cPrim);
458 // A native shape is turned into a hull collision shape because native
459 // shapes are not shared so we have to hullify it so it will be tracked
460 // and freed at the correct time. This also solves the scaling problem
461 // (native shapes scale but hull/meshes are assumed to not be).
462 // TODO: decide of the native shape can just be used in the compound shape.
463 // Use call to CreateGeomNonSpecial().
464 BulletShape saveShape = cPrim.PhysShape;
465 cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
466 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
467 BulletShape newShape = cPrim.PhysShape;
468 cPrim.PhysShape = saveShape;
469
470 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
471 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
472 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
473 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
474 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
475 }
476 else
477 {
478 // For the shared shapes (meshes and hulls), just use the shape in the child.
479 // The reference count added here will be decremented when the compound shape
480 // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced).
481 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
482 {
483 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
484 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
485 }
486 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
487 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
488 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
489 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNonNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
490 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
491 371
492 } 372 // Offset the child shape from the center-of-mass and rotate it to vehicle relative.
493 memberIndex++; 373 OMV.Vector3 offsetPos = (cPrim.RawPosition - origRootPosition) * invRootOrientation - centerDisplacementV;
374 OMV.Quaternion offsetRot = OMV.Quaternion.Normalize(cPrim.RawOrientation) * invRootOrientation;
375
376 // Add the child shape to the compound shape being built
377 m_physicsScene.PE.AddChildShapeToCompoundShape(linksetShape.physShapeInfo, childShape.physShapeInfo, offsetPos, offsetRot);
378 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addChild,indx={1},cShape={2},offPos={3},offRot={4}",
379 LinksetRoot.LocalID, cPrim.LinksetChildIndex, childShape, offsetPos, offsetRot);
380
381 // Since we are borrowing the shape of the child, disable the origional child body
382 if (!IsRoot(cPrim))
383 {
384 m_physicsScene.PE.AddToCollisionFlags(cPrim.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
385 m_physicsScene.PE.ForceActivationState(cPrim.PhysBody, ActivationState.DISABLE_SIMULATION);
386 // We don't want collisions from the old linkset children.
387 m_physicsScene.PE.RemoveFromCollisionFlags(cPrim.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
388 cPrim.PhysBody.collisionType = CollisionType.LinksetChild;
494 } 389 }
390
495 return false; // 'false' says to move onto the next child in the list 391 return false; // 'false' says to move onto the next child in the list
496 }); 392 });
497 393
394 // Replace the root shape with the built compound shape.
395 // Object removed and added to world to get collision cache rebuilt for new shape.
396 LinksetRoot.PhysShape.Dereference(m_physicsScene);
397 LinksetRoot.PhysShape = linksetShape;
398 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, LinksetRoot.PhysBody);
399 m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, LinksetRoot.PhysBody, linksetShape.physShapeInfo);
400 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, LinksetRoot.PhysBody);
401 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addBody,body={1},shape={2}",
402 LinksetRoot.LocalID, LinksetRoot.PhysBody, linksetShape);
403
498 // With all of the linkset packed into the root prim, it has the mass of everyone. 404 // With all of the linkset packed into the root prim, it has the mass of everyone.
499 LinksetMass = ComputeLinksetMass(); 405 LinksetMass = ComputeLinksetMass();
500 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); 406 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
501 407
502 // Enable the physical position updator to return the position and rotation of the root shape 408 if (UseBulletSimRootOffsetHack)
503 PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE); 409 {
410 // Enable the physical position updator to return the position and rotation of the root shape.
411 // This enables a feature in the C++ code to return the world coordinates of the first shape in the
412 // compound shape. This aleviates the need to offset the returned physical position by the
413 // center-of-mass offset.
414 // TODO: either debug this feature or remove it.
415 m_physicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE);
416 }
504 } 417 }
505 finally 418 finally
506 { 419 {
@@ -508,7 +421,7 @@ public sealed class BSLinksetCompound : BSLinkset
508 } 421 }
509 422
510 // See that the Aabb surrounds the new shape 423 // See that the Aabb surrounds the new shape
511 PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); 424 m_physicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape.physShapeInfo);
512 } 425 }
513} 426}
514} \ No newline at end of file 427} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
index 6d252ca..aaf92c8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -28,6 +28,8 @@ using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Text; 29using System.Text;
30 30
31using OpenSim.Region.OptionalModules.Scripting;
32
31using OMV = OpenMetaverse; 33using OMV = OpenMetaverse;
32 34
33namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
@@ -36,26 +38,194 @@ public sealed class BSLinksetConstraints : BSLinkset
36{ 38{
37 // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; 39 // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
38 40
41 public class BSLinkInfoConstraint : BSLinkInfo
42 {
43 public ConstraintType constraintType;
44 public BSConstraint constraint;
45 public OMV.Vector3 linearLimitLow;
46 public OMV.Vector3 linearLimitHigh;
47 public OMV.Vector3 angularLimitLow;
48 public OMV.Vector3 angularLimitHigh;
49 public bool useFrameOffset;
50 public bool enableTransMotor;
51 public float transMotorMaxVel;
52 public float transMotorMaxForce;
53 public float cfm;
54 public float erp;
55 public float solverIterations;
56 //
57 public OMV.Vector3 frameInAloc;
58 public OMV.Quaternion frameInArot;
59 public OMV.Vector3 frameInBloc;
60 public OMV.Quaternion frameInBrot;
61 public bool useLinearReferenceFrameA;
62 // Spring
63 public bool[] springAxisEnable;
64 public float[] springDamping;
65 public float[] springStiffness;
66 public OMV.Vector3 springLinearEquilibriumPoint;
67 public OMV.Vector3 springAngularEquilibriumPoint;
68
69 public BSLinkInfoConstraint(BSPrimLinkable pMember)
70 : base(pMember)
71 {
72 constraint = null;
73 ResetLink();
74 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.creation", member.LocalID);
75 }
76
77 // Set all the parameters for this constraint to a fixed, non-movable constraint.
78 public override void ResetLink()
79 {
80 // constraintType = ConstraintType.D6_CONSTRAINT_TYPE;
81 constraintType = ConstraintType.FIXED_CONSTRAINT_TYPE;
82 linearLimitLow = OMV.Vector3.Zero;
83 linearLimitHigh = OMV.Vector3.Zero;
84 angularLimitLow = OMV.Vector3.Zero;
85 angularLimitHigh = OMV.Vector3.Zero;
86 useFrameOffset = BSParam.LinkConstraintUseFrameOffset;
87 enableTransMotor = BSParam.LinkConstraintEnableTransMotor;
88 transMotorMaxVel = BSParam.LinkConstraintTransMotorMaxVel;
89 transMotorMaxForce = BSParam.LinkConstraintTransMotorMaxForce;
90 cfm = BSParam.LinkConstraintCFM;
91 erp = BSParam.LinkConstraintERP;
92 solverIterations = BSParam.LinkConstraintSolverIterations;
93 frameInAloc = OMV.Vector3.Zero;
94 frameInArot = OMV.Quaternion.Identity;
95 frameInBloc = OMV.Vector3.Zero;
96 frameInBrot = OMV.Quaternion.Identity;
97 useLinearReferenceFrameA = true;
98 springAxisEnable = new bool[6];
99 springDamping = new float[6];
100 springStiffness = new float[6];
101 for (int ii = 0; ii < springAxisEnable.Length; ii++)
102 {
103 springAxisEnable[ii] = false;
104 springDamping[ii] = BSAPITemplate.SPRING_NOT_SPECIFIED;
105 springStiffness[ii] = BSAPITemplate.SPRING_NOT_SPECIFIED;
106 }
107 springLinearEquilibriumPoint = OMV.Vector3.Zero;
108 springAngularEquilibriumPoint = OMV.Vector3.Zero;
109 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.ResetLink", member.LocalID);
110 }
111
112 // Given a constraint, apply the current constraint parameters to same.
113 public override void SetLinkParameters(BSConstraint constrain)
114 {
115 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.SetLinkParameters,type={1}", member.LocalID, constraintType);
116 switch (constraintType)
117 {
118 case ConstraintType.FIXED_CONSTRAINT_TYPE:
119 case ConstraintType.D6_CONSTRAINT_TYPE:
120 BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof;
121 if (constrain6dof != null)
122 {
123 // NOTE: D6_SPRING_CONSTRAINT_TYPE should be updated if you change any of this code.
124 // zero linear and angular limits makes the objects unable to move in relation to each other
125 constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh);
126 constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh);
127
128 // tweek the constraint to increase stability
129 constrain6dof.UseFrameOffset(useFrameOffset);
130 constrain6dof.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce);
131 constrain6dof.SetCFMAndERP(cfm, erp);
132 if (solverIterations != 0f)
133 {
134 constrain6dof.SetSolverIterations(solverIterations);
135 }
136 }
137 break;
138 case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
139 BSConstraintSpring constrainSpring = constrain as BSConstraintSpring;
140 if (constrainSpring != null)
141 {
142 // zero linear and angular limits makes the objects unable to move in relation to each other
143 constrainSpring.SetLinearLimits(linearLimitLow, linearLimitHigh);
144 constrainSpring.SetAngularLimits(angularLimitLow, angularLimitHigh);
145
146 // tweek the constraint to increase stability
147 constrainSpring.UseFrameOffset(useFrameOffset);
148 constrainSpring.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce);
149 constrainSpring.SetCFMAndERP(cfm, erp);
150 if (solverIterations != 0f)
151 {
152 constrainSpring.SetSolverIterations(solverIterations);
153 }
154 for (int ii = 0; ii < springAxisEnable.Length; ii++)
155 {
156 constrainSpring.SetAxisEnable(ii, springAxisEnable[ii]);
157 if (springDamping[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED)
158 constrainSpring.SetDamping(ii, springDamping[ii]);
159 if (springStiffness[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED)
160 constrainSpring.SetStiffness(ii, springStiffness[ii]);
161 }
162 constrainSpring.CalculateTransforms();
163
164 if (springLinearEquilibriumPoint != OMV.Vector3.Zero)
165 constrainSpring.SetEquilibriumPoint(springLinearEquilibriumPoint, springAngularEquilibriumPoint);
166 else
167 constrainSpring.SetEquilibriumPoint(BSAPITemplate.SPRING_NOT_SPECIFIED, BSAPITemplate.SPRING_NOT_SPECIFIED);
168 }
169 break;
170 default:
171 break;
172 }
173 }
174
175 // Return 'true' if the property updates from the physics engine should be reported
176 // to the simulator.
177 // If the constraint is fixed, we don't need to report as the simulator and viewer will
178 // report the right things.
179 public override bool ShouldUpdateChildProperties()
180 {
181 bool ret = true;
182 if (constraintType == ConstraintType.FIXED_CONSTRAINT_TYPE)
183 ret = false;
184
185 return ret;
186 }
187 }
188
39 public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent) 189 public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent)
40 { 190 {
191 LinksetImpl = LinksetImplementation.Constraint;
41 } 192 }
42 193
194 private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINT]";
195
43 // When physical properties are changed the linkset needs to recalculate 196 // When physical properties are changed the linkset needs to recalculate
44 // its internal properties. 197 // its internal properties.
45 // This is queued in the 'post taint' queue so the 198 // This is queued in the 'post taint' queue so the
46 // refresh will happen once after all the other taints are applied. 199 // refresh will happen once after all the other taints are applied.
47 public override void Refresh(BSPrimLinkable requestor) 200 public override void Refresh(BSPrimLinkable requestor)
48 { 201 {
202 ScheduleRebuild(requestor);
49 base.Refresh(requestor); 203 base.Refresh(requestor);
50 204
51 if (HasAnyChildren && IsRoot(requestor)) 205 }
206
207 private void ScheduleRebuild(BSPrimLinkable requestor)
208 {
209 DetailLog("{0},BSLinksetConstraint.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}",
210 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren));
211
212 // When rebuilding, it is possible to set properties that would normally require a rebuild.
213 // If already rebuilding, don't request another rebuild.
214 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding.
215 if (!Rebuilding && HasAnyChildren)
52 { 216 {
53 // Queue to happen after all the other taint processing 217 // Queue to happen after all the other taint processing
54 PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() 218 m_physicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
219 {
220 if (HasAnyChildren)
55 { 221 {
56 if (HasAnyChildren && IsRoot(requestor)) 222 // Constraints that have not been changed are not rebuild but make sure
57 RecomputeLinksetConstraints(); 223 // the constraint of the requestor is rebuilt.
58 }); 224 PhysicallyUnlinkAChildFromRoot(LinksetRoot, requestor);
225 // Rebuild the linkset and all its constraints.
226 RecomputeLinksetConstraints();
227 }
228 });
59 } 229 }
60 } 230 }
61 231
@@ -67,8 +237,14 @@ public sealed class BSLinksetConstraints : BSLinkset
67 // Called at taint-time! 237 // Called at taint-time!
68 public override bool MakeDynamic(BSPrimLinkable child) 238 public override bool MakeDynamic(BSPrimLinkable child)
69 { 239 {
70 // What is done for each object in BSPrim is what we want. 240 bool ret = false;
71 return false; 241 DetailLog("{0},BSLinksetConstraints.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child));
242 if (IsRoot(child))
243 {
244 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
245 Refresh(LinksetRoot);
246 }
247 return ret;
72 } 248 }
73 249
74 // The object is going static (non-physical). Do any setup necessary for a static linkset. 250 // The object is going static (non-physical). Do any setup necessary for a static linkset.
@@ -78,8 +254,16 @@ public sealed class BSLinksetConstraints : BSLinkset
78 // Called at taint-time! 254 // Called at taint-time!
79 public override bool MakeStatic(BSPrimLinkable child) 255 public override bool MakeStatic(BSPrimLinkable child)
80 { 256 {
81 // What is done for each object in BSPrim is what we want. 257 bool ret = false;
82 return false; 258
259 DetailLog("{0},BSLinksetConstraint.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
260 child.ClearDisplacement();
261 if (IsRoot(child))
262 {
263 // Schedule a rebuild to verify that the root shape is set to the real shape.
264 Refresh(LinksetRoot);
265 }
266 return ret;
83 } 267 }
84 268
85 // Called at taint-time!! 269 // Called at taint-time!!
@@ -93,11 +277,11 @@ public sealed class BSLinksetConstraints : BSLinkset
93 // up to rebuild the constraints before the next simulation step. 277 // up to rebuild the constraints before the next simulation step.
94 // Returns 'true' of something was actually removed and would need restoring 278 // Returns 'true' of something was actually removed and would need restoring
95 // Called at taint-time!! 279 // Called at taint-time!!
96 public override bool RemoveBodyDependencies(BSPrimLinkable child) 280 public override bool RemoveDependencies(BSPrimLinkable child)
97 { 281 {
98 bool ret = false; 282 bool ret = false;
99 283
100 DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", 284 DetailLog("{0},BSLinksetConstraint.RemoveDependencies,removeChildrenForRoot,rID={1},rBody={2}",
101 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString); 285 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString);
102 286
103 lock (m_linksetActivityLock) 287 lock (m_linksetActivityLock)
@@ -118,7 +302,7 @@ public sealed class BSLinksetConstraints : BSLinkset
118 { 302 {
119 if (!HasChild(child)) 303 if (!HasChild(child))
120 { 304 {
121 m_children.Add(child); 305 m_children.Add(child, new BSLinkInfoConstraint(child));
122 306
123 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); 307 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
124 308
@@ -130,7 +314,7 @@ public sealed class BSLinksetConstraints : BSLinkset
130 314
131 // Remove the specified child from the linkset. 315 // Remove the specified child from the linkset.
132 // Safe to call even if the child is not really in my linkset. 316 // Safe to call even if the child is not really in my linkset.
133 protected override void RemoveChildFromLinkset(BSPrimLinkable child) 317 protected override void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime)
134 { 318 {
135 if (m_children.Remove(child)) 319 if (m_children.Remove(child))
136 { 320 {
@@ -142,7 +326,7 @@ public sealed class BSLinksetConstraints : BSLinkset
142 rootx.LocalID, rootx.PhysBody.AddrString, 326 rootx.LocalID, rootx.PhysBody.AddrString,
143 childx.LocalID, childx.PhysBody.AddrString); 327 childx.LocalID, childx.PhysBody.AddrString);
144 328
145 PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() 329 m_physicsScene.TaintedObject(inTaintTime, childx.LocalID, "BSLinksetConstraints.RemoveChildFromLinkset", delegate()
146 { 330 {
147 PhysicallyUnlinkAChildFromRoot(rootx, childx); 331 PhysicallyUnlinkAChildFromRoot(rootx, childx);
148 }); 332 });
@@ -165,73 +349,86 @@ public sealed class BSLinksetConstraints : BSLinkset
165 Refresh(rootPrim); 349 Refresh(rootPrim);
166 } 350 }
167 351
168 private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSPrimLinkable childPrim) 352 // Create a static constraint between the two passed objects
353 private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li)
169 { 354 {
355 BSLinkInfoConstraint linkInfo = li as BSLinkInfoConstraint;
356 if (linkInfo == null)
357 return null;
358
170 // Zero motion for children so they don't interpolate 359 // Zero motion for children so they don't interpolate
171 childPrim.ZeroMotion(true); 360 li.member.ZeroMotion(true);
172 361
173 // Relative position normalized to the root prim 362 BSConstraint constrain = null;
174 // Essentually a vector pointing from center of rootPrim to center of childPrim 363
175 OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; 364 switch (linkInfo.constraintType)
176
177 // real world coordinate of midpoint between the two objects
178 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
179
180 DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
181 rootPrim.LocalID,
182 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
183 childPrim.LocalID, childPrim.PhysBody.AddrString,
184 rootPrim.Position, childPrim.Position, midPoint);
185
186 // create a constraint that allows no freedom of movement between the two objects
187 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
188
189 BSConstraint6Dof constrain = new BSConstraint6Dof(
190 PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true );
191 // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true );
192
193 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
194 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
195 * of the objects.
196 * Code left for future programmers.
197 // ==================================================================================
198 // relative position normalized to the root prim
199 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
200 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
201
202 // relative rotation of the child to the parent
203 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
204 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
205
206 DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
207 BS6DofConstraint constrain = new BS6DofConstraint(
208 PhysicsScene.World, rootPrim.Body, childPrim.Body,
209 OMV.Vector3.Zero,
210 OMV.Quaternion.Inverse(rootPrim.Orientation),
211 OMV.Vector3.Zero,
212 OMV.Quaternion.Inverse(childPrim.Orientation),
213 true,
214 true
215 );
216 // ==================================================================================
217 */
218
219 PhysicsScene.Constraints.AddConstraint(constrain);
220
221 // zero linear and angular limits makes the objects unable to move in relation to each other
222 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
223 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
224
225 // tweek the constraint to increase stability
226 constrain.UseFrameOffset(BSParam.LinkConstraintUseFrameOffset);
227 constrain.TranslationalLimitMotor(BSParam.LinkConstraintEnableTransMotor,
228 BSParam.LinkConstraintTransMotorMaxVel,
229 BSParam.LinkConstraintTransMotorMaxForce);
230 constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);
231 if (BSParam.LinkConstraintSolverIterations != 0f)
232 { 365 {
233 constrain.SetSolverIterations(BSParam.LinkConstraintSolverIterations); 366 case ConstraintType.FIXED_CONSTRAINT_TYPE:
367 case ConstraintType.D6_CONSTRAINT_TYPE:
368 // Relative position normalized to the root prim
369 // Essentually a vector pointing from center of rootPrim to center of li.member
370 OMV.Vector3 childRelativePosition = linkInfo.member.Position - rootPrim.Position;
371
372 // real world coordinate of midpoint between the two objects
373 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
374
375 DetailLog("{0},BSLinksetConstraint.BuildConstraint,6Dof,rBody={1},cBody={2},rLoc={3},cLoc={4},midLoc={5}",
376 rootPrim.LocalID, rootPrim.PhysBody, linkInfo.member.PhysBody,
377 rootPrim.Position, linkInfo.member.Position, midPoint);
378
379 // create a constraint that allows no freedom of movement between the two objects
380 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
381
382 constrain = new BSConstraint6Dof(
383 m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody, midPoint, true, true );
384
385 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
386 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
387 * of the objects.
388 * Code left for future programmers.
389 // ==================================================================================
390 // relative position normalized to the root prim
391 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
392 OMV.Vector3 childRelativePosition = (liConstraint.member.Position - rootPrim.Position) * invThisOrientation;
393
394 // relative rotation of the child to the parent
395 OMV.Quaternion childRelativeRotation = invThisOrientation * liConstraint.member.Orientation;
396 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
397
398 DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, liConstraint.member.LocalID);
399 constrain = new BS6DofConstraint(
400 PhysicsScene.World, rootPrim.Body, liConstraint.member.Body,
401 OMV.Vector3.Zero,
402 OMV.Quaternion.Inverse(rootPrim.Orientation),
403 OMV.Vector3.Zero,
404 OMV.Quaternion.Inverse(liConstraint.member.Orientation),
405 true,
406 true
407 );
408 // ==================================================================================
409 */
410
411 break;
412 case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
413 constrain = new BSConstraintSpring(m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody,
414 linkInfo.frameInAloc, linkInfo.frameInArot, linkInfo.frameInBloc, linkInfo.frameInBrot,
415 linkInfo.useLinearReferenceFrameA,
416 true /*disableCollisionsBetweenLinkedBodies*/);
417 DetailLog("{0},BSLinksetConstraint.BuildConstraint,spring,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6}",
418 rootPrim.LocalID,
419 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
420 linkInfo.member.LocalID, linkInfo.member.PhysBody.AddrString,
421 rootPrim.Position, linkInfo.member.Position);
422
423 break;
424 default:
425 break;
234 } 426 }
427
428 linkInfo.SetLinkParameters(constrain);
429
430 m_physicsScene.Constraints.AddConstraint(constrain);
431
235 return constrain; 432 return constrain;
236 } 433 }
237 434
@@ -247,13 +444,22 @@ public sealed class BSLinksetConstraints : BSLinkset
247 rootPrim.LocalID, rootPrim.PhysBody.AddrString, 444 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
248 childPrim.LocalID, childPrim.PhysBody.AddrString); 445 childPrim.LocalID, childPrim.PhysBody.AddrString);
249 446
250 // Find the constraint for this link and get rid of it from the overall collection and from my list 447 // If asked to unlink root from root, just remove all the constraints
251 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) 448 if (rootPrim == childPrim || childPrim == LinksetRoot)
252 { 449 {
253 // Make the child refresh its location 450 PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
254 PhysicsScene.PE.PushUpdate(childPrim.PhysBody);
255 ret = true; 451 ret = true;
256 } 452 }
453 else
454 {
455 // Find the constraint for this link and get rid of it from the overall collection and from my list
456 if (m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody))
457 {
458 // Make the child refresh its location
459 m_physicsScene.PE.PushUpdate(childPrim.PhysBody);
460 ret = true;
461 }
462 }
257 463
258 return ret; 464 return ret;
259 } 465 }
@@ -265,7 +471,7 @@ public sealed class BSLinksetConstraints : BSLinkset
265 { 471 {
266 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); 472 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
267 473
268 return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody); 474 return m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody);
269 } 475 }
270 476
271 // Call each of the constraints that make up this linkset and recompute the 477 // Call each of the constraints that make up this linkset and recompute the
@@ -281,24 +487,360 @@ public sealed class BSLinksetConstraints : BSLinkset
281 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", 487 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}",
282 LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, linksetMass); 488 LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, linksetMass);
283 489
284 foreach (BSPrimLinkable child in m_children) 490 try
285 { 491 {
286 // A child in the linkset physically shows the mass of the whole linkset. 492 Rebuilding = true;
287 // This allows Bullet to apply enough force on the child to move the whole linkset.
288 // (Also do the mass stuff before recomputing the constraint so mass is not zero.)
289 child.UpdatePhysicalMassProperties(linksetMass, true);
290 493
291 BSConstraint constrain; 494 // There is no reason to build all this physical stuff for a non-physical linkset.
292 if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) 495 if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren)
293 { 496 {
294 // If constraint doesn't exist yet, create it. 497 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetCompound,notPhysicalOrNoChildren", LinksetRoot.LocalID);
295 constrain = BuildConstraint(LinksetRoot, child); 498 return; // Note the 'finally' clause at the botton which will get executed.
296 } 499 }
297 constrain.RecomputeConstraintVariables(linksetMass);
298 500
299 // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG 501 ForEachLinkInfo((li) =>
502 {
503 // A child in the linkset physically shows the mass of the whole linkset.
504 // This allows Bullet to apply enough force on the child to move the whole linkset.
505 // (Also do the mass stuff before recomputing the constraint so mass is not zero.)
506 li.member.UpdatePhysicalMassProperties(linksetMass, true);
507
508 BSConstraint constrain;
509 if (!m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, li.member.PhysBody, out constrain))
510 {
511 // If constraint doesn't exist yet, create it.
512 constrain = BuildConstraint(LinksetRoot, li);
513 }
514 li.SetLinkParameters(constrain);
515 constrain.RecomputeConstraintVariables(linksetMass);
516
517 // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG
518 return false; // 'false' says to keep processing other members
519 });
300 } 520 }
521 finally
522 {
523 Rebuilding = false;
524 }
525 }
301 526
527 #region Extension
528 public override object Extension(string pFunct, params object[] pParams)
529 {
530 object ret = null;
531 switch (pFunct)
532 {
533 // pParams = [ BSPhysObject root, BSPhysObject child, integer linkType ]
534 case ExtendedPhysics.PhysFunctChangeLinkType:
535 if (pParams.Length > 2)
536 {
537 int requestedType = (int)pParams[2];
538 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,requestedType={1}", LinksetRoot.LocalID, requestedType);
539 if (requestedType == (int)ConstraintType.FIXED_CONSTRAINT_TYPE
540 || requestedType == (int)ConstraintType.D6_CONSTRAINT_TYPE
541 || requestedType == (int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE
542 || requestedType == (int)ConstraintType.HINGE_CONSTRAINT_TYPE
543 || requestedType == (int)ConstraintType.CONETWIST_CONSTRAINT_TYPE
544 || requestedType == (int)ConstraintType.SLIDER_CONSTRAINT_TYPE)
545 {
546 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
547 if (child != null)
548 {
549 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,rootID={1},childID={2},type={3}",
550 LinksetRoot.LocalID, LinksetRoot.LocalID, child.LocalID, requestedType);
551 m_physicsScene.TaintedObject(child.LocalID, "BSLinksetConstraint.PhysFunctChangeLinkType", delegate()
552 {
553 // Pick up all the constraints currently created.
554 RemoveDependencies(child);
555
556 BSLinkInfo linkInfo = null;
557 if (TryGetLinkInfo(child, out linkInfo))
558 {
559 BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
560 if (linkInfoC != null)
561 {
562 linkInfoC.constraintType = (ConstraintType)requestedType;
563 ret = (object)true;
564 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,link={1},type={2}",
565 linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
566 }
567 else
568 {
569 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,linkInfoNotConstraint,childID={1}", LinksetRoot.LocalID, child.LocalID);
570 }
571 }
572 else
573 {
574 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,noLinkInfoForChild,childID={1}", LinksetRoot.LocalID, child.LocalID);
575 }
576 // Cause the whole linkset to be rebuilt in post-taint time.
577 Refresh(child);
578 });
579 }
580 else
581 {
582 DetailLog("{0},BSLinksetConstraint.SetLinkType,childNotBSPrimLinkable", LinksetRoot.LocalID);
583 }
584 }
585 else
586 {
587 DetailLog("{0},BSLinksetConstraint.SetLinkType,illegalRequestedType,reqested={1},spring={2}",
588 LinksetRoot.LocalID, requestedType, ((int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE));
589 }
590 }
591 break;
592 // pParams = [ BSPhysObject root, BSPhysObject child ]
593 case ExtendedPhysics.PhysFunctGetLinkType:
594 if (pParams.Length > 0)
595 {
596 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
597 if (child != null)
598 {
599 BSLinkInfo linkInfo = null;
600 if (TryGetLinkInfo(child, out linkInfo))
601 {
602 BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
603 if (linkInfoC != null)
604 {
605 ret = (object)(int)linkInfoC.constraintType;
606 DetailLog("{0},BSLinksetConstraint.GetLinkType,link={1},type={2}",
607 linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
608
609 }
610 }
611 }
612 }
613 break;
614 // pParams = [ BSPhysObject root, BSPhysObject child, int op, object opParams, int op, object opParams, ... ]
615 case ExtendedPhysics.PhysFunctChangeLinkParams:
616 // There should be two parameters: the childActor and a list of parameters to set
617 if (pParams.Length > 2)
618 {
619 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
620 BSLinkInfo baseLinkInfo = null;
621 if (TryGetLinkInfo(child, out baseLinkInfo))
622 {
623 BSLinkInfoConstraint linkInfo = baseLinkInfo as BSLinkInfoConstraint;
624 if (linkInfo != null)
625 {
626 int valueInt;
627 float valueFloat;
628 bool valueBool;
629 OMV.Vector3 valueVector;
630 OMV.Vector3 valueVector2;
631 OMV.Quaternion valueQuaternion;
632 int axisLow, axisHigh;
633
634 int opIndex = 2;
635 while (opIndex < pParams.Length)
636 {
637 int thisOp = 0;
638 string errMsg = "";
639 try
640 {
641 thisOp = (int)pParams[opIndex];
642 DetailLog("{0},BSLinksetConstraint.ChangeLinkParams2,op={1},val={2}",
643 linkInfo.member.LocalID, thisOp, pParams[opIndex + 1]);
644 switch (thisOp)
645 {
646 case ExtendedPhysics.PHYS_PARAM_LINK_TYPE:
647 valueInt = (int)pParams[opIndex + 1];
648 ConstraintType valueType = (ConstraintType)valueInt;
649 if (valueType == ConstraintType.FIXED_CONSTRAINT_TYPE
650 || valueType == ConstraintType.D6_CONSTRAINT_TYPE
651 || valueType == ConstraintType.D6_SPRING_CONSTRAINT_TYPE
652 || valueType == ConstraintType.HINGE_CONSTRAINT_TYPE
653 || valueType == ConstraintType.CONETWIST_CONSTRAINT_TYPE
654 || valueType == ConstraintType.SLIDER_CONSTRAINT_TYPE)
655 {
656 linkInfo.constraintType = valueType;
657 }
658 opIndex += 2;
659 break;
660 case ExtendedPhysics.PHYS_PARAM_FRAMEINA_LOC:
661 errMsg = "PHYS_PARAM_FRAMEINA_LOC takes one parameter of type vector";
662 valueVector = (OMV.Vector3)pParams[opIndex + 1];
663 linkInfo.frameInAloc = valueVector;
664 opIndex += 2;
665 break;
666 case ExtendedPhysics.PHYS_PARAM_FRAMEINA_ROT:
667 errMsg = "PHYS_PARAM_FRAMEINA_ROT takes one parameter of type rotation";
668 valueQuaternion = (OMV.Quaternion)pParams[opIndex + 1];
669 linkInfo.frameInArot = valueQuaternion;
670 opIndex += 2;
671 break;
672 case ExtendedPhysics.PHYS_PARAM_FRAMEINB_LOC:
673 errMsg = "PHYS_PARAM_FRAMEINB_LOC takes one parameter of type vector";
674 valueVector = (OMV.Vector3)pParams[opIndex + 1];
675 linkInfo.frameInBloc = valueVector;
676 opIndex += 2;
677 break;
678 case ExtendedPhysics.PHYS_PARAM_FRAMEINB_ROT:
679 errMsg = "PHYS_PARAM_FRAMEINB_ROT takes one parameter of type rotation";
680 valueQuaternion = (OMV.Quaternion)pParams[opIndex + 1];
681 linkInfo.frameInBrot = valueQuaternion;
682 opIndex += 2;
683 break;
684 case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_LOW:
685 errMsg = "PHYS_PARAM_LINEAR_LIMIT_LOW takes one parameter of type vector";
686 valueVector = (OMV.Vector3)pParams[opIndex + 1];
687 linkInfo.linearLimitLow = valueVector;
688 opIndex += 2;
689 break;
690 case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_HIGH:
691 errMsg = "PHYS_PARAM_LINEAR_LIMIT_HIGH takes one parameter of type vector";
692 valueVector = (OMV.Vector3)pParams[opIndex + 1];
693 linkInfo.linearLimitHigh = valueVector;
694 opIndex += 2;
695 break;
696 case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_LOW:
697 errMsg = "PHYS_PARAM_ANGULAR_LIMIT_LOW takes one parameter of type vector";
698 valueVector = (OMV.Vector3)pParams[opIndex + 1];
699 linkInfo.angularLimitLow = valueVector;
700 opIndex += 2;
701 break;
702 case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_HIGH:
703 errMsg = "PHYS_PARAM_ANGULAR_LIMIT_HIGH takes one parameter of type vector";
704 valueVector = (OMV.Vector3)pParams[opIndex + 1];
705 linkInfo.angularLimitHigh = valueVector;
706 opIndex += 2;
707 break;
708 case ExtendedPhysics.PHYS_PARAM_USE_FRAME_OFFSET:
709 errMsg = "PHYS_PARAM_USE_FRAME_OFFSET takes one parameter of type integer (bool)";
710 valueBool = ((int)pParams[opIndex + 1]) != 0;
711 linkInfo.useFrameOffset = valueBool;
712 opIndex += 2;
713 break;
714 case ExtendedPhysics.PHYS_PARAM_ENABLE_TRANSMOTOR:
715 errMsg = "PHYS_PARAM_ENABLE_TRANSMOTOR takes one parameter of type integer (bool)";
716 valueBool = ((int)pParams[opIndex + 1]) != 0;
717 linkInfo.enableTransMotor = valueBool;
718 opIndex += 2;
719 break;
720 case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXVEL:
721 errMsg = "PHYS_PARAM_TRANSMOTOR_MAXVEL takes one parameter of type float";
722 valueFloat = (float)pParams[opIndex + 1];
723 linkInfo.transMotorMaxVel = valueFloat;
724 opIndex += 2;
725 break;
726 case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXFORCE:
727 errMsg = "PHYS_PARAM_TRANSMOTOR_MAXFORCE takes one parameter of type float";
728 valueFloat = (float)pParams[opIndex + 1];
729 linkInfo.transMotorMaxForce = valueFloat;
730 opIndex += 2;
731 break;
732 case ExtendedPhysics.PHYS_PARAM_CFM:
733 errMsg = "PHYS_PARAM_CFM takes one parameter of type float";
734 valueFloat = (float)pParams[opIndex + 1];
735 linkInfo.cfm = valueFloat;
736 opIndex += 2;
737 break;
738 case ExtendedPhysics.PHYS_PARAM_ERP:
739 errMsg = "PHYS_PARAM_ERP takes one parameter of type float";
740 valueFloat = (float)pParams[opIndex + 1];
741 linkInfo.erp = valueFloat;
742 opIndex += 2;
743 break;
744 case ExtendedPhysics.PHYS_PARAM_SOLVER_ITERATIONS:
745 errMsg = "PHYS_PARAM_SOLVER_ITERATIONS takes one parameter of type float";
746 valueFloat = (float)pParams[opIndex + 1];
747 linkInfo.solverIterations = valueFloat;
748 opIndex += 2;
749 break;
750 case ExtendedPhysics.PHYS_PARAM_SPRING_AXIS_ENABLE:
751 errMsg = "PHYS_PARAM_SPRING_AXIS_ENABLE takes two parameters of types integer and integer (bool)";
752 valueInt = (int)pParams[opIndex + 1];
753 valueBool = ((int)pParams[opIndex + 2]) != 0;
754 GetAxisRange(valueInt, out axisLow, out axisHigh);
755 for (int ii = axisLow; ii <= axisHigh; ii++)
756 linkInfo.springAxisEnable[ii] = valueBool;
757 opIndex += 3;
758 break;
759 case ExtendedPhysics.PHYS_PARAM_SPRING_DAMPING:
760 errMsg = "PHYS_PARAM_SPRING_DAMPING takes two parameters of types integer and float";
761 valueInt = (int)pParams[opIndex + 1];
762 valueFloat = (float)pParams[opIndex + 2];
763 GetAxisRange(valueInt, out axisLow, out axisHigh);
764 for (int ii = axisLow; ii <= axisHigh; ii++)
765 linkInfo.springDamping[ii] = valueFloat;
766 opIndex += 3;
767 break;
768 case ExtendedPhysics.PHYS_PARAM_SPRING_STIFFNESS:
769 errMsg = "PHYS_PARAM_SPRING_STIFFNESS takes two parameters of types integer and float";
770 valueInt = (int)pParams[opIndex + 1];
771 valueFloat = (float)pParams[opIndex + 2];
772 GetAxisRange(valueInt, out axisLow, out axisHigh);
773 for (int ii = axisLow; ii <= axisHigh; ii++)
774 linkInfo.springStiffness[ii] = valueFloat;
775 opIndex += 3;
776 break;
777 case ExtendedPhysics.PHYS_PARAM_SPRING_EQUILIBRIUM_POINT:
778 errMsg = "PHYS_PARAM_SPRING_EQUILIBRIUM_POINT takes two parameters of type vector";
779 valueVector = (OMV.Vector3)pParams[opIndex + 1];
780 valueVector2 = (OMV.Vector3)pParams[opIndex + 2];
781 linkInfo.springLinearEquilibriumPoint = valueVector;
782 linkInfo.springAngularEquilibriumPoint = valueVector2;
783 opIndex += 3;
784 break;
785 case ExtendedPhysics.PHYS_PARAM_USE_LINEAR_FRAMEA:
786 errMsg = "PHYS_PARAM_USE_LINEAR_FRAMEA takes one parameter of type integer (bool)";
787 valueBool = ((int)pParams[opIndex + 1]) != 0;
788 linkInfo.useLinearReferenceFrameA = valueBool;
789 opIndex += 2;
790 break;
791 default:
792 break;
793 }
794 }
795 catch (InvalidCastException e)
796 {
797 m_physicsScene.Logger.WarnFormat("{0} value of wrong type in physSetLinksetParams: {1}, err={2}",
798 LogHeader, errMsg, e);
799 }
800 catch (Exception e)
801 {
802 m_physicsScene.Logger.WarnFormat("{0} bad parameters in physSetLinksetParams: {1}", LogHeader, e);
803 }
804 }
805 }
806 // Something changed so a rebuild is in order
807 Refresh(child);
808 }
809 }
810 break;
811 default:
812 ret = base.Extension(pFunct, pParams);
813 break;
814 }
815 return ret;
816 }
817
818 // Bullet constraints keep some limit parameters for each linear and angular axis.
819 // Setting same is easier if there is an easy way to see all or types.
820 // This routine returns the array limits for the set of axis.
821 private void GetAxisRange(int rangeSpec, out int low, out int high)
822 {
823 switch (rangeSpec)
824 {
825 case ExtendedPhysics.PHYS_AXIS_LINEAR_ALL:
826 low = 0;
827 high = 2;
828 break;
829 case ExtendedPhysics.PHYS_AXIS_ANGULAR_ALL:
830 low = 3;
831 high = 5;
832 break;
833 case ExtendedPhysics.PHYS_AXIS_ALL:
834 low = 0;
835 high = 5;
836 break;
837 default:
838 low = high = rangeSpec;
839 break;
840 }
841 return;
302 } 842 }
843 #endregion // Extension
844
303} 845}
304} 846}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
index 9501e2d..7693195 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
@@ -65,13 +65,11 @@ public abstract class BSMotor
65} 65}
66 66
67// Motor which moves CurrentValue to TargetValue over TimeScale seconds. 67// Motor which moves CurrentValue to TargetValue over TimeScale seconds.
68// The TargetValue decays in TargetValueDecayTimeScale and 68// The TargetValue decays in TargetValueDecayTimeScale.
69// the CurrentValue will be held back by FrictionTimeScale.
70// This motor will "zero itself" over time in that the targetValue will 69// This motor will "zero itself" over time in that the targetValue will
71// decay to zero and the currentValue will follow it to that zero. 70// decay to zero and the currentValue will follow it to that zero.
72// The overall effect is for the returned correction value to go from large 71// The overall effect is for the returned correction value to go from large
73// values (the total difference between current and target minus friction) 72// values to small and eventually zero values.
74// to small and eventually zero values.
75// TimeScale and TargetDelayTimeScale may be 'infinite' which means no decay. 73// TimeScale and TargetDelayTimeScale may be 'infinite' which means no decay.
76 74
77// For instance, if something is moving at speed X and the desired speed is Y, 75// For instance, if something is moving at speed X and the desired speed is Y,
@@ -88,7 +86,6 @@ public class BSVMotor : BSMotor
88 86
89 public virtual float TimeScale { get; set; } 87 public virtual float TimeScale { get; set; }
90 public virtual float TargetValueDecayTimeScale { get; set; } 88 public virtual float TargetValueDecayTimeScale { get; set; }
91 public virtual Vector3 FrictionTimescale { get; set; }
92 public virtual float Efficiency { get; set; } 89 public virtual float Efficiency { get; set; }
93 90
94 public virtual float ErrorZeroThreshold { get; set; } 91 public virtual float ErrorZeroThreshold { get; set; }
@@ -102,7 +99,7 @@ public class BSVMotor : BSMotor
102 return ErrorIsZero(LastError); 99 return ErrorIsZero(LastError);
103 } 100 }
104 public virtual bool ErrorIsZero(Vector3 err) 101 public virtual bool ErrorIsZero(Vector3 err)
105 { 102 {
106 return (err == Vector3.Zero || err.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)); 103 return (err == Vector3.Zero || err.ApproxEquals(Vector3.Zero, ErrorZeroThreshold));
107 } 104 }
108 105
@@ -111,16 +108,14 @@ public class BSVMotor : BSMotor
111 { 108 {
112 TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite; 109 TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
113 Efficiency = 1f; 110 Efficiency = 1f;
114 FrictionTimescale = BSMotor.InfiniteVector;
115 CurrentValue = TargetValue = Vector3.Zero; 111 CurrentValue = TargetValue = Vector3.Zero;
116 ErrorZeroThreshold = 0.001f; 112 ErrorZeroThreshold = 0.001f;
117 } 113 }
118 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) 114 public BSVMotor(string useName, float timeScale, float decayTimeScale, float efficiency)
119 : this(useName) 115 : this(useName)
120 { 116 {
121 TimeScale = timeScale; 117 TimeScale = timeScale;
122 TargetValueDecayTimeScale = decayTimeScale; 118 TargetValueDecayTimeScale = decayTimeScale;
123 FrictionTimescale = frictionTimeScale;
124 Efficiency = efficiency; 119 Efficiency = efficiency;
125 CurrentValue = TargetValue = Vector3.Zero; 120 CurrentValue = TargetValue = Vector3.Zero;
126 } 121 }
@@ -149,7 +144,6 @@ public class BSVMotor : BSMotor
149 144
150 Vector3 correction = Vector3.Zero; 145 Vector3 correction = Vector3.Zero;
151 Vector3 error = TargetValue - CurrentValue; 146 Vector3 error = TargetValue - CurrentValue;
152 LastError = error;
153 if (!ErrorIsZero(error)) 147 if (!ErrorIsZero(error))
154 { 148 {
155 correction = StepError(timeStep, error); 149 correction = StepError(timeStep, error);
@@ -165,26 +159,11 @@ public class BSVMotor : BSMotor
165 TargetValue *= (1f - decayFactor); 159 TargetValue *= (1f - decayFactor);
166 } 160 }
167 161
168 // The amount we can correct the error is reduced by the friction
169 Vector3 frictionFactor = Vector3.Zero;
170 if (FrictionTimescale != BSMotor.InfiniteVector)
171 {
172 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
173 // Individual friction components can be 'infinite' so compute each separately.
174 frictionFactor.X = (FrictionTimescale.X == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.X);
175 frictionFactor.Y = (FrictionTimescale.Y == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Y);
176 frictionFactor.Z = (FrictionTimescale.Z == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Z);
177 frictionFactor *= timeStep;
178 CurrentValue *= (Vector3.One - frictionFactor);
179 }
180
181 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}", 162 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}",
182 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, 163 BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
183 timeStep, error, correction); 164 timeStep, error, correction);
184 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}", 165 MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},tgt={4},curr={5}",
185 BSScene.DetailLogZero, UseName, 166 BSScene.DetailLogZero, UseName, TargetValueDecayTimeScale, decayFactor, TargetValue, CurrentValue);
186 TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor,
187 TargetValue, CurrentValue);
188 } 167 }
189 else 168 else
190 { 169 {
@@ -199,6 +178,7 @@ public class BSVMotor : BSMotor
199 MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},currTgt={4},currCurr={5}", 178 MDetailLog("{0}, BSVMotor.Step,zero,{1},origTgt={2},origCurr={3},currTgt={4},currCurr={5}",
200 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, TargetValue, CurrentValue); 179 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, TargetValue, CurrentValue);
201 } 180 }
181 LastError = error;
202 182
203 return correction; 183 return correction;
204 } 184 }
@@ -208,6 +188,8 @@ public class BSVMotor : BSMotor
208 CurrentValue = current; 188 CurrentValue = current;
209 return Step(timeStep); 189 return Step(timeStep);
210 } 190 }
191 // Given and error, computer a correction for this step.
192 // Simple scaling of the error by the timestep.
211 public virtual Vector3 StepError(float timeStep, Vector3 error) 193 public virtual Vector3 StepError(float timeStep, Vector3 error)
212 { 194 {
213 if (!Enabled) return Vector3.Zero; 195 if (!Enabled) return Vector3.Zero;
@@ -235,27 +217,27 @@ public class BSVMotor : BSMotor
235 // maximum number of outputs to generate. 217 // maximum number of outputs to generate.
236 int maxOutput = 50; 218 int maxOutput = 50;
237 MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName); 219 MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName);
238 MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},frictTS={4},eff={5},curr={6},tgt={7}", 220 MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},eff={4},curr={5},tgt={6}",
239 BSScene.DetailLogZero, UseName, 221 BSScene.DetailLogZero, UseName,
240 TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency, 222 TimeScale, TargetValueDecayTimeScale, Efficiency,
241 CurrentValue, TargetValue); 223 CurrentValue, TargetValue);
242 224
243 LastError = BSMotor.InfiniteVector; 225 LastError = BSMotor.InfiniteVector;
244 while (maxOutput-- > 0 && !LastError.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)) 226 while (maxOutput-- > 0 && !ErrorIsZero())
245 { 227 {
246 Vector3 lastStep = Step(timeStep); 228 Vector3 lastStep = Step(timeStep);
247 MDetailLog("{0},BSVMotor.Test,{1},cur={2},tgt={3},lastError={4},lastStep={5}", 229 MDetailLog("{0},BSVMotor.Test,{1},cur={2},tgt={3},lastError={4},lastStep={5}",
248 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep); 230 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep);
249 } 231 }
250 MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName); 232 MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName);
251 233
252 234
253 } 235 }
254 236
255 public override string ToString() 237 public override string ToString()
256 { 238 {
257 return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>", 239 return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4}>",
258 UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale); 240 UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale);
259 } 241 }
260} 242}
261 243
@@ -265,7 +247,6 @@ public class BSFMotor : BSMotor
265{ 247{
266 public virtual float TimeScale { get; set; } 248 public virtual float TimeScale { get; set; }
267 public virtual float TargetValueDecayTimeScale { get; set; } 249 public virtual float TargetValueDecayTimeScale { get; set; }
268 public virtual float FrictionTimescale { get; set; }
269 public virtual float Efficiency { get; set; } 250 public virtual float Efficiency { get; set; }
270 251
271 public virtual float ErrorZeroThreshold { get; set; } 252 public virtual float ErrorZeroThreshold { get; set; }
@@ -279,16 +260,15 @@ public class BSFMotor : BSMotor
279 return ErrorIsZero(LastError); 260 return ErrorIsZero(LastError);
280 } 261 }
281 public virtual bool ErrorIsZero(float err) 262 public virtual bool ErrorIsZero(float err)
282 { 263 {
283 return (err >= -ErrorZeroThreshold && err <= ErrorZeroThreshold); 264 return (err >= -ErrorZeroThreshold && err <= ErrorZeroThreshold);
284 } 265 }
285 266
286 public BSFMotor(string useName, float timeScale, float decayTimescale, float friction, float efficiency) 267 public BSFMotor(string useName, float timeScale, float decayTimescale, float efficiency)
287 : base(useName) 268 : base(useName)
288 { 269 {
289 TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite; 270 TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
290 Efficiency = 1f; 271 Efficiency = 1f;
291 FrictionTimescale = BSMotor.Infinite;
292 CurrentValue = TargetValue = 0f; 272 CurrentValue = TargetValue = 0f;
293 ErrorZeroThreshold = 0.01f; 273 ErrorZeroThreshold = 0.01f;
294 } 274 }
@@ -315,7 +295,6 @@ public class BSFMotor : BSMotor
315 295
316 float correction = 0f; 296 float correction = 0f;
317 float error = TargetValue - CurrentValue; 297 float error = TargetValue - CurrentValue;
318 LastError = error;
319 if (!ErrorIsZero(error)) 298 if (!ErrorIsZero(error))
320 { 299 {
321 correction = StepError(timeStep, error); 300 correction = StepError(timeStep, error);
@@ -331,24 +310,11 @@ public class BSFMotor : BSMotor
331 TargetValue *= (1f - decayFactor); 310 TargetValue *= (1f - decayFactor);
332 } 311 }
333 312
334 // The amount we can correct the error is reduced by the friction
335 float frictionFactor = 0f;
336 if (FrictionTimescale != BSMotor.Infinite)
337 {
338 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
339 // Individual friction components can be 'infinite' so compute each separately.
340 frictionFactor = 1f / FrictionTimescale;
341 frictionFactor *= timeStep;
342 CurrentValue *= (1f - frictionFactor);
343 }
344
345 MDetailLog("{0}, BSFMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}", 313 MDetailLog("{0}, BSFMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}",
346 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, 314 BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
347 timeStep, error, correction); 315 timeStep, error, correction);
348 MDetailLog("{0}, BSFMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}", 316 MDetailLog("{0}, BSFMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},tgt={4},curr={5}",
349 BSScene.DetailLogZero, UseName, 317 BSScene.DetailLogZero, UseName, TargetValueDecayTimeScale, decayFactor, TargetValue, CurrentValue);
350 TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor,
351 TargetValue, CurrentValue);
352 } 318 }
353 else 319 else
354 { 320 {
@@ -363,6 +329,7 @@ public class BSFMotor : BSMotor
363 MDetailLog("{0}, BSFMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}", 329 MDetailLog("{0}, BSFMotor.Step,zero,{1},origTgt={2},origCurr={3},ret={4}",
364 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue); 330 BSScene.DetailLogZero, UseName, origCurrVal, origTarget, CurrentValue);
365 } 331 }
332 LastError = error;
366 333
367 return CurrentValue; 334 return CurrentValue;
368 } 335 }
@@ -390,15 +357,15 @@ public class BSFMotor : BSMotor
390 357
391 public override string ToString() 358 public override string ToString()
392 { 359 {
393 return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>", 360 return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4}>",
394 UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale); 361 UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale);
395 } 362 }
396 363
397} 364}
398 365
399// ============================================================================ 366// ============================================================================
400// ============================================================================ 367// ============================================================================
401// Proportional, Integral, Derivitive Motor 368// Proportional, Integral, Derivitive ("PID") Motor
402// Good description at http://www.answers.com/topic/pid-controller . Includes processes for choosing p, i and d factors. 369// Good description at http://www.answers.com/topic/pid-controller . Includes processes for choosing p, i and d factors.
403public class BSPIDVMotor : BSVMotor 370public class BSPIDVMotor : BSVMotor
404{ 371{
@@ -410,7 +377,6 @@ public class BSPIDVMotor : BSVMotor
410 // The factors are vectors for the three dimensions. This is the proportional of each 377 // The factors are vectors for the three dimensions. This is the proportional of each
411 // that is applied. This could be multiplied through the actual factors but it 378 // that is applied. This could be multiplied through the actual factors but it
412 // is sometimes easier to manipulate the factors and their mix separately. 379 // is sometimes easier to manipulate the factors and their mix separately.
413 // to
414 public Vector3 FactorMix; 380 public Vector3 FactorMix;
415 381
416 // Arbritrary factor range. 382 // Arbritrary factor range.
@@ -448,14 +414,14 @@ public class BSPIDVMotor : BSVMotor
448 // If efficiency is high (1f), use a factor value that moves the error value to zero with little overshoot. 414 // If efficiency is high (1f), use a factor value that moves the error value to zero with little overshoot.
449 // If efficiency is low (0f), use a factor value that overcorrects. 415 // If efficiency is low (0f), use a factor value that overcorrects.
450 // TODO: might want to vary contribution of different factor depending on efficiency. 416 // TODO: might want to vary contribution of different factor depending on efficiency.
451 float factor = ((1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow) / 3f; 417 // float factor = ((1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow) / 3f;
452 // float factor = (1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow; 418 float factor = (1f - this.Efficiency) * EfficiencyHigh + EfficiencyLow;
453 419
454 proportionFactor = new Vector3(factor, factor, factor); 420 proportionFactor = new Vector3(factor, factor, factor);
455 integralFactor = new Vector3(factor, factor, factor); 421 integralFactor = new Vector3(factor, factor, factor);
456 derivFactor = new Vector3(factor, factor, factor); 422 derivFactor = new Vector3(factor, factor, factor);
457 423
458 MDetailLog("{0},BSPIDVMotor.setEfficiency,eff={1},factor={2}", BSScene.DetailLogZero, Efficiency, factor); 424 MDetailLog("{0}, BSPIDVMotor.setEfficiency,eff={1},factor={2}", BSScene.DetailLogZero, Efficiency, factor);
459 } 425 }
460 } 426 }
461 427
@@ -469,16 +435,15 @@ public class BSPIDVMotor : BSVMotor
469 435
470 // A simple derivitive is the rate of change from the last error. 436 // A simple derivitive is the rate of change from the last error.
471 Vector3 derivitive = (error - LastError) * timeStep; 437 Vector3 derivitive = (error - LastError) * timeStep;
472 LastError = error;
473 438
474 // Correction = (proportionOfPresentError + accumulationOfPastError + rateOfChangeOfError) 439 // Correction = (proportionOfPresentError + accumulationOfPastError + rateOfChangeOfError)
475 Vector3 ret = error * timeStep * proportionFactor * FactorMix.X 440 Vector3 ret = error / TimeScale * timeStep * proportionFactor * FactorMix.X
476 + RunningIntegration * integralFactor * FactorMix.Y 441 + RunningIntegration / TimeScale * integralFactor * FactorMix.Y
477 + derivitive * derivFactor * FactorMix.Z 442 + derivitive / TimeScale * derivFactor * FactorMix.Z
478 ; 443 ;
479 444
480 MDetailLog("{0},BSPIDVMotor.step,ts={1},err={2},runnInt={3},deriv={4},ret={5}", 445 MDetailLog("{0}, BSPIDVMotor.step,ts={1},err={2},lerr={3},runnInt={4},deriv={5},ret={6}",
481 BSScene.DetailLogZero, timeStep, error, RunningIntegration, derivitive, ret); 446 BSScene.DetailLogZero, timeStep, error, LastError, RunningIntegration, derivitive, ret);
482 447
483 return ret; 448 return ret;
484 } 449 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 385ed9e..834228e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection;
29using System.Text; 30using System.Text;
30 31
31using OpenSim.Region.Physics.Manager; 32using OpenSim.Region.Physics.Manager;
@@ -37,7 +38,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
37{ 38{
38public static class BSParam 39public static class BSParam
39{ 40{
40 private static string LogHeader = "[BULLETSIM PARAMETERS]"; 41 private static string LogHeader = "[BULLETSIM PARAMETERS]";
41 42
42 // Tuning notes: 43 // Tuning notes:
43 // From: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6575 44 // From: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6575
@@ -51,7 +52,10 @@ public static class BSParam
51 // This is separate/independent from the collision margin. The collision margin increases the object a bit 52 // This is separate/independent from the collision margin. The collision margin increases the object a bit
52 // to improve collision detection performance and accuracy. 53 // to improve collision detection performance and accuracy.
53 // =================== 54 // ===================
54 // From: 55 // From:
56
57 public static bool UseSeparatePhysicsThread { get; private set; }
58 public static float PhysicsTimeStep { get; private set; }
55 59
56 // Level of Detail values kept as float because that's what the Meshmerizer wants 60 // Level of Detail values kept as float because that's what the Meshmerizer wants
57 public static float MeshLOD { get; private set; } 61 public static float MeshLOD { get; private set; }
@@ -86,8 +90,12 @@ public static class BSParam
86 public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes 90 public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
87 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects 91 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
88 public static bool ShouldRemoveZeroWidthTriangles { get; private set; } 92 public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
93 public static bool ShouldUseBulletHACD { get; set; }
94 public static bool ShouldUseSingleConvexHullForPrims { get; set; }
95 public static bool ShouldUseGImpactShapeForPrims { get; set; }
96 public static bool ShouldUseAssetHulls { get; set; }
89 97
90 public static float TerrainImplementation { get; private set; } 98 public static float TerrainImplementation { get; set; }
91 public static int TerrainMeshMagnification { get; private set; } 99 public static int TerrainMeshMagnification { get; private set; }
92 public static float TerrainFriction { get; private set; } 100 public static float TerrainFriction { get; private set; }
93 public static float TerrainHitFraction { get; private set; } 101 public static float TerrainHitFraction { get; private set; }
@@ -112,6 +120,7 @@ public static class BSParam
112 public static float NumberOfSolverIterations { get; private set; } 120 public static float NumberOfSolverIterations { get; private set; }
113 public static bool UseSingleSidedMeshes { get; private set; } 121 public static bool UseSingleSidedMeshes { get; private set; }
114 public static float GlobalContactBreakingThreshold { get; private set; } 122 public static float GlobalContactBreakingThreshold { get; private set; }
123 public static float PhysicsUnmanLoggingFrames { get; private set; }
115 124
116 // Avatar parameters 125 // Avatar parameters
117 public static float AvatarFriction { get; private set; } 126 public static float AvatarFriction { get; private set; }
@@ -122,11 +131,18 @@ public static class BSParam
122 public static float AvatarCapsuleWidth { get; private set; } 131 public static float AvatarCapsuleWidth { get; private set; }
123 public static float AvatarCapsuleDepth { get; private set; } 132 public static float AvatarCapsuleDepth { get; private set; }
124 public static float AvatarCapsuleHeight { get; private set; } 133 public static float AvatarCapsuleHeight { get; private set; }
134 public static float AvatarHeightLowFudge { get; private set; }
135 public static float AvatarHeightMidFudge { get; private set; }
136 public static float AvatarHeightHighFudge { get; private set; }
125 public static float AvatarContactProcessingThreshold { get; private set; } 137 public static float AvatarContactProcessingThreshold { get; private set; }
138 public static float AvatarStopZeroThreshold { get; private set; }
139 public static int AvatarJumpFrames { get; private set; }
126 public static float AvatarBelowGroundUpCorrectionMeters { get; private set; } 140 public static float AvatarBelowGroundUpCorrectionMeters { get; private set; }
127 public static float AvatarStepHeight { get; private set; } 141 public static float AvatarStepHeight { get; private set; }
128 public static float AvatarStepApproachFactor { get; private set; } 142 public static float AvatarStepApproachFactor { get; private set; }
129 public static float AvatarStepForceFactor { get; private set; } 143 public static float AvatarStepForceFactor { get; private set; }
144 public static float AvatarStepUpCorrectionFactor { get; private set; }
145 public static int AvatarStepSmoothingSteps { get; private set; }
130 146
131 // Vehicle parameters 147 // Vehicle parameters
132 public static float VehicleMaxLinearVelocity { get; private set; } 148 public static float VehicleMaxLinearVelocity { get; private set; }
@@ -138,9 +154,15 @@ public static class BSParam
138 public static float VehicleRestitution { get; private set; } 154 public static float VehicleRestitution { get; private set; }
139 public static Vector3 VehicleLinearFactor { get; private set; } 155 public static Vector3 VehicleLinearFactor { get; private set; }
140 public static Vector3 VehicleAngularFactor { get; private set; } 156 public static Vector3 VehicleAngularFactor { get; private set; }
157 public static Vector3 VehicleInertiaFactor { get; private set; }
141 public static float VehicleGroundGravityFudge { get; private set; } 158 public static float VehicleGroundGravityFudge { get; private set; }
142 public static float VehicleAngularBankingTimescaleFudge { get; private set; } 159 public static float VehicleAngularBankingTimescaleFudge { get; private set; }
143 public static bool VehicleDebuggingEnabled { get; private set; } 160 public static bool VehicleEnableLinearDeflection { get; private set; }
161 public static bool VehicleLinearDeflectionNotCollidingNoZ { get; private set; }
162 public static bool VehicleEnableAngularVerticalAttraction { get; private set; }
163 public static int VehicleAngularVerticalAttractionAlgorithm { get; private set; }
164 public static bool VehicleEnableAngularDeflection { get; private set; }
165 public static bool VehicleEnableAngularBanking { get; private set; }
144 166
145 // Convex Hulls 167 // Convex Hulls
146 public static int CSHullMaxDepthSplit { get; private set; } 168 public static int CSHullMaxDepthSplit { get; private set; }
@@ -149,9 +171,19 @@ public static class BSParam
149 public static float CSHullVolumeConservationThresholdPercent { get; private set; } 171 public static float CSHullVolumeConservationThresholdPercent { get; private set; }
150 public static int CSHullMaxVertices { get; private set; } 172 public static int CSHullMaxVertices { get; private set; }
151 public static float CSHullMaxSkinWidth { get; private set; } 173 public static float CSHullMaxSkinWidth { get; private set; }
174 public static float BHullMaxVerticesPerHull { get; private set; } // 100
175 public static float BHullMinClusters { get; private set; } // 2
176 public static float BHullCompacityWeight { get; private set; } // 0.1
177 public static float BHullVolumeWeight { get; private set; } // 0.0
178 public static float BHullConcavity { get; private set; } // 100
179 public static bool BHullAddExtraDistPoints { get; private set; } // false
180 public static bool BHullAddNeighboursDistPoints { get; private set; } // false
181 public static bool BHullAddFacesPoints { get; private set; } // false
182 public static bool BHullShouldAdjustCollisionMargin { get; private set; } // false
152 183
153 // Linkset implementation parameters 184 // Linkset implementation parameters
154 public static float LinksetImplementation { get; private set; } 185 public static float LinksetImplementation { get; private set; }
186 public static bool LinksetOffsetCenterOfMass { get; private set; }
155 public static bool LinkConstraintUseFrameOffset { get; private set; } 187 public static bool LinkConstraintUseFrameOffset { get; private set; }
156 public static bool LinkConstraintEnableTransMotor { get; private set; } 188 public static bool LinkConstraintEnableTransMotor { get; private set; }
157 public static float LinkConstraintTransMotorMaxVel { get; private set; } 189 public static float LinkConstraintTransMotorMaxVel { get; private set; }
@@ -223,16 +255,41 @@ public static class BSParam
223 getter = pGetter; 255 getter = pGetter;
224 objectSet = pObjSetter; 256 objectSet = pObjSetter;
225 } 257 }
226 /* Wish I could simplify using this definition but CLR doesn't store references so closure around delegates of references won't work 258 // Simple parameter variable where property name is the same as the INI file name
227 public ParameterDefn(string pName, string pDesc, T pDefault, ref T loc) 259 // and the value is only a simple get and set.
260 public ParameterDefn(string pName, string pDesc, T pDefault)
228 : base(pName, pDesc) 261 : base(pName, pDesc)
229 { 262 {
230 defaultValue = pDefault; 263 defaultValue = pDefault;
231 setter = (s, v) => { loc = v; }; 264 setter = (s, v) => { SetValueByName(s, name, v); };
232 getter = (s) => { return loc; }; 265 getter = (s) => { return GetValueByName(s, name); };
233 objectSet = null; 266 objectSet = null;
234 } 267 }
235 */ 268 // Use reflection to find the property named 'pName' in BSParam and assign 'val' to same.
269 private void SetValueByName(BSScene s, string pName, T val)
270 {
271 PropertyInfo prop = typeof(BSParam).GetProperty(pName, BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
272 if (prop == null)
273 {
274 // This should only be output when someone adds a new INI parameter and misspells the name.
275 s.Logger.ErrorFormat("{0} SetValueByName: did not find '{1}'. Verify specified property name is the same as the given INI parameters name.", LogHeader, pName);
276 }
277 else
278 {
279 prop.SetValue(null, val, null);
280 }
281 }
282 // Use reflection to find the property named 'pName' in BSParam and return the value in same.
283 private T GetValueByName(BSScene s, string pName)
284 {
285 PropertyInfo prop = typeof(BSParam).GetProperty(pName, BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
286 if (prop == null)
287 {
288 // This should only be output when someone adds a new INI parameter and misspells the name.
289 s.Logger.ErrorFormat("{0} GetValueByName: did not find '{1}'. Verify specified property name is the same as the given INI parameter name.", LogHeader, pName);
290 }
291 return (T)prop.GetValue(null, null);
292 }
236 public override void AssignDefault(BSScene s) 293 public override void AssignDefault(BSScene s)
237 { 294 {
238 setter(s, defaultValue); 295 setter(s, defaultValue);
@@ -309,6 +366,11 @@ public static class BSParam
309 // v = value (appropriate type) 366 // v = value (appropriate type)
310 private static ParameterDefnBase[] ParameterDefinitions = 367 private static ParameterDefnBase[] ParameterDefinitions =
311 { 368 {
369 new ParameterDefn<bool>("UseSeparatePhysicsThread", "If 'true', the physics engine runs independent from the simulator heartbeat",
370 false ),
371 new ParameterDefn<float>("PhysicsTimeStep", "If separate thread, seconds to simulate each interval",
372 0.089f ),
373
312 new ParameterDefn<bool>("MeshSculptedPrim", "Whether to create meshes for sculpties", 374 new ParameterDefn<bool>("MeshSculptedPrim", "Whether to create meshes for sculpties",
313 true, 375 true,
314 (s) => { return ShouldMeshSculptedPrim; }, 376 (s) => { return ShouldMeshSculptedPrim; },
@@ -322,18 +384,20 @@ public static class BSParam
322 (s) => { return ShouldUseHullsForPhysicalObjects; }, 384 (s) => { return ShouldUseHullsForPhysicalObjects; },
323 (s,v) => { ShouldUseHullsForPhysicalObjects = v; } ), 385 (s,v) => { ShouldUseHullsForPhysicalObjects = v; } ),
324 new ParameterDefn<bool>("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes", 386 new ParameterDefn<bool>("ShouldRemoveZeroWidthTriangles", "If true, remove degenerate triangles from meshes",
325 true, 387 true ),
326 (s) => { return ShouldRemoveZeroWidthTriangles; }, 388 new ParameterDefn<bool>("ShouldUseBulletHACD", "If true, use the Bullet version of HACD",
327 (s,v) => { ShouldRemoveZeroWidthTriangles = v; } ), 389 false ),
390 new ParameterDefn<bool>("ShouldUseSingleConvexHullForPrims", "If true, use a single convex hull shape for physical prims",
391 true ),
392 new ParameterDefn<bool>("ShouldUseGImpactShapeForPrims", "If true, use a GImpact shape for prims with cuts and twists",
393 false ),
394 new ParameterDefn<bool>("ShouldUseAssetHulls", "If true, use hull if specified in the mesh asset info",
395 true ),
328 396
329 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions", 397 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
330 5, 398 5 ),
331 (s) => { return CrossingFailuresBeforeOutOfBounds; },
332 (s,v) => { CrossingFailuresBeforeOutOfBounds = v; } ),
333 new ParameterDefn<float>("UpdateVelocityChangeThreshold", "Change in updated velocity required before reporting change to simulator", 399 new ParameterDefn<float>("UpdateVelocityChangeThreshold", "Change in updated velocity required before reporting change to simulator",
334 0.1f, 400 0.1f ),
335 (s) => { return UpdateVelocityChangeThreshold; },
336 (s,v) => { UpdateVelocityChangeThreshold = v; } ),
337 401
338 new ParameterDefn<float>("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 402 new ParameterDefn<float>("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
339 32f, 403 32f,
@@ -399,26 +463,22 @@ public static class BSParam
399 (s) => { return MaxAddForceMagnitude; }, 463 (s) => { return MaxAddForceMagnitude; },
400 (s,v) => { MaxAddForceMagnitude = v; MaxAddForceMagnitudeSquared = v * v; } ), 464 (s,v) => { MaxAddForceMagnitude = v; MaxAddForceMagnitudeSquared = v * v; } ),
401 // Density is passed around as 100kg/m3. This scales that to 1kg/m3. 465 // Density is passed around as 100kg/m3. This scales that to 1kg/m3.
466 // Reduce by power of 100 because Bullet doesn't seem to handle objects with large mass very well
402 new ParameterDefn<float>("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)", 467 new ParameterDefn<float>("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)",
403 0.01f, 468 0.01f ),
404 (s) => { return DensityScaleFactor; },
405 (s,v) => { DensityScaleFactor = v; } ),
406 469
407 new ParameterDefn<float>("PID_D", "Derivitive factor for motion smoothing", 470 new ParameterDefn<float>("PID_D", "Derivitive factor for motion smoothing",
408 2200f, 471 2200f ),
409 (s) => { return (float)PID_D; },
410 (s,v) => { PID_D = v; } ),
411 new ParameterDefn<float>("PID_P", "Parameteric factor for motion smoothing", 472 new ParameterDefn<float>("PID_P", "Parameteric factor for motion smoothing",
412 900f, 473 900f ),
413 (s) => { return (float)PID_P; },
414 (s,v) => { PID_P = v; } ),
415 474
416 new ParameterDefn<float>("DefaultFriction", "Friction factor used on new objects", 475 new ParameterDefn<float>("DefaultFriction", "Friction factor used on new objects",
417 0.2f, 476 0.2f,
418 (s) => { return DefaultFriction; }, 477 (s) => { return DefaultFriction; },
419 (s,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ), 478 (s,v) => { DefaultFriction = v; s.UnmanagedParams[0].defaultFriction = v; } ),
479 // For historical reasons, the viewer and simulator multiply the density by 100
420 new ParameterDefn<float>("DefaultDensity", "Density for new objects" , 480 new ParameterDefn<float>("DefaultDensity", "Density for new objects" ,
421 10.000006836f, // Aluminum g/cm3 481 1000.0006836f, // Aluminum g/cm3 * 100
422 (s) => { return DefaultDensity; }, 482 (s) => { return DefaultDensity; },
423 (s,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ), 483 (s,v) => { DefaultDensity = v; s.UnmanagedParams[0].defaultDensity = v; } ),
424 new ParameterDefn<float>("DefaultRestitution", "Bouncyness of an object" , 484 new ParameterDefn<float>("DefaultRestitution", "Bouncyness of an object" ,
@@ -478,86 +538,61 @@ public static class BSParam
478 (s,o) => { s.PE.SetContactProcessingThreshold(o.PhysBody, ContactProcessingThreshold); } ), 538 (s,o) => { s.PE.SetContactProcessingThreshold(o.PhysBody, ContactProcessingThreshold); } ),
479 539
480 new ParameterDefn<float>("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)", 540 new ParameterDefn<float>("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
481 (float)BSTerrainPhys.TerrainImplementation.Mesh, 541 (float)BSTerrainPhys.TerrainImplementation.Mesh ),
482 (s) => { return TerrainImplementation; },
483 (s,v) => { TerrainImplementation = v; } ),
484 new ParameterDefn<int>("TerrainMeshMagnification", "Number of times the 256x256 heightmap is multiplied to create the terrain mesh" , 542 new ParameterDefn<int>("TerrainMeshMagnification", "Number of times the 256x256 heightmap is multiplied to create the terrain mesh" ,
485 2, 543 2 ),
486 (s) => { return TerrainMeshMagnification; },
487 (s,v) => { TerrainMeshMagnification = v; } ),
488 new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" , 544 new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,
489 0.3f, 545 0.3f ),
490 (s) => { return TerrainFriction; },
491 (s,v) => { TerrainFriction = v; /* TODO: set on real terrain */} ),
492 new ParameterDefn<float>("TerrainHitFraction", "Distance to measure hit collisions" , 546 new ParameterDefn<float>("TerrainHitFraction", "Distance to measure hit collisions" ,
493 0.8f, 547 0.8f ),
494 (s) => { return TerrainHitFraction; },
495 (s,v) => { TerrainHitFraction = v; /* TODO: set on real terrain */ } ),
496 new ParameterDefn<float>("TerrainRestitution", "Bouncyness" , 548 new ParameterDefn<float>("TerrainRestitution", "Bouncyness" ,
497 0f, 549 0f ),
498 (s) => { return TerrainRestitution; },
499 (s,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
500 new ParameterDefn<float>("TerrainContactProcessingThreshold", "Distance from terrain to stop processing collisions" , 550 new ParameterDefn<float>("TerrainContactProcessingThreshold", "Distance from terrain to stop processing collisions" ,
501 0.0f, 551 0.0f ),
502 (s) => { return TerrainContactProcessingThreshold; },
503 (s,v) => { TerrainContactProcessingThreshold = v; /* TODO: set on real terrain */ } ),
504 new ParameterDefn<float>("TerrainCollisionMargin", "Margin where collision checking starts" , 552 new ParameterDefn<float>("TerrainCollisionMargin", "Margin where collision checking starts" ,
505 0.08f, 553 0.08f ),
506 (s) => { return TerrainCollisionMargin; },
507 (s,v) => { TerrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
508 554
509 new ParameterDefn<float>("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 555 new ParameterDefn<float>("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
510 0.2f, 556 0.2f ),
511 (s) => { return AvatarFriction; },
512 (s,v) => { AvatarFriction = v; } ),
513 new ParameterDefn<float>("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", 557 new ParameterDefn<float>("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
514 0.95f, 558 0.95f ),
515 (s) => { return AvatarStandingFriction; },
516 (s,v) => { AvatarStandingFriction = v; } ),
517 new ParameterDefn<float>("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run", 559 new ParameterDefn<float>("AvatarAlwaysRunFactor", "Speed multiplier if avatar is set to always run",
518 1.3f, 560 1.3f ),
519 (s) => { return AvatarAlwaysRunFactor; }, 561 // For historical reasons, density is reported * 100
520 (s,v) => { AvatarAlwaysRunFactor = v; } ), 562 new ParameterDefn<float>("AvatarDensity", "Density of an avatar. Changed on avatar recreation. Scaled times 100.",
521 new ParameterDefn<float>("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 563 3500f) , // 3.5 * 100
522 3.5f,
523 (s) => { return AvatarDensity; },
524 (s,v) => { AvatarDensity = v; } ),
525 new ParameterDefn<float>("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", 564 new ParameterDefn<float>("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
526 0f, 565 0f ),
527 (s) => { return AvatarRestitution; },
528 (s,v) => { AvatarRestitution = v; } ),
529 new ParameterDefn<float>("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule", 566 new ParameterDefn<float>("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
530 0.6f, 567 0.6f ) ,
531 (s) => { return AvatarCapsuleWidth; },
532 (s,v) => { AvatarCapsuleWidth = v; } ),
533 new ParameterDefn<float>("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule", 568 new ParameterDefn<float>("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
534 0.45f, 569 0.45f ),
535 (s) => { return AvatarCapsuleDepth; },
536 (s,v) => { AvatarCapsuleDepth = v; } ),
537 new ParameterDefn<float>("AvatarCapsuleHeight", "Default height of space around avatar", 570 new ParameterDefn<float>("AvatarCapsuleHeight", "Default height of space around avatar",
538 1.5f, 571 1.5f ),
539 (s) => { return AvatarCapsuleHeight; }, 572 new ParameterDefn<float>("AvatarHeightLowFudge", "A fudge factor to make small avatars stand on the ground",
540 (s,v) => { AvatarCapsuleHeight = v; } ), 573 -0.2f ),
574 new ParameterDefn<float>("AvatarHeightMidFudge", "A fudge distance to adjust average sized avatars to be standing on ground",
575 0.1f ),
576 new ParameterDefn<float>("AvatarHeightHighFudge", "A fudge factor to make tall avatars stand on the ground",
577 0.1f ),
541 new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 578 new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
542 0.1f, 579 0.1f ),
543 (s) => { return AvatarContactProcessingThreshold; }, 580 new ParameterDefn<float>("AvatarStopZeroThreshold", "Movement velocity below which avatar is assumed to be stopped",
544 (s,v) => { AvatarContactProcessingThreshold = v; } ), 581 0.1f ),
545 new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", 582 new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
546 1.0f, 583 1.0f ),
547 (s) => { return AvatarBelowGroundUpCorrectionMeters; }, 584 new ParameterDefn<int>("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.",
548 (s,v) => { AvatarBelowGroundUpCorrectionMeters = v; } ), 585 4 ),
549 new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction", 586 new ParameterDefn<float>("AvatarStepHeight", "Height of a step obstacle to consider step correction",
550 0.3f, 587 0.6f ) ,
551 (s) => { return AvatarStepHeight; },
552 (s,v) => { AvatarStepHeight = v; } ),
553 new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)", 588 new ParameterDefn<float>("AvatarStepApproachFactor", "Factor to control angle of approach to step (0=straight on)",
554 0.6f, 589 0.6f ),
555 (s) => { return AvatarStepApproachFactor; },
556 (s,v) => { AvatarStepApproachFactor = v; } ),
557 new ParameterDefn<float>("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step", 590 new ParameterDefn<float>("AvatarStepForceFactor", "Controls the amount of force up applied to step up onto a step",
558 2.0f, 591 1.0f ),
559 (s) => { return AvatarStepForceFactor; }, 592 new ParameterDefn<float>("AvatarStepUpCorrectionFactor", "Multiplied by height of step collision to create up movement at step",
560 (s,v) => { AvatarStepForceFactor = v; } ), 593 1.0f ),
594 new ParameterDefn<int>("AvatarStepSmoothingSteps", "Number of frames after a step collision that we continue walking up stairs",
595 2 ),
561 596
562 new ParameterDefn<float>("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle", 597 new ParameterDefn<float>("VehicleMaxLinearVelocity", "Maximum velocity magnitude that can be assigned to a vehicle",
563 1000.0f, 598 1000.0f,
@@ -568,37 +603,33 @@ public static class BSParam
568 (s) => { return (float)VehicleMaxAngularVelocity; }, 603 (s) => { return (float)VehicleMaxAngularVelocity; },
569 (s,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ), 604 (s,v) => { VehicleMaxAngularVelocity = v; VehicleMaxAngularVelocitySq = v * v; } ),
570 new ParameterDefn<float>("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)", 605 new ParameterDefn<float>("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
571 0.0f, 606 0.0f ),
572 (s) => { return VehicleAngularDamping; },
573 (s,v) => { VehicleAngularDamping = v; } ),
574 new ParameterDefn<Vector3>("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (<0,0,0> to <1,1,1>)", 607 new ParameterDefn<Vector3>("VehicleLinearFactor", "Fraction of physical linear changes applied to vehicle (<0,0,0> to <1,1,1>)",
575 new Vector3(1f, 1f, 1f), 608 new Vector3(1f, 1f, 1f) ),
576 (s) => { return VehicleLinearFactor; },
577 (s,v) => { VehicleLinearFactor = v; } ),
578 new ParameterDefn<Vector3>("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (<0,0,0> to <1,1,1>)", 609 new ParameterDefn<Vector3>("VehicleAngularFactor", "Fraction of physical angular changes applied to vehicle (<0,0,0> to <1,1,1>)",
579 new Vector3(1f, 1f, 1f), 610 new Vector3(1f, 1f, 1f) ),
580 (s) => { return VehicleAngularFactor; }, 611 new ParameterDefn<Vector3>("VehicleInertiaFactor", "Fraction of physical inertia applied (<0,0,0> to <1,1,1>)",
581 (s,v) => { VehicleAngularFactor = v; } ), 612 new Vector3(1f, 1f, 1f) ),
582 new ParameterDefn<float>("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)", 613 new ParameterDefn<float>("VehicleFriction", "Friction of vehicle on the ground (0.0 - 1.0)",
583 0.0f, 614 0.0f ),
584 (s) => { return VehicleFriction; },
585 (s,v) => { VehicleFriction = v; } ),
586 new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)", 615 new ParameterDefn<float>("VehicleRestitution", "Bouncyness factor for vehicles (0.0 - 1.0)",
587 0.0f, 616 0.0f ),
588 (s) => { return VehicleRestitution; },
589 (s,v) => { VehicleRestitution = v; } ),
590 new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiply gravity if a ground vehicle is probably on the ground (0.0 - 1.0)", 617 new ParameterDefn<float>("VehicleGroundGravityFudge", "Factor to multiply gravity if a ground vehicle is probably on the ground (0.0 - 1.0)",
591 0.2f, 618 0.2f ),
592 (s) => { return VehicleGroundGravityFudge; },
593 (s,v) => { VehicleGroundGravityFudge = v; } ),
594 new ParameterDefn<float>("VehicleAngularBankingTimescaleFudge", "Factor to multiple angular banking timescale. Tune to increase realism.", 619 new ParameterDefn<float>("VehicleAngularBankingTimescaleFudge", "Factor to multiple angular banking timescale. Tune to increase realism.",
595 60.0f, 620 60.0f ),
596 (s) => { return VehicleAngularBankingTimescaleFudge; }, 621 new ParameterDefn<bool>("VehicleEnableLinearDeflection", "Turn on/off vehicle linear deflection effect",
597 (s,v) => { VehicleAngularBankingTimescaleFudge = v; } ), 622 true ),
598 new ParameterDefn<bool>("VehicleDebuggingEnable", "Turn on/off vehicle debugging", 623 new ParameterDefn<bool>("VehicleLinearDeflectionNotCollidingNoZ", "Turn on/off linear deflection Z effect on non-colliding vehicles",
599 false, 624 true ),
600 (s) => { return VehicleDebuggingEnabled; }, 625 new ParameterDefn<bool>("VehicleEnableAngularVerticalAttraction", "Turn on/off vehicle angular vertical attraction effect",
601 (s,v) => { VehicleDebuggingEnabled = v; } ), 626 true ),
627 new ParameterDefn<int>("VehicleAngularVerticalAttractionAlgorithm", "Select vertical attraction algo. You need to look at the source.",
628 0 ),
629 new ParameterDefn<bool>("VehicleEnableAngularDeflection", "Turn on/off vehicle angular deflection effect",
630 true ),
631 new ParameterDefn<bool>("VehicleEnableAngularBanking", "Turn on/off vehicle angular banking effect",
632 true ),
602 633
603 new ParameterDefn<float>("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", 634 new ParameterDefn<float>("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
604 0f, 635 0f,
@@ -611,7 +642,7 @@ public static class BSParam
611 new ParameterDefn<bool>("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", 642 new ParameterDefn<bool>("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
612 false, 643 false,
613 (s) => { return ShouldDisableContactPoolDynamicAllocation; }, 644 (s) => { return ShouldDisableContactPoolDynamicAllocation; },
614 (s,v) => { ShouldDisableContactPoolDynamicAllocation = v; 645 (s,v) => { ShouldDisableContactPoolDynamicAllocation = v;
615 s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = NumericBool(v); } ), 646 s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = NumericBool(v); } ),
616 new ParameterDefn<bool>("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", 647 new ParameterDefn<bool>("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
617 false, 648 false,
@@ -641,64 +672,61 @@ public static class BSParam
641 0f, 672 0f,
642 (s) => { return GlobalContactBreakingThreshold; }, 673 (s) => { return GlobalContactBreakingThreshold; },
643 (s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ), 674 (s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ),
675 new ParameterDefn<float>("PhysicsUnmanLoggingFrames", "If non-zero, frames between output of detailed unmanaged physics statistics",
676 0f,
677 (s) => { return PhysicsUnmanLoggingFrames; },
678 (s,v) => { PhysicsUnmanLoggingFrames = v; s.UnmanagedParams[0].physicsLoggingFrames = v; } ),
644 679
645 new ParameterDefn<int>("CSHullMaxDepthSplit", "CS impl: max depth to split for hull. 1-10 but > 7 is iffy", 680 new ParameterDefn<int>("CSHullMaxDepthSplit", "CS impl: max depth to split for hull. 1-10 but > 7 is iffy",
646 7, 681 7 ),
647 (s) => { return CSHullMaxDepthSplit; },
648 (s,v) => { CSHullMaxDepthSplit = v; } ),
649 new ParameterDefn<int>("CSHullMaxDepthSplitForSimpleShapes", "CS impl: max depth setting for simple prim shapes", 682 new ParameterDefn<int>("CSHullMaxDepthSplitForSimpleShapes", "CS impl: max depth setting for simple prim shapes",
650 2, 683 2 ),
651 (s) => { return CSHullMaxDepthSplitForSimpleShapes; },
652 (s,v) => { CSHullMaxDepthSplitForSimpleShapes = v; } ),
653 new ParameterDefn<float>("CSHullConcavityThresholdPercent", "CS impl: concavity threshold percent (0-20)", 684 new ParameterDefn<float>("CSHullConcavityThresholdPercent", "CS impl: concavity threshold percent (0-20)",
654 5f, 685 5f ),
655 (s) => { return CSHullConcavityThresholdPercent; },
656 (s,v) => { CSHullConcavityThresholdPercent = v; } ),
657 new ParameterDefn<float>("CSHullVolumeConservationThresholdPercent", "percent volume conservation to collapse hulls (0-30)", 686 new ParameterDefn<float>("CSHullVolumeConservationThresholdPercent", "percent volume conservation to collapse hulls (0-30)",
658 5f, 687 5f ),
659 (s) => { return CSHullVolumeConservationThresholdPercent; },
660 (s,v) => { CSHullVolumeConservationThresholdPercent = v; } ),
661 new ParameterDefn<int>("CSHullMaxVertices", "CS impl: maximum number of vertices in output hulls. Keep < 50.", 688 new ParameterDefn<int>("CSHullMaxVertices", "CS impl: maximum number of vertices in output hulls. Keep < 50.",
662 32, 689 32 ),
663 (s) => { return CSHullMaxVertices; },
664 (s,v) => { CSHullMaxVertices = v; } ),
665 new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.", 690 new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.",
666 0, 691 0f ),
667 (s) => { return CSHullMaxSkinWidth; }, 692
668 (s,v) => { CSHullMaxSkinWidth = v; } ), 693 new ParameterDefn<float>("BHullMaxVerticesPerHull", "Bullet impl: max number of vertices per created hull",
694 200f ),
695 new ParameterDefn<float>("BHullMinClusters", "Bullet impl: minimum number of hulls to create per mesh",
696 10f ),
697 new ParameterDefn<float>("BHullCompacityWeight", "Bullet impl: weight factor for how compact to make hulls",
698 20f ),
699 new ParameterDefn<float>("BHullVolumeWeight", "Bullet impl: weight factor for volume in created hull",
700 0.1f ),
701 new ParameterDefn<float>("BHullConcavity", "Bullet impl: weight factor for how convex a created hull can be",
702 10f ),
703 new ParameterDefn<bool>("BHullAddExtraDistPoints", "Bullet impl: whether to add extra vertices for long distance vectors",
704 true ),
705 new ParameterDefn<bool>("BHullAddNeighboursDistPoints", "Bullet impl: whether to add extra vertices between neighbor hulls",
706 true ),
707 new ParameterDefn<bool>("BHullAddFacesPoints", "Bullet impl: whether to add extra vertices to break up hull faces",
708 true ),
709 new ParameterDefn<bool>("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin",
710 false ),
669 711
670 new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", 712 new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
671 (float)BSLinkset.LinksetImplementation.Compound, 713 (float)BSLinkset.LinksetImplementation.Compound ),
672 (s) => { return LinksetImplementation; }, 714 new ParameterDefn<bool>("LinksetOffsetCenterOfMass", "If 'true', compute linkset center-of-mass and offset linkset position to account for same",
673 (s,v) => { LinksetImplementation = v; } ), 715 true ),
674 new ParameterDefn<bool>("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", 716 new ParameterDefn<bool>("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
675 false, 717 false ),
676 (s) => { return LinkConstraintUseFrameOffset; },
677 (s,v) => { LinkConstraintUseFrameOffset = v; } ),
678 new ParameterDefn<bool>("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints", 718 new ParameterDefn<bool>("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
679 true, 719 true ),
680 (s) => { return LinkConstraintEnableTransMotor; },
681 (s,v) => { LinkConstraintEnableTransMotor = v; } ),
682 new ParameterDefn<float>("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints", 720 new ParameterDefn<float>("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
683 5.0f, 721 5.0f ),
684 (s) => { return LinkConstraintTransMotorMaxVel; },
685 (s,v) => { LinkConstraintTransMotorMaxVel = v; } ),
686 new ParameterDefn<float>("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints", 722 new ParameterDefn<float>("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
687 0.1f, 723 0.1f ),
688 (s) => { return LinkConstraintTransMotorMaxForce; },
689 (s,v) => { LinkConstraintTransMotorMaxForce = v; } ),
690 new ParameterDefn<float>("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", 724 new ParameterDefn<float>("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
691 0.1f, 725 0.1f ),
692 (s) => { return LinkConstraintCFM; },
693 (s,v) => { LinkConstraintCFM = v; } ),
694 new ParameterDefn<float>("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", 726 new ParameterDefn<float>("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
695 0.1f, 727 0.1f ),
696 (s) => { return LinkConstraintERP; },
697 (s,v) => { LinkConstraintERP = v; } ),
698 new ParameterDefn<float>("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", 728 new ParameterDefn<float>("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
699 40, 729 40 ),
700 (s) => { return LinkConstraintSolverIterations; },
701 (s,v) => { LinkConstraintSolverIterations = v; } ),
702 730
703 new ParameterDefn<int>("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)", 731 new ParameterDefn<int>("PhysicsMetricFrames", "Frames between outputting detailed phys metrics. (0 is off)",
704 0, 732 0,
@@ -707,7 +735,7 @@ public static class BSParam
707 new ParameterDefn<float>("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool", 735 new ParameterDefn<float>("ResetBroadphasePool", "Setting this is any value resets the broadphase collision pool",
708 0f, 736 0f,
709 (s) => { return 0f; }, 737 (s) => { return 0f; },
710 (s,v) => { BSParam.ResetBroadphasePoolTainted(s, v); } ), 738 (s,v) => { BSParam.ResetBroadphasePoolTainted(s, v, false /* inTaintTime */); } ),
711 new ParameterDefn<float>("ResetConstraintSolver", "Setting this is any value resets the constraint solver", 739 new ParameterDefn<float>("ResetConstraintSolver", "Setting this is any value resets the constraint solver",
712 0f, 740 0f,
713 (s) => { return 0f; }, 741 (s) => { return 0f; },
@@ -793,10 +821,10 @@ public static class BSParam
793 // ===================================================================== 821 // =====================================================================
794 // There are parameters that, when set, cause things to happen in the physics engine. 822 // There are parameters that, when set, cause things to happen in the physics engine.
795 // This causes the broadphase collision cache to be cleared. 823 // This causes the broadphase collision cache to be cleared.
796 private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v) 824 private static void ResetBroadphasePoolTainted(BSScene pPhysScene, float v, bool inTaintTime)
797 { 825 {
798 BSScene physScene = pPhysScene; 826 BSScene physScene = pPhysScene;
799 physScene.TaintedObject("BSParam.ResetBroadphasePoolTainted", delegate() 827 physScene.TaintedObject(inTaintTime, "BSParam.ResetBroadphasePoolTainted", delegate()
800 { 828 {
801 physScene.PE.ResetBroadphasePool(physScene.World); 829 physScene.PE.ResetBroadphasePool(physScene.World);
802 }); 830 });
@@ -806,7 +834,7 @@ public static class BSParam
806 private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v) 834 private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v)
807 { 835 {
808 BSScene physScene = pPhysScene; 836 BSScene physScene = pPhysScene;
809 physScene.TaintedObject("BSParam.ResetConstraintSolver", delegate() 837 physScene.TaintedObject(BSScene.DetailLogZero, "BSParam.ResetConstraintSolver", delegate()
810 { 838 {
811 physScene.PE.ResetConstraintSolver(physScene.World); 839 physScene.PE.ResetConstraintSolver(physScene.World);
812 }); 840 });
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 98ea833..f89b376 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -38,12 +38,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
38 * Class to wrap all objects. 38 * Class to wrap all objects.
39 * The rest of BulletSim doesn't need to keep checking for avatars or prims 39 * The rest of BulletSim doesn't need to keep checking for avatars or prims
40 * unless the difference is significant. 40 * unless the difference is significant.
41 * 41 *
42 * Variables in the physicsl objects are in three forms: 42 * Variables in the physicsl objects are in three forms:
43 * VariableName: used by the simulator and performs taint operations, etc 43 * VariableName: used by the simulator and performs taint operations, etc
44 * RawVariableName: direct reference to the BulletSim storage for the variable value 44 * RawVariableName: direct reference to the BulletSim storage for the variable value
45 * ForceVariableName: direct reference (store and fetch) to the value in the physics engine. 45 * ForceVariableName: direct reference (store and fetch) to the value in the physics engine.
46 * The last two (and certainly the last one) should be referenced only in taint-time. 46 * The last one should only be referenced in taint-time.
47 */ 47 */
48 48
49/* 49/*
@@ -52,7 +52,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce 52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce
53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse 53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse
54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v 54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v
55 * BS.ApplyCentralForce BS.ApplyTorque 55 * BS.ApplyCentralForce BS.ApplyTorque
56 */ 56 */
57 57
58// Flags used to denote which properties updates when making UpdateProperties calls to linksets, etc. 58// Flags used to denote which properties updates when making UpdateProperties calls to linksets, etc.
@@ -72,22 +72,27 @@ public abstract class BSPhysObject : PhysicsActor
72 } 72 }
73 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName) 73 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName)
74 { 74 {
75 PhysicsScene = parentScene; 75 IsInitialized = false;
76
77 PhysScene = parentScene;
76 LocalID = localID; 78 LocalID = localID;
77 PhysObjectName = name; 79 PhysObjectName = name;
78 Name = name; // PhysicsActor also has the name of the object. Someday consolidate. 80 Name = name; // PhysicsActor also has the name of the object. Someday consolidate.
79 TypeName = typeName; 81 TypeName = typeName;
80 82
81 // The collection of things that push me around 83 // The collection of things that push me around
82 PhysicalActors = new BSActorCollection(PhysicsScene); 84 PhysicalActors = new BSActorCollection(PhysScene);
83 85
84 // Initialize variables kept in base. 86 // Initialize variables kept in base.
85 GravModifier = 1.0f; 87 GravModifier = 1.0f;
86 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity); 88 Gravity = new OMV.Vector3(0f, 0f, BSParam.Gravity);
89 HoverActive = false;
87 90
88 // We don't have any physical representation yet. 91 // We don't have any physical representation yet.
89 PhysBody = new BulletBody(localID); 92 PhysBody = new BulletBody(localID);
90 PhysShape = new BulletShape(); 93 PhysShape = new BSShapeNull();
94
95 UserSetCenterOfMassDisplacement = null;
91 96
92 PrimAssetState = PrimAssetCondition.Unknown; 97 PrimAssetState = PrimAssetCondition.Unknown;
93 98
@@ -95,34 +100,41 @@ public abstract class BSPhysObject : PhysicsActor
95 SetMaterial((int)MaterialAttributes.Material.Wood); 100 SetMaterial((int)MaterialAttributes.Material.Wood);
96 101
97 CollisionCollection = new CollisionEventUpdate(); 102 CollisionCollection = new CollisionEventUpdate();
98 CollisionsLastTick = CollisionCollection; 103 CollisionsLastReported = CollisionCollection;
104 CollisionsLastTick = new CollisionEventUpdate();
105 CollisionsLastTickStep = -1;
106
99 SubscribedEventsMs = 0; 107 SubscribedEventsMs = 0;
100 CollidingStep = 0; 108 // Crazy values that will never be true
101 CollidingGroundStep = 0; 109 CollidingStep = BSScene.NotASimulationStep;
102 CollisionAccumulation = 0; 110 CollidingGroundStep = BSScene.NotASimulationStep;
111 CollisionAccumulation = BSScene.NotASimulationStep;
103 ColliderIsMoving = false; 112 ColliderIsMoving = false;
104 CollisionScore = 0; 113 CollisionScore = 0;
105 114
106 // All axis free. 115 // All axis free.
107 LockedAxis = LockedAxisFree; 116 LockedLinearAxis = LockedAxisFree;
117 LockedAngularAxis = LockedAxisFree;
108 } 118 }
109 119
110 // Tell the object to clean up. 120 // Tell the object to clean up.
111 public virtual void Destroy() 121 public virtual void Destroy()
112 { 122 {
113 UnRegisterAllPreStepActions(); 123 PhysicalActors.Enable(false);
114 UnRegisterAllPostStepActions(); 124 PhysScene.TaintedObject(LocalID, "BSPhysObject.Destroy", delegate()
115 PhysicsScene.TaintedObject("BSPhysObject.Destroy", delegate()
116 { 125 {
117 PhysicalActors.Release(); 126 PhysicalActors.Dispose();
118 }); 127 });
119 } 128 }
120 129
121 public BSScene PhysicsScene { get; protected set; } 130 public BSScene PhysScene { get; protected set; }
122 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor 131 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
123 public string PhysObjectName { get; protected set; } 132 public string PhysObjectName { get; protected set; }
124 public string TypeName { get; protected set; } 133 public string TypeName { get; protected set; }
125 134
135 // Set to 'true' when the object is completely initialized.
136 // This mostly prevents property updates and collisions until the object is completely here.
137 public bool IsInitialized { get; protected set; }
126 138
127 // Return the object mass without calculating it or having side effects 139 // Return the object mass without calculating it or having side effects
128 public abstract float RawMass { get; } 140 public abstract float RawMass { get; }
@@ -138,26 +150,19 @@ public abstract class BSPhysObject : PhysicsActor
138 // Reference to the physical body (btCollisionObject) of this object 150 // Reference to the physical body (btCollisionObject) of this object
139 public BulletBody PhysBody; 151 public BulletBody PhysBody;
140 // Reference to the physical shape (btCollisionShape) of this object 152 // Reference to the physical shape (btCollisionShape) of this object
141 public BulletShape PhysShape; 153 public BSShape PhysShape;
142 154
143 // The physical representation of the prim might require an asset fetch. 155 // The physical representation of the prim might require an asset fetch.
144 // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'. 156 // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
145 public enum PrimAssetCondition 157 public enum PrimAssetCondition
146 { 158 {
147 Unknown, Waiting, Failed, Fetched 159 Unknown, Waiting, FailedAssetFetch, FailedMeshing, Fetched
148 } 160 }
149 public PrimAssetCondition PrimAssetState { get; set; } 161 public PrimAssetCondition PrimAssetState { get; set; }
150 162
151 // The objects base shape information. Null if not a prim type shape. 163 // The objects base shape information. Null if not a prim type shape.
152 public PrimitiveBaseShape BaseShape { get; protected set; } 164 public PrimitiveBaseShape BaseShape { get; protected set; }
153 165
154 // Some types of objects have preferred physical representations.
155 // Returns SHAPE_UNKNOWN if there is no preference.
156 public virtual BSPhysicsShapeType PreferredPhysicalShape
157 {
158 get { return BSPhysicsShapeType.SHAPE_UNKNOWN; }
159 }
160
161 // When the physical properties are updated, an EntityProperty holds the update values. 166 // When the physical properties are updated, an EntityProperty holds the update values.
162 // Keep the current and last EntityProperties to enable computation of differences 167 // Keep the current and last EntityProperties to enable computation of differences
163 // between the current update and the previous values. 168 // between the current update and the previous values.
@@ -175,6 +180,7 @@ public abstract class BSPhysObject : PhysicsActor
175 public abstract bool IsSolid { get; } 180 public abstract bool IsSolid { get; }
176 public abstract bool IsStatic { get; } 181 public abstract bool IsStatic { get; }
177 public abstract bool IsSelected { get; } 182 public abstract bool IsSelected { get; }
183 public abstract bool IsVolumeDetect { get; }
178 184
179 // Materialness 185 // Materialness
180 public MaterialAttributes.Material Material { get; private set; } 186 public MaterialAttributes.Material Material { get; private set; }
@@ -183,13 +189,27 @@ public abstract class BSPhysObject : PhysicsActor
183 Material = (MaterialAttributes.Material)material; 189 Material = (MaterialAttributes.Material)material;
184 190
185 // Setting the material sets the material attributes also. 191 // Setting the material sets the material attributes also.
192 // TODO: decide if this is necessary -- the simulator does this.
186 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false); 193 MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
187 Friction = matAttrib.friction; 194 Friction = matAttrib.friction;
188 Restitution = matAttrib.restitution; 195 Restitution = matAttrib.restitution;
189 Density = matAttrib.density / BSParam.DensityScaleFactor; 196 Density = matAttrib.density;
190 // DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density); 197 // DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density);
191 } 198 }
192 199
200 public override float Density
201 {
202 get
203 {
204 return base.Density;
205 }
206 set
207 {
208 DetailLog("{0},BSPhysObject.Density,set,den={1}", LocalID, value);
209 base.Density = value;
210 }
211 }
212
193 // Stop all physical motion. 213 // Stop all physical motion.
194 public abstract void ZeroMotion(bool inTaintTime); 214 public abstract void ZeroMotion(bool inTaintTime);
195 public abstract void ZeroAngularMotion(bool inTaintTime); 215 public abstract void ZeroAngularMotion(bool inTaintTime);
@@ -197,21 +217,55 @@ public abstract class BSPhysObject : PhysicsActor
197 // Update the physical location and motion of the object. Called with data from Bullet. 217 // Update the physical location and motion of the object. Called with data from Bullet.
198 public abstract void UpdateProperties(EntityProperties entprop); 218 public abstract void UpdateProperties(EntityProperties entprop);
199 219
200 public abstract OMV.Vector3 RawPosition { get; set; } 220 public virtual OMV.Vector3 RawPosition { get; set; }
201 public abstract OMV.Vector3 ForcePosition { get; set; } 221 public abstract OMV.Vector3 ForcePosition { get; set; }
202 222
203 public abstract OMV.Quaternion RawOrientation { get; set; } 223 public virtual OMV.Quaternion RawOrientation { get; set; }
204 public abstract OMV.Quaternion ForceOrientation { get; set; } 224 public abstract OMV.Quaternion ForceOrientation { get; set; }
205 225
206 public abstract OMV.Vector3 RawVelocity { get; set; } 226 public OMV.Vector3 RawVelocity { get; set; }
207 public abstract OMV.Vector3 ForceVelocity { get; set; } 227 public abstract OMV.Vector3 ForceVelocity { get; set; }
208 228
229 public OMV.Vector3 RawForce { get; set; }
230 public OMV.Vector3 RawTorque { get; set; }
231 public override void AddAngularForce(OMV.Vector3 force, bool pushforce)
232 {
233 AddAngularForce(force, pushforce, false);
234 }
235 public abstract void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime);
236 public abstract void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime);
237
209 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } 238 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
210 239
211 public abstract float ForceBuoyancy { get; set; } 240 public abstract float ForceBuoyancy { get; set; }
212 241
213 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } 242 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
214 243
244 public override bool PIDActive { set { MoveToTargetActive = value; } }
245 public override OMV.Vector3 PIDTarget { set { MoveToTargetTarget = value; } }
246 public override float PIDTau { set { MoveToTargetTau = value; } }
247
248 public bool MoveToTargetActive { get; set; }
249 public OMV.Vector3 MoveToTargetTarget { get; set; }
250 public float MoveToTargetTau { get; set; }
251
252 // Used for llSetHoverHeight and maybe vehicle height. Hover Height will override MoveTo target's Z
253 public override bool PIDHoverActive { set { HoverActive = value; } }
254 public override float PIDHoverHeight { set { HoverHeight = value; } }
255 public override PIDHoverType PIDHoverType { set { HoverType = value; } }
256 public override float PIDHoverTau { set { HoverTau = value; } }
257
258 public bool HoverActive { get; set; }
259 public float HoverHeight { get; set; }
260 public PIDHoverType HoverType { get; set; }
261 public float HoverTau { get; set; }
262
263 // For RotLookAt
264 public override OMV.Quaternion APIDTarget { set { return; } }
265 public override bool APIDActive { set { return; } }
266 public override float APIDStrength { set { return; } }
267 public override float APIDDamping { set { return; } }
268
215 // The current velocity forward 269 // The current velocity forward
216 public virtual float ForwardSpeed 270 public virtual float ForwardSpeed
217 { 271 {
@@ -233,11 +287,69 @@ public abstract class BSPhysObject : PhysicsActor
233 287
234 // The user can optionally set the center of mass. The user's setting will override any 288 // The user can optionally set the center of mass. The user's setting will override any
235 // computed center-of-mass (like in linksets). 289 // computed center-of-mass (like in linksets).
236 public OMV.Vector3? UserSetCenterOfMass { get; set; } 290 // Note this is a displacement from the root's coordinates. Zero means use the root prim as center-of-mass.
291 public OMV.Vector3? UserSetCenterOfMassDisplacement { get; set; }
292
293 public OMV.Vector3 LockedLinearAxis { get; set; } // zero means locked. one means free.
294 public OMV.Vector3 LockedAngularAxis { get; set; } // zero means locked. one means free.
295 public const float FreeAxis = 1f;
296 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(FreeAxis, FreeAxis, FreeAxis); // All axis are free
297
298 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
299 // they need waking up when parameters are changed.
300 // Called in taint-time!!
301 public void ActivateIfPhysical(bool forceIt)
302 {
303 if (PhysBody.HasPhysicalBody)
304 {
305 if (IsPhysical)
306 {
307 // Physical objects might need activating
308 PhysScene.PE.Activate(PhysBody, forceIt);
309 }
310 else
311 {
312 // Clear the collision cache since we've changed some properties.
313 PhysScene.PE.ClearCollisionProxyCache(PhysScene.World, PhysBody);
314 }
315 }
316 }
237 317
238 public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free. 318 // 'actors' act on the physical object to change or constrain its motion. These can range from
239 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free 319 // hovering to complex vehicle motion.
240 public readonly String LockedAxisActorName = "BSPrim.LockedAxis"; 320 // May be called at non-taint time as this just adds the actor to the action list and the real
321 // work is done during the simulation step.
322 // Note that, if the actor is already in the list and we are disabling same, the actor is just left
323 // in the list disabled.
324 public delegate BSActor CreateActor();
325 public void EnableActor(bool enableActor, string actorName, CreateActor creator)
326 {
327 lock (PhysicalActors)
328 {
329 BSActor theActor;
330 if (PhysicalActors.TryGetActor(actorName, out theActor))
331 {
332 // The actor already exists so just turn it on or off
333 DetailLog("{0},BSPhysObject.EnableActor,enablingExistingActor,name={1},enable={2}", LocalID, actorName, enableActor);
334 theActor.Enabled = enableActor;
335 }
336 else
337 {
338 // The actor does not exist. If it should, create it.
339 if (enableActor)
340 {
341 DetailLog("{0},BSPhysObject.EnableActor,creatingActor,name={1}", LocalID, actorName);
342 theActor = creator();
343 PhysicalActors.Add(actorName, theActor);
344 theActor.Enabled = true;
345 }
346 else
347 {
348 DetailLog("{0},BSPhysObject.EnableActor,notCreatingActorSinceNotEnabled,name={1}", LocalID, actorName);
349 }
350 }
351 }
352 }
241 353
242 #region Collisions 354 #region Collisions
243 355
@@ -255,70 +367,98 @@ public abstract class BSPhysObject : PhysicsActor
255 protected CollisionFlags CurrentCollisionFlags { get; set; } 367 protected CollisionFlags CurrentCollisionFlags { get; set; }
256 // On a collision, check the collider and remember if the last collider was moving 368 // On a collision, check the collider and remember if the last collider was moving
257 // Used to modify the standing of avatars (avatars on stationary things stand still) 369 // Used to modify the standing of avatars (avatars on stationary things stand still)
258 protected bool ColliderIsMoving; 370 public bool ColliderIsMoving;
371 // 'true' if the last collider was a volume detect object
372 public bool ColliderIsVolumeDetect;
373 // Used by BSCharacter to manage standing (and not slipping)
374 public bool IsStationary;
259 375
260 // Count of collisions for this object 376 // Count of collisions for this object
261 protected long CollisionAccumulation { get; set; } 377 protected long CollisionAccumulation { get; set; }
262 378
263 public override bool IsColliding { 379 public override bool IsColliding {
264 get { return (CollidingStep == PhysicsScene.SimulationStep); } 380 get { return (CollidingStep == PhysScene.SimulationStep); }
265 set { 381 set {
266 if (value) 382 if (value)
267 CollidingStep = PhysicsScene.SimulationStep; 383 CollidingStep = PhysScene.SimulationStep;
268 else 384 else
269 CollidingStep = 0; 385 CollidingStep = BSScene.NotASimulationStep;
270 } 386 }
271 } 387 }
388 // Complex objects (like linksets) need to know if there is a collision on any part of
389 // their shape. 'IsColliding' has an existing definition of reporting a collision on
390 // only this specific prim or component of linksets.
391 // 'HasSomeCollision' is defined as reporting if there is a collision on any part of
392 // the complex body that this prim is the root of.
393 public virtual bool HasSomeCollision
394 {
395 get { return IsColliding; }
396 set { IsColliding = value; }
397 }
272 public override bool CollidingGround { 398 public override bool CollidingGround {
273 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } 399 get { return (CollidingGroundStep == PhysScene.SimulationStep); }
274 set 400 set
275 { 401 {
276 if (value) 402 if (value)
277 CollidingGroundStep = PhysicsScene.SimulationStep; 403 CollidingGroundStep = PhysScene.SimulationStep;
278 else 404 else
279 CollidingGroundStep = 0; 405 CollidingGroundStep = BSScene.NotASimulationStep;
280 } 406 }
281 } 407 }
282 public override bool CollidingObj { 408 public override bool CollidingObj {
283 get { return (CollidingObjectStep == PhysicsScene.SimulationStep); } 409 get { return (CollidingObjectStep == PhysScene.SimulationStep); }
284 set { 410 set {
285 if (value) 411 if (value)
286 CollidingObjectStep = PhysicsScene.SimulationStep; 412 CollidingObjectStep = PhysScene.SimulationStep;
287 else 413 else
288 CollidingObjectStep = 0; 414 CollidingObjectStep = BSScene.NotASimulationStep;
289 } 415 }
290 } 416 }
291 417
292 // The collisions that have been collected this tick 418 // The collisions that have been collected for the next collision reporting (throttled by subscription)
293 protected CollisionEventUpdate CollisionCollection; 419 protected CollisionEventUpdate CollisionCollection;
294 // Remember collisions from last tick for fancy collision based actions 420 // This is the collision collection last reported to the Simulator.
421 public CollisionEventUpdate CollisionsLastReported;
422 // Remember the collisions recorded in the last tick for fancy collision checking
295 // (like a BSCharacter walking up stairs). 423 // (like a BSCharacter walking up stairs).
296 protected CollisionEventUpdate CollisionsLastTick; 424 public CollisionEventUpdate CollisionsLastTick;
425 private long CollisionsLastTickStep = -1;
297 426
298 // The simulation step is telling this object about a collision. 427 // The simulation step is telling this object about a collision.
299 // Return 'true' if a collision was processed and should be sent up. 428 // Return 'true' if a collision was processed and should be sent up.
300 // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision. 429 // Return 'false' if this object is not enabled/subscribed/appropriate for or has already seen this collision.
301 // Called at taint time from within the Step() function 430 // Called at taint time from within the Step() function
431 public delegate bool CollideCall(uint collidingWith, BSPhysObject collidee, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth);
302 public virtual bool Collide(uint collidingWith, BSPhysObject collidee, 432 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
303 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 433 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
304 { 434 {
305 bool ret = false; 435 bool ret = false;
306 436
307 // The following lines make IsColliding(), CollidingGround() and CollidingObj work 437 // The following lines make IsColliding(), CollidingGround() and CollidingObj work
308 CollidingStep = PhysicsScene.SimulationStep; 438 CollidingStep = PhysScene.SimulationStep;
309 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) 439 if (collidingWith <= PhysScene.TerrainManager.HighestTerrainID)
310 { 440 {
311 CollidingGroundStep = PhysicsScene.SimulationStep; 441 CollidingGroundStep = PhysScene.SimulationStep;
312 } 442 }
313 else 443 else
314 { 444 {
315 CollidingObjectStep = PhysicsScene.SimulationStep; 445 CollidingObjectStep = PhysScene.SimulationStep;
316 } 446 }
317 447
318 CollisionAccumulation++; 448 CollisionAccumulation++;
319 449
320 // For movement tests, remember if we are colliding with an object that is moving. 450 // For movement tests, remember if we are colliding with an object that is moving.
321 ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false; 451 ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false;
452 ColliderIsVolumeDetect = collidee != null ? (collidee.IsVolumeDetect) : false;
453
454 // Make a collection of the collisions that happened the last simulation tick.
455 // This is different than the collection created for sending up to the simulator as it is cleared every tick.
456 if (CollisionsLastTickStep != PhysScene.SimulationStep)
457 {
458 CollisionsLastTick = new CollisionEventUpdate();
459 CollisionsLastTickStep = PhysScene.SimulationStep;
460 }
461 CollisionsLastTick.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
322 462
323 // If someone has subscribed for collision events log the collision so it will be reported up 463 // If someone has subscribed for collision events log the collision so it will be reported up
324 if (SubscribedEvents()) { 464 if (SubscribedEvents()) {
@@ -340,12 +480,12 @@ public abstract class BSPhysObject : PhysicsActor
340 bool ret = true; 480 bool ret = true;
341 481
342 // If the 'no collision' call, force it to happen right now so quick collision_end 482 // If the 'no collision' call, force it to happen right now so quick collision_end
343 bool force = (CollisionCollection.Count == 0 && CollisionsLastTick.Count != 0); 483 bool force = (CollisionCollection.Count == 0 && CollisionsLastReported.Count != 0);
344 484
345 // throttle the collisions to the number of milliseconds specified in the subscription 485 // throttle the collisions to the number of milliseconds specified in the subscription
346 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) 486 if (force || (PhysScene.SimulationNowTime >= NextCollisionOkTime))
347 { 487 {
348 NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; 488 NextCollisionOkTime = PhysScene.SimulationNowTime + SubscribedEventsMs;
349 489
350 // We are called if we previously had collisions. If there are no collisions 490 // We are called if we previously had collisions. If there are no collisions
351 // this time, send up one last empty event so OpenSim can sense collision end. 491 // this time, send up one last empty event so OpenSim can sense collision end.
@@ -359,11 +499,11 @@ public abstract class BSPhysObject : PhysicsActor
359 base.SendCollisionUpdate(CollisionCollection); 499 base.SendCollisionUpdate(CollisionCollection);
360 500
361 // Remember the collisions from this tick for some collision specific processing. 501 // Remember the collisions from this tick for some collision specific processing.
362 CollisionsLastTick = CollisionCollection; 502 CollisionsLastReported = CollisionCollection;
363 503
364 // The CollisionCollection instance is passed around in the simulator. 504 // The CollisionCollection instance is passed around in the simulator.
365 // Make sure we don't have a handle to that one and that a new one is used for next time. 505 // Make sure we don't have a handle to that one and that a new one is used for next time.
366 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here, 506 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
367 // a race condition is created for the other users of this instance. 507 // a race condition is created for the other users of this instance.
368 CollisionCollection = new CollisionEventUpdate(); 508 CollisionCollection = new CollisionEventUpdate();
369 } 509 }
@@ -380,10 +520,10 @@ public abstract class BSPhysObject : PhysicsActor
380 // make sure first collision happens 520 // make sure first collision happens
381 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); 521 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
382 522
383 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() 523 PhysScene.TaintedObject(LocalID, TypeName+".SubscribeEvents", delegate()
384 { 524 {
385 if (PhysBody.HasPhysicalBody) 525 if (PhysBody.HasPhysicalBody)
386 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 526 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
387 }); 527 });
388 } 528 }
389 else 529 else
@@ -395,11 +535,11 @@ public abstract class BSPhysObject : PhysicsActor
395 public override void UnSubscribeEvents() { 535 public override void UnSubscribeEvents() {
396 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); 536 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
397 SubscribedEventsMs = 0; 537 SubscribedEventsMs = 0;
398 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 538 PhysScene.TaintedObject(LocalID, TypeName+".UnSubscribeEvents", delegate()
399 { 539 {
400 // Make sure there is a body there because sometimes destruction happens in an un-ideal order. 540 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
401 if (PhysBody.HasPhysicalBody) 541 if (PhysBody.HasPhysicalBody)
402 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 542 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
403 }); 543 });
404 } 544 }
405 // Return 'true' if the simulator wants collision events 545 // Return 'true' if the simulator wants collision events
@@ -413,7 +553,7 @@ public abstract class BSPhysObject : PhysicsActor
413 { 553 {
414 // Scale the collision count by the time since the last collision. 554 // Scale the collision count by the time since the last collision.
415 // The "+1" prevents dividing by zero. 555 // The "+1" prevents dividing by zero.
416 long timeAgo = PhysicsScene.SimulationStep - CollidingStep + 1; 556 long timeAgo = PhysScene.SimulationStep - CollidingStep + 1;
417 CollisionScore = CollisionAccumulation / timeAgo; 557 CollisionScore = CollisionAccumulation / timeAgo;
418 } 558 }
419 public override float CollisionScore { get; set; } 559 public override float CollisionScore { get; set; }
@@ -424,104 +564,6 @@ public abstract class BSPhysObject : PhysicsActor
424 564
425 public BSActorCollection PhysicalActors; 565 public BSActorCollection PhysicalActors;
426 566
427 // There are some actions that must be performed for a physical object before each simulation step.
428 // These actions are optional so, rather than scanning all the physical objects and asking them
429 // if they have anything to do, a physical object registers for an event call before the step is performed.
430 // This bookkeeping makes it easy to add, remove and clean up after all these registrations.
431 private Dictionary<string, BSScene.PreStepAction> RegisteredPrestepActions = new Dictionary<string, BSScene.PreStepAction>();
432 private Dictionary<string, BSScene.PostStepAction> RegisteredPoststepActions = new Dictionary<string, BSScene.PostStepAction>();
433 protected void RegisterPreStepAction(string op, uint id, BSScene.PreStepAction actn)
434 {
435 string identifier = op + "-" + id.ToString();
436
437 lock (RegisteredPrestepActions)
438 {
439 // Clean out any existing action
440 UnRegisterPreStepAction(op, id);
441 RegisteredPrestepActions[identifier] = actn;
442 PhysicsScene.BeforeStep += actn;
443 }
444 DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
445 }
446
447 // Unregister a pre step action. Safe to call if the action has not been registered.
448 // Returns 'true' if an action was actually removed
449 protected bool UnRegisterPreStepAction(string op, uint id)
450 {
451 string identifier = op + "-" + id.ToString();
452 bool removed = false;
453 lock (RegisteredPrestepActions)
454 {
455 if (RegisteredPrestepActions.ContainsKey(identifier))
456 {
457 PhysicsScene.BeforeStep -= RegisteredPrestepActions[identifier];
458 RegisteredPrestepActions.Remove(identifier);
459 removed = true;
460 }
461 }
462 DetailLog("{0},BSPhysObject.UnRegisterPreStepAction,id={1},removed={2}", LocalID, identifier, removed);
463 return removed;
464 }
465
466 protected void UnRegisterAllPreStepActions()
467 {
468 lock (RegisteredPrestepActions)
469 {
470 foreach (KeyValuePair<string, BSScene.PreStepAction> kvp in RegisteredPrestepActions)
471 {
472 PhysicsScene.BeforeStep -= kvp.Value;
473 }
474 RegisteredPrestepActions.Clear();
475 }
476 DetailLog("{0},BSPhysObject.UnRegisterAllPreStepActions,", LocalID);
477 }
478
479 protected void RegisterPostStepAction(string op, uint id, BSScene.PostStepAction actn)
480 {
481 string identifier = op + "-" + id.ToString();
482
483 lock (RegisteredPoststepActions)
484 {
485 // Clean out any existing action
486 UnRegisterPostStepAction(op, id);
487 RegisteredPoststepActions[identifier] = actn;
488 PhysicsScene.AfterStep += actn;
489 }
490 DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier);
491 }
492
493 // Unregister a pre step action. Safe to call if the action has not been registered.
494 // Returns 'true' if an action was actually removed.
495 protected bool UnRegisterPostStepAction(string op, uint id)
496 {
497 string identifier = op + "-" + id.ToString();
498 bool removed = false;
499 lock (RegisteredPoststepActions)
500 {
501 if (RegisteredPoststepActions.ContainsKey(identifier))
502 {
503 PhysicsScene.AfterStep -= RegisteredPoststepActions[identifier];
504 RegisteredPoststepActions.Remove(identifier);
505 removed = true;
506 }
507 }
508 DetailLog("{0},BSPhysObject.UnRegisterPostStepAction,id={1},removed={2}", LocalID, identifier, removed);
509 return removed;
510 }
511
512 protected void UnRegisterAllPostStepActions()
513 {
514 lock (RegisteredPoststepActions)
515 {
516 foreach (KeyValuePair<string, BSScene.PostStepAction> kvp in RegisteredPoststepActions)
517 {
518 PhysicsScene.AfterStep -= kvp.Value;
519 }
520 RegisteredPoststepActions.Clear();
521 }
522 DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID);
523 }
524
525 // When an update to the physical properties happens, this event is fired to let 567 // When an update to the physical properties happens, this event is fired to let
526 // different actors to modify the update before it is passed around 568 // different actors to modify the update before it is passed around
527 public delegate void PreUpdatePropertyAction(ref EntityProperties entprop); 569 public delegate void PreUpdatePropertyAction(ref EntityProperties entprop);
@@ -533,53 +575,13 @@ public abstract class BSPhysObject : PhysicsActor
533 actions(ref entprop); 575 actions(ref entprop);
534 } 576 }
535 577
536 private Dictionary<string, PreUpdatePropertyAction> RegisteredPreUpdatePropertyActions = new Dictionary<string, PreUpdatePropertyAction>();
537 public void RegisterPreUpdatePropertyAction(string identifier, PreUpdatePropertyAction actn)
538 {
539 lock (RegisteredPreUpdatePropertyActions)
540 {
541 // Clean out any existing action
542 UnRegisterPreUpdatePropertyAction(identifier);
543 RegisteredPreUpdatePropertyActions[identifier] = actn;
544 OnPreUpdateProperty += actn;
545 }
546 DetailLog("{0},BSPhysObject.RegisterPreUpdatePropertyAction,id={1}", LocalID, identifier);
547 }
548 public bool UnRegisterPreUpdatePropertyAction(string identifier)
549 {
550 bool removed = false;
551 lock (RegisteredPreUpdatePropertyActions)
552 {
553 if (RegisteredPreUpdatePropertyActions.ContainsKey(identifier))
554 {
555 OnPreUpdateProperty -= RegisteredPreUpdatePropertyActions[identifier];
556 RegisteredPreUpdatePropertyActions.Remove(identifier);
557 removed = true;
558 }
559 }
560 DetailLog("{0},BSPhysObject.UnRegisterPreUpdatePropertyAction,id={1},removed={2}", LocalID, identifier, removed);
561 return removed;
562 }
563 public void UnRegisterAllPreUpdatePropertyActions()
564 {
565 lock (RegisteredPreUpdatePropertyActions)
566 {
567 foreach (KeyValuePair<string, PreUpdatePropertyAction> kvp in RegisteredPreUpdatePropertyActions)
568 {
569 OnPreUpdateProperty -= kvp.Value;
570 }
571 RegisteredPreUpdatePropertyActions.Clear();
572 }
573 DetailLog("{0},BSPhysObject.UnRegisterAllPreUpdatePropertyAction,", LocalID);
574 }
575
576 #endregion // Per Simulation Step actions 578 #endregion // Per Simulation Step actions
577 579
578 // High performance detailed logging routine used by the physical objects. 580 // High performance detailed logging routine used by the physical objects.
579 protected void DetailLog(string msg, params Object[] args) 581 protected void DetailLog(string msg, params Object[] args)
580 { 582 {
581 if (PhysicsScene.PhysicsLogging.Enabled) 583 if (PhysScene.PhysicsLogging.Enabled)
582 PhysicsScene.DetailLog(msg, args); 584 PhysScene.DetailLog(msg, args);
583 } 585 }
584 586
585} 587}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index e56276a..15b7090 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
41 [Serializable] 41 [Serializable]
42public class BSPrim : BSPhysObject 42public class BSPrim : BSPhysObject
43{ 43{
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 private static readonly string LogHeader = "[BULLETS PRIM]"; 45 private static readonly string LogHeader = "[BULLETS PRIM]";
46 46
47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. 47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
@@ -51,15 +51,8 @@ public class BSPrim : BSPhysObject
51 private bool _isSelected; 51 private bool _isSelected;
52 private bool _isVolumeDetect; 52 private bool _isVolumeDetect;
53 53
54 // _position is what the simulator thinks the positions of the prim is.
55 private OMV.Vector3 _position;
56
57 private float _mass; // the mass of this object 54 private float _mass; // the mass of this object
58 private OMV.Vector3 _force;
59 private OMV.Vector3 _velocity;
60 private OMV.Vector3 _torque;
61 private OMV.Vector3 _acceleration; 55 private OMV.Vector3 _acceleration;
62 private OMV.Quaternion _orientation;
63 private int _physicsActorType; 56 private int _physicsActorType;
64 private bool _isPhysical; 57 private bool _isPhysical;
65 private bool _flying; 58 private bool _flying;
@@ -72,17 +65,18 @@ public class BSPrim : BSPhysObject
72 65
73 private int CrossingFailures { get; set; } 66 private int CrossingFailures { get; set; }
74 67
75 public BSDynamics VehicleActor; 68 // Keep a handle to the vehicle actor so it is easy to set parameters on same.
76 public string VehicleActorName = "BasicVehicle"; 69 public const string VehicleActorName = "BasicVehicle";
77
78 private BSVMotor _targetMotor;
79 private OMV.Vector3 _PIDTarget;
80 private float _PIDTau;
81 70
82 private BSFMotor _hoverMotor; 71 // Parameters for the hover actor
83 private float _PIDHoverHeight; 72 public const string HoverActorName = "BSPrim.HoverActor";
84 private PIDHoverType _PIDHoverType; 73 // Parameters for the axis lock actor
85 private float _PIDHoverTau; 74 public const String LockedAxisActorName = "BSPrim.LockedAxis";
75 // Parameters for the move to target actor
76 public const string MoveToTargetActorName = "BSPrim.MoveToTargetActor";
77 // Parameters for the setForce and setTorque actors
78 public const string SetForceActorName = "BSPrim.SetForceActor";
79 public const string SetTorqueActorName = "BSPrim.SetTorqueActor";
86 80
87 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, 81 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
88 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 82 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
@@ -90,32 +84,34 @@ public class BSPrim : BSPhysObject
90 { 84 {
91 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 85 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
92 _physicsActorType = (int)ActorTypes.Prim; 86 _physicsActorType = (int)ActorTypes.Prim;
93 _position = pos; 87 RawPosition = pos;
94 _size = size; 88 _size = size;
95 Scale = size; // prims are the size the user wants them to be (different for BSCharactes). 89 Scale = size; // prims are the size the user wants them to be (different for BSCharactes).
96 _orientation = rotation; 90 RawOrientation = rotation;
97 _buoyancy = 0f; 91 _buoyancy = 0f;
98 _velocity = OMV.Vector3.Zero; 92 RawVelocity = OMV.Vector3.Zero;
99 _rotationalVelocity = OMV.Vector3.Zero; 93 _rotationalVelocity = OMV.Vector3.Zero;
100 BaseShape = pbs; 94 BaseShape = pbs;
101 _isPhysical = pisPhysical; 95 _isPhysical = pisPhysical;
102 _isVolumeDetect = false; 96 _isVolumeDetect = false;
103 97
104 VehicleActor = new BSDynamics(PhysicsScene, this, VehicleActorName); 98 // Add a dynamic vehicle to our set of actors that can move this prim.
105 PhysicalActors.Add(VehicleActorName, VehicleActor); 99 // PhysicalActors.Add(VehicleActorName, new BSDynamics(PhysScene, this, VehicleActorName));
106 100
107 _mass = CalculateMass(); 101 _mass = CalculateMass();
108 102
109 // DetailLog("{0},BSPrim.constructor,call", LocalID); 103 // DetailLog("{0},BSPrim.constructor,call", LocalID);
110 // do the actual object creation at taint time 104 // do the actual object creation at taint time
111 PhysicsScene.TaintedObject("BSPrim.create", delegate() 105 PhysScene.TaintedObject(LocalID, "BSPrim.create", delegate()
112 { 106 {
113 // Make sure the object is being created with some sanity. 107 // Make sure the object is being created with some sanity.
114 ExtremeSanityCheck(true /* inTaintTime */); 108 ExtremeSanityCheck(true /* inTaintTime */);
115 109
116 CreateGeomAndObject(true); 110 CreateGeomAndObject(true);
117 111
118 CurrentCollisionFlags = PhysicsScene.PE.GetCollisionFlags(PhysBody); 112 CurrentCollisionFlags = PhysScene.PE.GetCollisionFlags(PhysBody);
113
114 IsInitialized = true;
119 }); 115 });
120 } 116 }
121 117
@@ -123,19 +119,21 @@ public class BSPrim : BSPhysObject
123 public override void Destroy() 119 public override void Destroy()
124 { 120 {
125 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 121 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
122 IsInitialized = false;
123
126 base.Destroy(); 124 base.Destroy();
127 125
128 // Undo any vehicle properties 126 // Undo any vehicle properties
129 this.VehicleType = (int)Vehicle.TYPE_NONE; 127 this.VehicleType = (int)Vehicle.TYPE_NONE;
130 128
131 PhysicsScene.TaintedObject("BSPrim.Destroy", delegate() 129 PhysScene.TaintedObject(LocalID, "BSPrim.Destroy", delegate()
132 { 130 {
133 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 131 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
134 // If there are physical body and shape, release my use of same. 132 // If there are physical body and shape, release my use of same.
135 PhysicsScene.Shapes.DereferenceBody(PhysBody, null); 133 PhysScene.Shapes.DereferenceBody(PhysBody, null);
136 PhysBody.Clear(); 134 PhysBody.Clear();
137 PhysicsScene.Shapes.DereferenceShape(PhysShape, null); 135 PhysShape.Dereference(PhysScene);
138 PhysShape.Clear(); 136 PhysShape = new BSShapeNull();
139 }); 137 });
140 } 138 }
141 139
@@ -161,25 +159,13 @@ public class BSPrim : BSPhysObject
161 ForceBodyShapeRebuild(false); 159 ForceBodyShapeRebuild(false);
162 } 160 }
163 } 161 }
164 // 'unknown' says to choose the best type
165 public override BSPhysicsShapeType PreferredPhysicalShape
166 { get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } }
167
168 public override bool ForceBodyShapeRebuild(bool inTaintTime) 162 public override bool ForceBodyShapeRebuild(bool inTaintTime)
169 { 163 {
170 if (inTaintTime) 164 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ForceBodyShapeRebuild", delegate()
171 { 165 {
172 _mass = CalculateMass(); // changing the shape changes the mass 166 _mass = CalculateMass(); // changing the shape changes the mass
173 CreateGeomAndObject(true); 167 CreateGeomAndObject(true);
174 } 168 });
175 else
176 {
177 PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate()
178 {
179 _mass = CalculateMass(); // changing the shape changes the mass
180 CreateGeomAndObject(true);
181 });
182 }
183 return true; 169 return true;
184 } 170 }
185 public override bool Grabbed { 171 public override bool Grabbed {
@@ -192,7 +178,7 @@ public class BSPrim : BSPhysObject
192 if (value != _isSelected) 178 if (value != _isSelected)
193 { 179 {
194 _isSelected = value; 180 _isSelected = value;
195 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() 181 PhysScene.TaintedObject(LocalID, "BSPrim.setSelected", delegate()
196 { 182 {
197 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); 183 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
198 SetObjectDynamic(false); 184 SetObjectDynamic(false);
@@ -233,28 +219,28 @@ public class BSPrim : BSPhysObject
233 // Called at taint time! 219 // Called at taint time!
234 public override void ZeroMotion(bool inTaintTime) 220 public override void ZeroMotion(bool inTaintTime)
235 { 221 {
236 _velocity = OMV.Vector3.Zero; 222 RawVelocity = OMV.Vector3.Zero;
237 _acceleration = OMV.Vector3.Zero; 223 _acceleration = OMV.Vector3.Zero;
238 _rotationalVelocity = OMV.Vector3.Zero; 224 _rotationalVelocity = OMV.Vector3.Zero;
239 225
240 // Zero some other properties in the physics engine 226 // Zero some other properties in the physics engine
241 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 227 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate()
242 { 228 {
243 if (PhysBody.HasPhysicalBody) 229 if (PhysBody.HasPhysicalBody)
244 PhysicsScene.PE.ClearAllForces(PhysBody); 230 PhysScene.PE.ClearAllForces(PhysBody);
245 }); 231 });
246 } 232 }
247 public override void ZeroAngularMotion(bool inTaintTime) 233 public override void ZeroAngularMotion(bool inTaintTime)
248 { 234 {
249 _rotationalVelocity = OMV.Vector3.Zero; 235 _rotationalVelocity = OMV.Vector3.Zero;
250 // Zero some other properties in the physics engine 236 // Zero some other properties in the physics engine
251 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 237 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate()
252 { 238 {
253 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); 239 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
254 if (PhysBody.HasPhysicalBody) 240 if (PhysBody.HasPhysicalBody)
255 { 241 {
256 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); 242 PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
257 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); 243 PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
258 } 244 }
259 }); 245 });
260 } 246 }
@@ -268,64 +254,58 @@ public class BSPrim : BSPhysObject
268 if (axis.X != 1) locking.X = 0f; 254 if (axis.X != 1) locking.X = 0f;
269 if (axis.Y != 1) locking.Y = 0f; 255 if (axis.Y != 1) locking.Y = 0f;
270 if (axis.Z != 1) locking.Z = 0f; 256 if (axis.Z != 1) locking.Z = 0f;
271 LockedAxis = locking; 257 LockedAngularAxis = locking;
272 258
273 if (LockedAxis != LockedAxisFree) 259 EnableActor(LockedAngularAxis != LockedAxisFree, LockedAxisActorName, delegate()
274 { 260 {
275 PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate() 261 return new BSActorLockAxis(PhysScene, this, LockedAxisActorName);
276 { 262 });
277 // If there is not already an axis locker, make one 263
278 if (!PhysicalActors.HasActor(LockedAxisActorName)) 264 // Update parameters so the new actor's Refresh() action is called at the right time.
279 { 265 PhysScene.TaintedObject(LocalID, "BSPrim.LockAngularMotion", delegate()
280 DetailLog("{0},BSPrim.LockAngularMotion,taint,registeringLockAxisActor", LocalID); 266 {
281 PhysicalActors.Add(LockedAxisActorName, new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName)); 267 UpdatePhysicalParameters();
282 } 268 });
283 UpdatePhysicalParameters(); 269
284 });
285 }
286 return; 270 return;
287 } 271 }
288 272
289 public override OMV.Vector3 RawPosition
290 {
291 get { return _position; }
292 set { _position = value; }
293 }
294 public override OMV.Vector3 Position { 273 public override OMV.Vector3 Position {
295 get { 274 get {
296 // don't do the GetObjectPosition for root elements because this function is called a zillion times. 275 // don't do the GetObjectPosition for root elements because this function is called a zillion times.
297 // _position = ForcePosition; 276 // RawPosition = ForcePosition;
298 return _position; 277 return RawPosition;
299 } 278 }
300 set { 279 set {
301 // If the position must be forced into the physics engine, use ForcePosition. 280 // If the position must be forced into the physics engine, use ForcePosition.
302 // All positions are given in world positions. 281 // All positions are given in world positions.
303 if (_position == value) 282 if (RawPosition == value)
304 { 283 {
305 DetailLog("{0},BSPrim.setPosition,call,positionNotChanging,pos={1},orient={2}", LocalID, _position, _orientation); 284 DetailLog("{0},BSPrim.setPosition,call,positionNotChanging,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
306 return; 285 return;
307 } 286 }
308 _position = value; 287 RawPosition = value;
309 PositionSanityCheck(false); 288 PositionSanityCheck(false);
310 289
311 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() 290 PhysScene.TaintedObject(LocalID, "BSPrim.setPosition", delegate()
312 { 291 {
313 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 292 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
314 ForcePosition = _position; 293 ForcePosition = RawPosition;
315 }); 294 });
316 } 295 }
317 } 296 }
318 297
298 // NOTE: overloaded by BSPrimDisplaced to handle offset for center-of-gravity.
319 public override OMV.Vector3 ForcePosition { 299 public override OMV.Vector3 ForcePosition {
320 get { 300 get {
321 _position = PhysicsScene.PE.GetPosition(PhysBody); 301 RawPosition = PhysScene.PE.GetPosition(PhysBody);
322 return _position; 302 return RawPosition;
323 } 303 }
324 set { 304 set {
325 _position = value; 305 RawPosition = value;
326 if (PhysBody.HasPhysicalBody) 306 if (PhysBody.HasPhysicalBody)
327 { 307 {
328 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 308 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
329 ActivateIfPhysical(false); 309 ActivateIfPhysical(false);
330 } 310 }
331 } 311 }
@@ -342,7 +322,7 @@ public class BSPrim : BSPhysObject
342 if (!IsPhysicallyActive) 322 if (!IsPhysicallyActive)
343 return ret; 323 return ret;
344 324
345 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) 325 if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
346 { 326 {
347 // The physical object is out of the known/simulated area. 327 // The physical object is out of the known/simulated area.
348 // Upper levels of code will handle the transition to other areas so, for 328 // Upper levels of code will handle the transition to other areas so, for
@@ -350,7 +330,7 @@ public class BSPrim : BSPhysObject
350 return ret; 330 return ret;
351 } 331 }
352 332
353 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); 333 float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
354 OMV.Vector3 upForce = OMV.Vector3.Zero; 334 OMV.Vector3 upForce = OMV.Vector3.Zero;
355 float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z)); 335 float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z));
356 if ((RawPosition.Z + approxSize / 2f) < terrainHeight) 336 if ((RawPosition.Z + approxSize / 2f) < terrainHeight)
@@ -359,10 +339,10 @@ public class BSPrim : BSPhysObject
359 float targetHeight = terrainHeight + (Size.Z / 2f); 339 float targetHeight = terrainHeight + (Size.Z / 2f);
360 // If the object is below ground it just has to be moved up because pushing will 340 // If the object is below ground it just has to be moved up because pushing will
361 // not get it through the terrain 341 // not get it through the terrain
362 _position.Z = targetHeight; 342 RawPosition = new OMV.Vector3(RawPosition.X, RawPosition.Y, targetHeight);
363 if (inTaintTime) 343 if (inTaintTime)
364 { 344 {
365 ForcePosition = _position; 345 ForcePosition = RawPosition;
366 } 346 }
367 // If we are throwing the object around, zero its other forces 347 // If we are throwing the object around, zero its other forces
368 ZeroMotion(inTaintTime); 348 ZeroMotion(inTaintTime);
@@ -371,7 +351,7 @@ public class BSPrim : BSPhysObject
371 351
372 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 352 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
373 { 353 {
374 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); 354 float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
375 // TODO: a floating motor so object will bob in the water 355 // TODO: a floating motor so object will bob in the water
376 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) 356 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f)
377 { 357 {
@@ -379,8 +359,8 @@ public class BSPrim : BSPhysObject
379 upForce.Z = (waterHeight - RawPosition.Z) * 1f; 359 upForce.Z = (waterHeight - RawPosition.Z) * 1f;
380 360
381 // Apply upforce and overcome gravity. 361 // Apply upforce and overcome gravity.
382 OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity; 362 OMV.Vector3 correctionForce = upForce - PhysScene.DefaultGravity;
383 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce); 363 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, RawPosition, upForce, correctionForce);
384 AddForce(correctionForce, false, inTaintTime); 364 AddForce(correctionForce, false, inTaintTime);
385 ret = true; 365 ret = true;
386 } 366 }
@@ -399,17 +379,17 @@ public class BSPrim : BSPhysObject
399 uint wayOutThere = Constants.RegionSize * Constants.RegionSize; 379 uint wayOutThere = Constants.RegionSize * Constants.RegionSize;
400 // There have been instances of objects getting thrown way out of bounds and crashing 380 // There have been instances of objects getting thrown way out of bounds and crashing
401 // the border crossing code. 381 // the border crossing code.
402 if ( _position.X < -Constants.RegionSize || _position.X > wayOutThere 382 if ( RawPosition.X < -Constants.RegionSize || RawPosition.X > wayOutThere
403 || _position.Y < -Constants.RegionSize || _position.Y > wayOutThere 383 || RawPosition.Y < -Constants.RegionSize || RawPosition.Y > wayOutThere
404 || _position.Z < -Constants.RegionSize || _position.Z > wayOutThere) 384 || RawPosition.Z < -Constants.RegionSize || RawPosition.Z > wayOutThere)
405 { 385 {
406 _position = new OMV.Vector3(10, 10, 50); 386 RawPosition = new OMV.Vector3(10, 10, 50);
407 ZeroMotion(inTaintTime); 387 ZeroMotion(inTaintTime);
408 ret = true; 388 ret = true;
409 } 389 }
410 if (_velocity.LengthSquared() > BSParam.MaxLinearVelocity) 390 if (RawVelocity.LengthSquared() > BSParam.MaxLinearVelocity)
411 { 391 {
412 _velocity = Util.ClampV(_velocity, BSParam.MaxLinearVelocity); 392 RawVelocity = Util.ClampV(RawVelocity, BSParam.MaxLinearVelocity);
413 ret = true; 393 ret = true;
414 } 394 }
415 if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared) 395 if (_rotationalVelocity.LengthSquared() > BSParam.MaxAngularVelocitySquared)
@@ -434,7 +414,7 @@ public class BSPrim : BSPhysObject
434 get { return _mass; } 414 get { return _mass; }
435 } 415 }
436 // used when we only want this prim's mass and not the linkset thing 416 // used when we only want this prim's mass and not the linkset thing
437 public override float RawMass { 417 public override float RawMass {
438 get { return _mass; } 418 get { return _mass; }
439 } 419 }
440 // Set the physical mass to the passed mass. 420 // Set the physical mass to the passed mass.
@@ -445,10 +425,10 @@ public class BSPrim : BSPhysObject
445 { 425 {
446 if (IsStatic) 426 if (IsStatic)
447 { 427 {
448 PhysicsScene.PE.SetGravity(PhysBody, PhysicsScene.DefaultGravity); 428 PhysScene.PE.SetGravity(PhysBody, PhysScene.DefaultGravity);
449 Inertia = OMV.Vector3.Zero; 429 Inertia = OMV.Vector3.Zero;
450 PhysicsScene.PE.SetMassProps(PhysBody, 0f, Inertia); 430 PhysScene.PE.SetMassProps(PhysBody, 0f, Inertia);
451 PhysicsScene.PE.UpdateInertiaTensor(PhysBody); 431 PhysScene.PE.UpdateInertiaTensor(PhysBody);
452 } 432 }
453 else 433 else
454 { 434 {
@@ -457,16 +437,19 @@ public class BSPrim : BSPhysObject
457 // Changing interesting properties doesn't change proxy and collision cache 437 // Changing interesting properties doesn't change proxy and collision cache
458 // information. The Bullet solution is to re-add the object to the world 438 // information. The Bullet solution is to re-add the object to the world
459 // after parameters are changed. 439 // after parameters are changed.
460 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 440 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
461 } 441 }
462 442
463 // The computation of mass props requires gravity to be set on the object. 443 // The computation of mass props requires gravity to be set on the object.
464 Gravity = ComputeGravity(Buoyancy); 444 Gravity = ComputeGravity(Buoyancy);
465 PhysicsScene.PE.SetGravity(PhysBody, Gravity); 445 PhysScene.PE.SetGravity(PhysBody, Gravity);
446
447 // OMV.Vector3 currentScale = PhysScene.PE.GetLocalScaling(PhysShape.physShapeInfo); // DEBUG DEBUG
448 // DetailLog("{0},BSPrim.UpdateMassProperties,currentScale{1},shape={2}", LocalID, currentScale, PhysShape.physShapeInfo); // DEBUG DEBUG
466 449
467 Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); 450 Inertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
468 PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia); 451 PhysScene.PE.SetMassProps(PhysBody, physMass, Inertia);
469 PhysicsScene.PE.UpdateInertiaTensor(PhysBody); 452 PhysScene.PE.UpdateInertiaTensor(PhysBody);
470 453
471 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}", 454 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}",
472 LocalID, physMass, Inertia, Gravity, inWorld); 455 LocalID, physMass, Inertia, Gravity, inWorld);
@@ -482,7 +465,7 @@ public class BSPrim : BSPhysObject
482 // Return what gravity should be set to this very moment 465 // Return what gravity should be set to this very moment
483 public OMV.Vector3 ComputeGravity(float buoyancy) 466 public OMV.Vector3 ComputeGravity(float buoyancy)
484 { 467 {
485 OMV.Vector3 ret = PhysicsScene.DefaultGravity; 468 OMV.Vector3 ret = PhysScene.DefaultGravity;
486 469
487 if (!IsStatic) 470 if (!IsStatic)
488 { 471 {
@@ -506,83 +489,121 @@ public class BSPrim : BSPhysObject
506 } 489 }
507 490
508 public override OMV.Vector3 Force { 491 public override OMV.Vector3 Force {
509 get { return _force; } 492 get { return RawForce; }
510 set { 493 set {
511 _force = value; 494 RawForce = value;
512 if (_force != OMV.Vector3.Zero) 495 EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate()
513 { 496 {
514 // If the force is non-zero, it must be reapplied each tick because 497 return new BSActorSetForce(PhysScene, this, SetForceActorName);
515 // Bullet clears the forces applied last frame. 498 });
516 RegisterPreStepAction("BSPrim.setForce", LocalID, 499 }
517 delegate(float timeStep) 500 }
518 {
519 if (!IsPhysicallyActive || _force == OMV.Vector3.Zero)
520 {
521 UnRegisterPreStepAction("BSPrim.setForce", LocalID);
522 return;
523 }
524 501
525 DetailLog("{0},BSPrim.setForce,preStep,force={1}", LocalID, _force); 502 // Find and return a handle to the current vehicle actor.
526 if (PhysBody.HasPhysicalBody) 503 // Return 'null' if there is no vehicle actor.
527 { 504 public BSDynamics GetVehicleActor(bool createIfNone)
528 PhysicsScene.PE.ApplyCentralForce(PhysBody, _force); 505 {
529 ActivateIfPhysical(false); 506 BSDynamics ret = null;
530 } 507 BSActor actor;
531 } 508 if (PhysicalActors.TryGetActor(VehicleActorName, out actor))
532 ); 509 {
533 } 510 ret = actor as BSDynamics;
534 else 511 }
512 else
513 {
514 if (createIfNone)
535 { 515 {
536 UnRegisterPreStepAction("BSPrim.setForce", LocalID); 516 ret = new BSDynamics(PhysScene, this, VehicleActorName);
517 PhysicalActors.Add(ret.ActorName, ret);
537 } 518 }
538 } 519 }
520 return ret;
539 } 521 }
540 522
541 public override int VehicleType { 523 public override int VehicleType {
542 get { 524 get {
543 return (int)VehicleActor.Type; // if we are a vehicle, return that type 525 int ret = (int)Vehicle.TYPE_NONE;
526 BSDynamics vehicleActor = GetVehicleActor(false /* createIfNone */);
527 if (vehicleActor != null)
528 ret = (int)vehicleActor.Type;
529 return ret;
544 } 530 }
545 set { 531 set {
546 Vehicle type = (Vehicle)value; 532 Vehicle type = (Vehicle)value;
547 533
548 PhysicsScene.TaintedObject("setVehicleType", delegate() 534 PhysScene.TaintedObject(LocalID, "setVehicleType", delegate()
549 { 535 {
550 // Done at taint time so we're sure the physics engine is not using the variables 536 // Some vehicle scripts change vehicle type on the fly as an easy way to
551 // Vehicle code changes the parameters for this vehicle type. 537 // change all the parameters. Like a plane changing to CAR when on the
552 VehicleActor.ProcessTypeChange(type); 538 // ground. In this case, don't want to zero motion.
553 ActivateIfPhysical(false); 539 // ZeroMotion(true /* inTaintTime */);
540 if (type == Vehicle.TYPE_NONE)
541 {
542 // Vehicle type is 'none' so get rid of any actor that may have been allocated.
543 BSDynamics vehicleActor = GetVehicleActor(false /* createIfNone */);
544 if (vehicleActor != null)
545 {
546 PhysicalActors.RemoveAndRelease(vehicleActor.ActorName);
547 }
548 }
549 else
550 {
551 // Vehicle type is not 'none' so create an actor and set it running.
552 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
553 if (vehicleActor != null)
554 {
555 vehicleActor.ProcessTypeChange(type);
556 ActivateIfPhysical(false);
557 }
558 }
554 }); 559 });
555 } 560 }
556 } 561 }
557 public override void VehicleFloatParam(int param, float value) 562 public override void VehicleFloatParam(int param, float value)
558 { 563 {
559 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 564 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFloatParam", delegate()
560 { 565 {
561 VehicleActor.ProcessFloatVehicleParam((Vehicle)param, value); 566 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
562 ActivateIfPhysical(false); 567 if (vehicleActor != null)
568 {
569 vehicleActor.ProcessFloatVehicleParam((Vehicle)param, value);
570 ActivateIfPhysical(false);
571 }
563 }); 572 });
564 } 573 }
565 public override void VehicleVectorParam(int param, OMV.Vector3 value) 574 public override void VehicleVectorParam(int param, OMV.Vector3 value)
566 { 575 {
567 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 576 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleVectorParam", delegate()
568 { 577 {
569 VehicleActor.ProcessVectorVehicleParam((Vehicle)param, value); 578 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
570 ActivateIfPhysical(false); 579 if (vehicleActor != null)
580 {
581 vehicleActor.ProcessVectorVehicleParam((Vehicle)param, value);
582 ActivateIfPhysical(false);
583 }
571 }); 584 });
572 } 585 }
573 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 586 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
574 { 587 {
575 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 588 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleRotationParam", delegate()
576 { 589 {
577 VehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation); 590 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
578 ActivateIfPhysical(false); 591 if (vehicleActor != null)
592 {
593 vehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation);
594 ActivateIfPhysical(false);
595 }
579 }); 596 });
580 } 597 }
581 public override void VehicleFlags(int param, bool remove) 598 public override void VehicleFlags(int param, bool remove)
582 { 599 {
583 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() 600 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFlags", delegate()
584 { 601 {
585 VehicleActor.ProcessVehicleFlags(param, remove); 602 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
603 if (vehicleActor != null)
604 {
605 vehicleActor.ProcessVehicleFlags(param, remove);
606 }
586 }); 607 });
587 } 608 }
588 609
@@ -592,7 +613,7 @@ public class BSPrim : BSPhysObject
592 if (_isVolumeDetect != newValue) 613 if (_isVolumeDetect != newValue)
593 { 614 {
594 _isVolumeDetect = newValue; 615 _isVolumeDetect = newValue;
595 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() 616 PhysScene.TaintedObject(LocalID, "BSPrim.SetVolumeDetect", delegate()
596 { 617 {
597 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); 618 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
598 SetObjectDynamic(true); 619 SetObjectDynamic(true);
@@ -600,10 +621,14 @@ public class BSPrim : BSPhysObject
600 } 621 }
601 return; 622 return;
602 } 623 }
624 public override bool IsVolumeDetect
625 {
626 get { return _isVolumeDetect; }
627 }
603 public override void SetMaterial(int material) 628 public override void SetMaterial(int material)
604 { 629 {
605 base.SetMaterial(material); 630 base.SetMaterial(material);
606 PhysicsScene.TaintedObject("BSPrim.SetMaterial", delegate() 631 PhysScene.TaintedObject(LocalID, "BSPrim.SetMaterial", delegate()
607 { 632 {
608 UpdatePhysicalParameters(); 633 UpdatePhysicalParameters();
609 }); 634 });
@@ -616,7 +641,7 @@ public class BSPrim : BSPhysObject
616 if (base.Friction != value) 641 if (base.Friction != value)
617 { 642 {
618 base.Friction = value; 643 base.Friction = value;
619 PhysicsScene.TaintedObject("BSPrim.setFriction", delegate() 644 PhysScene.TaintedObject(LocalID, "BSPrim.setFriction", delegate()
620 { 645 {
621 UpdatePhysicalParameters(); 646 UpdatePhysicalParameters();
622 }); 647 });
@@ -631,7 +656,7 @@ public class BSPrim : BSPhysObject
631 if (base.Restitution != value) 656 if (base.Restitution != value)
632 { 657 {
633 base.Restitution = value; 658 base.Restitution = value;
634 PhysicsScene.TaintedObject("BSPrim.setRestitution", delegate() 659 PhysScene.TaintedObject(LocalID, "BSPrim.setRestitution", delegate()
635 { 660 {
636 UpdatePhysicalParameters(); 661 UpdatePhysicalParameters();
637 }); 662 });
@@ -648,7 +673,7 @@ public class BSPrim : BSPhysObject
648 if (base.Density != value) 673 if (base.Density != value)
649 { 674 {
650 base.Density = value; 675 base.Density = value;
651 PhysicsScene.TaintedObject("BSPrim.setDensity", delegate() 676 PhysScene.TaintedObject(LocalID, "BSPrim.setDensity", delegate()
652 { 677 {
653 UpdatePhysicalParameters(); 678 UpdatePhysicalParameters();
654 }); 679 });
@@ -663,93 +688,66 @@ public class BSPrim : BSPhysObject
663 if (base.GravModifier != value) 688 if (base.GravModifier != value)
664 { 689 {
665 base.GravModifier = value; 690 base.GravModifier = value;
666 PhysicsScene.TaintedObject("BSPrim.setGravityModifier", delegate() 691 PhysScene.TaintedObject(LocalID, "BSPrim.setGravityModifier", delegate()
667 { 692 {
668 UpdatePhysicalParameters(); 693 UpdatePhysicalParameters();
669 }); 694 });
670 } 695 }
671 } 696 }
672 } 697 }
673 public override OMV.Vector3 RawVelocity
674 {
675 get { return _velocity; }
676 set { _velocity = value; }
677 }
678 public override OMV.Vector3 Velocity { 698 public override OMV.Vector3 Velocity {
679 get { return _velocity; } 699 get { return RawVelocity; }
680 set { 700 set {
681 _velocity = value; 701 RawVelocity = value;
682 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() 702 PhysScene.TaintedObject(LocalID, "BSPrim.setVelocity", delegate()
683 { 703 {
684 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 704 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity);
685 ForceVelocity = _velocity; 705 ForceVelocity = RawVelocity;
686 }); 706 });
687 } 707 }
688 } 708 }
689 public override OMV.Vector3 ForceVelocity { 709 public override OMV.Vector3 ForceVelocity {
690 get { return _velocity; } 710 get { return RawVelocity; }
691 set { 711 set {
692 PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity"); 712 PhysScene.AssertInTaintTime("BSPrim.ForceVelocity");
693 713
694 _velocity = Util.ClampV(value, BSParam.MaxLinearVelocity); 714 RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
695 if (PhysBody.HasPhysicalBody) 715 if (PhysBody.HasPhysicalBody)
696 { 716 {
697 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, _velocity); 717 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity);
698 PhysicsScene.PE.SetLinearVelocity(PhysBody, _velocity); 718 PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
699 ActivateIfPhysical(false); 719 ActivateIfPhysical(false);
700 } 720 }
701 } 721 }
702 } 722 }
703 public override OMV.Vector3 Torque { 723 public override OMV.Vector3 Torque {
704 get { return _torque; } 724 get { return RawTorque; }
705 set { 725 set {
706 _torque = value; 726 RawTorque = value;
707 if (_torque != OMV.Vector3.Zero) 727 EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate()
708 {
709 // If the torque is non-zero, it must be reapplied each tick because
710 // Bullet clears the forces applied last frame.
711 RegisterPreStepAction("BSPrim.setTorque", LocalID,
712 delegate(float timeStep)
713 {
714 if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero)
715 {
716 UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
717 return;
718 }
719
720 if (PhysBody.HasPhysicalBody)
721 AddAngularForce(_torque, false, true);
722 }
723 );
724 }
725 else
726 { 728 {
727 UnRegisterPreStepAction("BSPrim.setTorque", LocalID); 729 return new BSActorSetTorque(PhysScene, this, SetTorqueActorName);
728 } 730 });
729 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 731 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque);
730 } 732 }
731 } 733 }
732 public override OMV.Vector3 Acceleration { 734 public override OMV.Vector3 Acceleration {
733 get { return _acceleration; } 735 get { return _acceleration; }
734 set { _acceleration = value; } 736 set { _acceleration = value; }
735 } 737 }
736 public override OMV.Quaternion RawOrientation 738
737 {
738 get { return _orientation; }
739 set { _orientation = value; }
740 }
741 public override OMV.Quaternion Orientation { 739 public override OMV.Quaternion Orientation {
742 get { 740 get {
743 return _orientation; 741 return RawOrientation;
744 } 742 }
745 set { 743 set {
746 if (_orientation == value) 744 if (RawOrientation == value)
747 return; 745 return;
748 _orientation = value; 746 RawOrientation = value;
749 747
750 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() 748 PhysScene.TaintedObject(LocalID, "BSPrim.setOrientation", delegate()
751 { 749 {
752 ForceOrientation = _orientation; 750 ForceOrientation = RawOrientation;
753 }); 751 });
754 } 752 }
755 } 753 }
@@ -758,14 +756,14 @@ public class BSPrim : BSPhysObject
758 { 756 {
759 get 757 get
760 { 758 {
761 _orientation = PhysicsScene.PE.GetOrientation(PhysBody); 759 RawOrientation = PhysScene.PE.GetOrientation(PhysBody);
762 return _orientation; 760 return RawOrientation;
763 } 761 }
764 set 762 set
765 { 763 {
766 _orientation = value; 764 RawOrientation = value;
767 if (PhysBody.HasPhysicalBody) 765 if (PhysBody.HasPhysicalBody)
768 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 766 PhysScene.PE.SetTranslation(PhysBody, RawPosition, RawOrientation);
769 } 767 }
770 } 768 }
771 public override int PhysicsActorType { 769 public override int PhysicsActorType {
@@ -778,7 +776,7 @@ public class BSPrim : BSPhysObject
778 if (_isPhysical != value) 776 if (_isPhysical != value)
779 { 777 {
780 _isPhysical = value; 778 _isPhysical = value;
781 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() 779 PhysScene.TaintedObject(LocalID, "BSPrim.setIsPhysical", delegate()
782 { 780 {
783 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); 781 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
784 SetObjectDynamic(true); 782 SetObjectDynamic(true);
@@ -822,24 +820,24 @@ public class BSPrim : BSPhysObject
822 // isSolid: other objects bounce off of this object 820 // isSolid: other objects bounce off of this object
823 // isVolumeDetect: other objects pass through but can generate collisions 821 // isVolumeDetect: other objects pass through but can generate collisions
824 // collisionEvents: whether this object returns collision events 822 // collisionEvents: whether this object returns collision events
823 // NOTE: overloaded by BSPrimLinkable to also update linkset physical parameters.
825 public virtual void UpdatePhysicalParameters() 824 public virtual void UpdatePhysicalParameters()
826 { 825 {
827 if (!PhysBody.HasPhysicalBody) 826 if (!PhysBody.HasPhysicalBody)
828 { 827 {
829 // This would only happen if updates are called for during initialization when the body is not set up yet. 828 // This would only happen if updates are called for during initialization when the body is not set up yet.
830 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID); 829 // DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID);
831 return; 830 return;
832 } 831 }
833 832
834 // Mangling all the physical properties requires the object not be in the physical world. 833 // Mangling all the physical properties requires the object not be in the physical world.
835 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). 834 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
836 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 835 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
837 836
838 // Set up the object physicalness (does gravity and collisions move this object) 837 // Set up the object physicalness (does gravity and collisions move this object)
839 MakeDynamic(IsStatic); 838 MakeDynamic(IsStatic);
840 839
841 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) 840 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
842 VehicleActor.Refresh();
843 PhysicalActors.Refresh(); 841 PhysicalActors.Refresh();
844 842
845 // Arrange for collision events if the simulator wants them 843 // Arrange for collision events if the simulator wants them
@@ -851,10 +849,11 @@ public class BSPrim : BSPhysObject
851 AddObjectToPhysicalWorld(); 849 AddObjectToPhysicalWorld();
852 850
853 // Rebuild its shape 851 // Rebuild its shape
854 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); 852 PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody);
855 853
856 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}", 854 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}",
857 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape); 855 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(),
856 CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
858 } 857 }
859 858
860 // "Making dynamic" means changing to and from static. 859 // "Making dynamic" means changing to and from static.
@@ -867,28 +866,28 @@ public class BSPrim : BSPhysObject
867 if (makeStatic) 866 if (makeStatic)
868 { 867 {
869 // Become a Bullet 'static' object type 868 // Become a Bullet 'static' object type
870 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); 869 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
871 // Stop all movement 870 // Stop all movement
872 ZeroMotion(true); 871 ZeroMotion(true);
873 872
874 // Set various physical properties so other object interact properly 873 // Set various physical properties so other object interact properly
875 PhysicsScene.PE.SetFriction(PhysBody, Friction); 874 PhysScene.PE.SetFriction(PhysBody, Friction);
876 PhysicsScene.PE.SetRestitution(PhysBody, Restitution); 875 PhysScene.PE.SetRestitution(PhysBody, Restitution);
877 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 876 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
878 877
879 // Mass is zero which disables a bunch of physics stuff in Bullet 878 // Mass is zero which disables a bunch of physics stuff in Bullet
880 UpdatePhysicalMassProperties(0f, false); 879 UpdatePhysicalMassProperties(0f, false);
881 // Set collision detection parameters 880 // Set collision detection parameters
882 if (BSParam.CcdMotionThreshold > 0f) 881 if (BSParam.CcdMotionThreshold > 0f)
883 { 882 {
884 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 883 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
885 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 884 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
886 } 885 }
887 886
888 // The activation state is 'disabled' so Bullet will not try to act on it. 887 // The activation state is 'disabled' so Bullet will not try to act on it.
889 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION); 888 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION);
890 // Start it out sleeping and physical actions could wake it up. 889 // Start it out sleeping and physical actions could wake it up.
891 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING); 890 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING);
892 891
893 // This collides like a static object 892 // This collides like a static object
894 PhysBody.collisionType = CollisionType.Static; 893 PhysBody.collisionType = CollisionType.Static;
@@ -896,11 +895,11 @@ public class BSPrim : BSPhysObject
896 else 895 else
897 { 896 {
898 // Not a Bullet static object 897 // Not a Bullet static object
899 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); 898 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
900 899
901 // Set various physical properties so other object interact properly 900 // Set various physical properties so other object interact properly
902 PhysicsScene.PE.SetFriction(PhysBody, Friction); 901 PhysScene.PE.SetFriction(PhysBody, Friction);
903 PhysicsScene.PE.SetRestitution(PhysBody, Restitution); 902 PhysScene.PE.SetRestitution(PhysBody, Restitution);
904 // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution); 903 // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution);
905 904
906 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 905 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
@@ -908,8 +907,8 @@ public class BSPrim : BSPhysObject
908 // PhysicsScene.PE.ClearAllForces(BSBody); 907 // PhysicsScene.PE.ClearAllForces(BSBody);
909 908
910 // For good measure, make sure the transform is set through to the motion state 909 // For good measure, make sure the transform is set through to the motion state
911 ForcePosition = _position; 910 ForcePosition = RawPosition;
912 ForceVelocity = _velocity; 911 ForceVelocity = RawVelocity;
913 ForceRotationalVelocity = _rotationalVelocity; 912 ForceRotationalVelocity = _rotationalVelocity;
914 913
915 // A dynamic object has mass 914 // A dynamic object has mass
@@ -918,22 +917,22 @@ public class BSPrim : BSPhysObject
918 // Set collision detection parameters 917 // Set collision detection parameters
919 if (BSParam.CcdMotionThreshold > 0f) 918 if (BSParam.CcdMotionThreshold > 0f)
920 { 919 {
921 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 920 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
922 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 921 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
923 } 922 }
924 923
925 // Various values for simulation limits 924 // Various values for simulation limits
926 PhysicsScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping); 925 PhysScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping);
927 PhysicsScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime); 926 PhysScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime);
928 PhysicsScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold); 927 PhysScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold);
929 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 928 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
930 929
931 // This collides like an object. 930 // This collides like an object.
932 PhysBody.collisionType = CollisionType.Dynamic; 931 PhysBody.collisionType = CollisionType.Dynamic;
933 932
934 // Force activation of the object so Bullet will act on it. 933 // Force activation of the object so Bullet will act on it.
935 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. 934 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
936 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); 935 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
937 } 936 }
938 } 937 }
939 938
@@ -943,7 +942,7 @@ public class BSPrim : BSPhysObject
943 // the functions after this one set up the state of a possibly newly created collision body. 942 // the functions after this one set up the state of a possibly newly created collision body.
944 private void MakeSolid(bool makeSolid) 943 private void MakeSolid(bool makeSolid)
945 { 944 {
946 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(PhysBody); 945 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysScene.PE.GetBodyType(PhysBody);
947 if (makeSolid) 946 if (makeSolid)
948 { 947 {
949 // Verify the previous code created the correct shape for this type of thing. 948 // Verify the previous code created the correct shape for this type of thing.
@@ -951,7 +950,7 @@ public class BSPrim : BSPhysObject
951 { 950 {
952 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); 951 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
953 } 952 }
954 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); 953 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
955 } 954 }
956 else 955 else
957 { 956 {
@@ -959,32 +958,23 @@ public class BSPrim : BSPhysObject
959 { 958 {
960 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); 959 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
961 } 960 }
962 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); 961 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
963 962
964 // Change collision info from a static object to a ghosty collision object 963 // Change collision info from a static object to a ghosty collision object
965 PhysBody.collisionType = CollisionType.VolumeDetect; 964 PhysBody.collisionType = CollisionType.VolumeDetect;
966 } 965 }
967 } 966 }
968 967
969 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so
970 // they need waking up when parameters are changed.
971 // Called in taint-time!!
972 private void ActivateIfPhysical(bool forceIt)
973 {
974 if (IsPhysical && PhysBody.HasPhysicalBody)
975 PhysicsScene.PE.Activate(PhysBody, forceIt);
976 }
977
978 // Turn on or off the flag controlling whether collision events are returned to the simulator. 968 // Turn on or off the flag controlling whether collision events are returned to the simulator.
979 private void EnableCollisions(bool wantsCollisionEvents) 969 private void EnableCollisions(bool wantsCollisionEvents)
980 { 970 {
981 if (wantsCollisionEvents) 971 if (wantsCollisionEvents)
982 { 972 {
983 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 973 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
984 } 974 }
985 else 975 else
986 { 976 {
987 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 977 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
988 } 978 }
989 } 979 }
990 980
@@ -995,7 +985,7 @@ public class BSPrim : BSPhysObject
995 { 985 {
996 if (PhysBody.HasPhysicalBody) 986 if (PhysBody.HasPhysicalBody)
997 { 987 {
998 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); 988 PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody);
999 } 989 }
1000 else 990 else
1001 { 991 {
@@ -1030,12 +1020,12 @@ public class BSPrim : BSPhysObject
1030 public override bool FloatOnWater { 1020 public override bool FloatOnWater {
1031 set { 1021 set {
1032 _floatOnWater = value; 1022 _floatOnWater = value;
1033 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() 1023 PhysScene.TaintedObject(LocalID, "BSPrim.setFloatOnWater", delegate()
1034 { 1024 {
1035 if (_floatOnWater) 1025 if (_floatOnWater)
1036 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 1026 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
1037 else 1027 else
1038 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 1028 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
1039 }); 1029 });
1040 } 1030 }
1041 } 1031 }
@@ -1047,7 +1037,7 @@ public class BSPrim : BSPhysObject
1047 _rotationalVelocity = value; 1037 _rotationalVelocity = value;
1048 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity); 1038 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity);
1049 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 1039 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
1050 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 1040 PhysScene.TaintedObject(LocalID, "BSPrim.setRotationalVelocity", delegate()
1051 { 1041 {
1052 ForceRotationalVelocity = _rotationalVelocity; 1042 ForceRotationalVelocity = _rotationalVelocity;
1053 }); 1043 });
@@ -1062,7 +1052,7 @@ public class BSPrim : BSPhysObject
1062 if (PhysBody.HasPhysicalBody) 1052 if (PhysBody.HasPhysicalBody)
1063 { 1053 {
1064 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 1054 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
1065 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); 1055 PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
1066 // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); 1056 // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
1067 ActivateIfPhysical(false); 1057 ActivateIfPhysical(false);
1068 } 1058 }
@@ -1078,7 +1068,7 @@ public class BSPrim : BSPhysObject
1078 get { return _buoyancy; } 1068 get { return _buoyancy; }
1079 set { 1069 set {
1080 _buoyancy = value; 1070 _buoyancy = value;
1081 PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() 1071 PhysScene.TaintedObject(LocalID, "BSPrim.setBuoyancy", delegate()
1082 { 1072 {
1083 ForceBuoyancy = _buoyancy; 1073 ForceBuoyancy = _buoyancy;
1084 }); 1074 });
@@ -1096,179 +1086,54 @@ public class BSPrim : BSPhysObject
1096 } 1086 }
1097 } 1087 }
1098 1088
1099 // Used for MoveTo
1100 public override OMV.Vector3 PIDTarget {
1101 set
1102 {
1103 // TODO: add a sanity check -- don't move more than a region or something like that.
1104 _PIDTarget = value;
1105 }
1106 }
1107 public override float PIDTau {
1108 set { _PIDTau = value; }
1109 }
1110 public override bool PIDActive { 1089 public override bool PIDActive {
1111 set { 1090 set {
1112 if (value) 1091 base.MoveToTargetActive = value;
1092 EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate()
1113 { 1093 {
1114 // We're taking over after this. 1094 return new BSActorMoveToTarget(PhysScene, this, MoveToTargetActorName);
1115 ZeroMotion(true); 1095 });
1116 1096 }
1117 _targetMotor = new BSVMotor("BSPrim.PIDTarget", 1097 }
1118 _PIDTau, // timeScale
1119 BSMotor.Infinite, // decay time scale
1120 BSMotor.InfiniteVector, // friction timescale
1121 1f // efficiency
1122 );
1123 _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1124 _targetMotor.SetTarget(_PIDTarget);
1125 _targetMotor.SetCurrent(RawPosition);
1126 /*
1127 _targetMotor = new BSPIDVMotor("BSPrim.PIDTarget");
1128 _targetMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1129
1130 _targetMotor.SetTarget(_PIDTarget);
1131 _targetMotor.SetCurrent(RawPosition);
1132 _targetMotor.TimeScale = _PIDTau;
1133 _targetMotor.Efficiency = 1f;
1134 */
1135
1136 RegisterPreStepAction("BSPrim.PIDTarget", LocalID, delegate(float timeStep)
1137 {
1138 if (!IsPhysicallyActive)
1139 {
1140 UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID);
1141 return;
1142 }
1143
1144 OMV.Vector3 origPosition = RawPosition; // DEBUG DEBUG (for printout below)
1145
1146 // 'movePosition' is where we'd like the prim to be at this moment.
1147 OMV.Vector3 movePosition = RawPosition + _targetMotor.Step(timeStep);
1148 1098
1149 // If we are very close to our target, turn off the movement motor. 1099 public override OMV.Vector3 PIDTarget
1150 if (_targetMotor.ErrorIsZero()) 1100 {
1151 { 1101 set
1152 DetailLog("{0},BSPrim.PIDTarget,zeroMovement,movePos={1},pos={2},mass={3}", 1102 {
1153 LocalID, movePosition, RawPosition, Mass); 1103 base.PIDTarget = value;
1154 ForcePosition = _targetMotor.TargetValue; 1104 BSActor actor;
1155 _targetMotor.Enabled = false; 1105 if (PhysicalActors.TryGetActor(MoveToTargetActorName, out actor))
1156 }
1157 else
1158 {
1159 _position = movePosition;
1160 PositionSanityCheck(true /* intaintTime */);
1161 ForcePosition = _position;
1162 }
1163 DetailLog("{0},BSPrim.PIDTarget,move,fromPos={1},movePos={2}", LocalID, origPosition, movePosition);
1164 });
1165 }
1166 else
1167 { 1106 {
1168 // Stop any targetting 1107 // if the actor exists, tell it to refresh its values.
1169 UnRegisterPreStepAction("BSPrim.PIDTarget", LocalID); 1108 actor.Refresh();
1170 } 1109 }
1110
1171 } 1111 }
1172 } 1112 }
1173
1174 // Used for llSetHoverHeight and maybe vehicle height 1113 // Used for llSetHoverHeight and maybe vehicle height
1175 // Hover Height will override MoveTo target's Z 1114 // Hover Height will override MoveTo target's Z
1176 public override bool PIDHoverActive { 1115 public override bool PIDHoverActive {
1177 set { 1116 set {
1178 if (value) 1117 base.HoverActive = value;
1118 EnableActor(HoverActive, HoverActorName, delegate()
1179 { 1119 {
1180 // Turning the target on 1120 return new BSActorHover(PhysScene, this, HoverActorName);
1181 _hoverMotor = new BSFMotor("BSPrim.Hover", 1121 });
1182 _PIDHoverTau, // timeScale
1183 BSMotor.Infinite, // decay time scale
1184 BSMotor.Infinite, // friction timescale
1185 1f // efficiency
1186 );
1187 _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
1188 _hoverMotor.SetCurrent(RawPosition.Z);
1189 _hoverMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
1190
1191 RegisterPreStepAction("BSPrim.Hover", LocalID, delegate(float timeStep)
1192 {
1193 // Don't do hovering while the object is selected.
1194 if (!IsPhysicallyActive)
1195 return;
1196
1197 _hoverMotor.SetCurrent(RawPosition.Z);
1198 _hoverMotor.SetTarget(ComputeCurrentPIDHoverHeight());
1199 float targetHeight = _hoverMotor.Step(timeStep);
1200
1201 // 'targetHeight' is where we'd like the Z of the prim to be at this moment.
1202 // Compute the amount of force to push us there.
1203 float moveForce = (targetHeight - RawPosition.Z) * Mass;
1204 // Undo anything the object thinks it's doing at the moment
1205 moveForce = -RawVelocity.Z * Mass;
1206
1207 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, new OMV.Vector3(0f, 0f, moveForce));
1208 DetailLog("{0},BSPrim.Hover,move,targHt={1},moveForce={2},mass={3}", LocalID, targetHeight, moveForce, Mass);
1209 });
1210 }
1211 else
1212 {
1213 UnRegisterPreStepAction("BSPrim.Hover", LocalID);
1214 }
1215 }
1216 }
1217 public override float PIDHoverHeight {
1218 set { _PIDHoverHeight = value; }
1219 }
1220 public override PIDHoverType PIDHoverType {
1221 set { _PIDHoverType = value; }
1222 }
1223 public override float PIDHoverTau {
1224 set { _PIDHoverTau = value; }
1225 }
1226 // Based on current position, determine what we should be hovering at now.
1227 // Must recompute often. What if we walked offa cliff>
1228 private float ComputeCurrentPIDHoverHeight()
1229 {
1230 float ret = _PIDHoverHeight;
1231 float groundHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
1232
1233 switch (_PIDHoverType)
1234 {
1235 case PIDHoverType.Ground:
1236 ret = groundHeight + _PIDHoverHeight;
1237 break;
1238 case PIDHoverType.GroundAndWater:
1239 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(RawPosition);
1240 if (groundHeight > waterHeight)
1241 {
1242 ret = groundHeight + _PIDHoverHeight;
1243 }
1244 else
1245 {
1246 ret = waterHeight + _PIDHoverHeight;
1247 }
1248 break;
1249 } 1122 }
1250 return ret;
1251 } 1123 }
1252 1124
1253
1254 // For RotLookAt
1255 public override OMV.Quaternion APIDTarget { set { return; } }
1256 public override bool APIDActive { set { return; } }
1257 public override float APIDStrength { set { return; } }
1258 public override float APIDDamping { set { return; } }
1259
1260 public override void AddForce(OMV.Vector3 force, bool pushforce) { 1125 public override void AddForce(OMV.Vector3 force, bool pushforce) {
1261 // Per documentation, max force is limited. 1126 // Per documentation, max force is limited.
1262 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 1127 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
1263 1128
1264 // Since this force is being applied in only one step, make this a force per second. 1129 // Since this force is being applied in only one step, make this a force per second.
1265 addForce /= PhysicsScene.LastTimeStep; 1130 addForce /= PhysScene.LastTimeStep;
1266 AddForce(addForce, pushforce, false /* inTaintTime */); 1131 AddForce(addForce, pushforce, false /* inTaintTime */);
1267 } 1132 }
1268 1133
1269 // Applying a force just adds this to the total force on the object. 1134 // Applying a force just adds this to the total force on the object.
1270 // This added force will only last the next simulation tick. 1135 // This added force will only last the next simulation tick.
1271 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 1136 public override void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
1272 // for an object, doesn't matter if force is a pushforce or not 1137 // for an object, doesn't matter if force is a pushforce or not
1273 if (IsPhysicallyActive) 1138 if (IsPhysicallyActive)
1274 { 1139 {
@@ -1277,13 +1142,15 @@ public class BSPrim : BSPhysObject
1277 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); 1142 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
1278 1143
1279 OMV.Vector3 addForce = force; 1144 OMV.Vector3 addForce = force;
1280 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() 1145 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddForce", delegate()
1281 { 1146 {
1282 // Bullet adds this central force to the total force for this tick 1147 // Bullet adds this central force to the total force for this tick.
1148 // Deep down in Bullet:
1149 // linearVelocity += totalForce / mass * timeStep;
1283 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce); 1150 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
1284 if (PhysBody.HasPhysicalBody) 1151 if (PhysBody.HasPhysicalBody)
1285 { 1152 {
1286 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); 1153 PhysScene.PE.ApplyCentralForce(PhysBody, addForce);
1287 ActivateIfPhysical(false); 1154 ActivateIfPhysical(false);
1288 } 1155 }
1289 }); 1156 });
@@ -1305,13 +1172,13 @@ public class BSPrim : BSPhysObject
1305 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude); 1172 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude);
1306 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse); 1173 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse);
1307 1174
1308 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate() 1175 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddImpulse", delegate()
1309 { 1176 {
1310 // Bullet adds this impulse immediately to the velocity 1177 // Bullet adds this impulse immediately to the velocity
1311 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse); 1178 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse);
1312 if (PhysBody.HasPhysicalBody) 1179 if (PhysBody.HasPhysicalBody)
1313 { 1180 {
1314 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, addImpulse); 1181 PhysScene.PE.ApplyCentralImpulse(PhysBody, addImpulse);
1315 ActivateIfPhysical(false); 1182 ActivateIfPhysical(false);
1316 } 1183 }
1317 }); 1184 });
@@ -1324,20 +1191,18 @@ public class BSPrim : BSPhysObject
1324 } 1191 }
1325 } 1192 }
1326 1193
1327 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 1194 // BSPhysObject.AddAngularForce()
1328 AddAngularForce(force, pushforce, false); 1195 public override void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
1329 }
1330 public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime)
1331 { 1196 {
1332 if (force.IsFinite()) 1197 if (force.IsFinite())
1333 { 1198 {
1334 OMV.Vector3 angForce = force; 1199 OMV.Vector3 angForce = force;
1335 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() 1200 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddAngularForce", delegate()
1336 { 1201 {
1337 if (PhysBody.HasPhysicalBody) 1202 if (PhysBody.HasPhysicalBody)
1338 { 1203 {
1339 DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce); 1204 DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce);
1340 PhysicsScene.PE.ApplyTorque(PhysBody, angForce); 1205 PhysScene.PE.ApplyTorque(PhysBody, angForce);
1341 ActivateIfPhysical(false); 1206 ActivateIfPhysical(false);
1342 } 1207 }
1343 }); 1208 });
@@ -1356,11 +1221,11 @@ public class BSPrim : BSPhysObject
1356 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) 1221 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1357 { 1222 {
1358 OMV.Vector3 applyImpulse = impulse; 1223 OMV.Vector3 applyImpulse = impulse;
1359 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() 1224 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ApplyTorqueImpulse", delegate()
1360 { 1225 {
1361 if (PhysBody.HasPhysicalBody) 1226 if (PhysBody.HasPhysicalBody)
1362 { 1227 {
1363 PhysicsScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse); 1228 PhysScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse);
1364 ActivateIfPhysical(false); 1229 ActivateIfPhysical(false);
1365 } 1230 }
1366 }); 1231 });
@@ -1649,6 +1514,8 @@ public class BSPrim : BSPhysObject
1649 1514
1650 returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); 1515 returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass);
1651 // DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass); 1516 // DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass);
1517 DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3},pathB={4},pathE={5},profB={6},profE={7},siz={8}",
1518 LocalID, Density, volume, returnMass, pathBegin, pathEnd, profileBegin, profileEnd, _size);
1652 1519
1653 return returnMass; 1520 return returnMass;
1654 }// end CalculateMass 1521 }// end CalculateMass
@@ -1661,13 +1528,14 @@ public class BSPrim : BSPhysObject
1661 { 1528 {
1662 // Create the correct physical representation for this type of object. 1529 // Create the correct physical representation for this type of object.
1663 // Updates base.PhysBody and base.PhysShape with the new information. 1530 // Updates base.PhysBody and base.PhysShape with the new information.
1664 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. 1531 // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary.
1665 PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody) 1532 PhysScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysScene.World, this, delegate(BulletBody pBody, BulletShape pShape)
1666 { 1533 {
1667 // Called if the current prim body is about to be destroyed. 1534 // Called if the current prim body is about to be destroyed.
1668 // Remove all the physical dependencies on the old body. 1535 // Remove all the physical dependencies on the old body.
1669 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) 1536 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...)
1670 RemoveBodyDependencies(); 1537 // Note: this virtual function is overloaded by BSPrimLinkable to remove linkset constraints.
1538 RemoveDependencies();
1671 }); 1539 });
1672 1540
1673 // Make sure the properties are set on the new object 1541 // Make sure the properties are set on the new object
@@ -1675,27 +1543,45 @@ public class BSPrim : BSPhysObject
1675 return; 1543 return;
1676 } 1544 }
1677 1545
1678 protected virtual void RemoveBodyDependencies() 1546 // Called at taint-time
1547 protected virtual void RemoveDependencies()
1548 {
1549 PhysicalActors.RemoveDependencies();
1550 }
1551
1552 #region Extension
1553 public override object Extension(string pFunct, params object[] pParams)
1679 { 1554 {
1680 VehicleActor.RemoveBodyDependencies(); 1555 DetailLog("{0} BSPrim.Extension,op={1}", LocalID, pFunct);
1681 PhysicalActors.RemoveBodyDependencies(); 1556 object ret = null;
1557 switch (pFunct)
1558 {
1559 default:
1560 ret = base.Extension(pFunct, pParams);
1561 break;
1562 }
1563 return ret;
1682 } 1564 }
1565 #endregion // Extension
1683 1566
1684 // The physics engine says that properties have updated. Update same and inform 1567 // The physics engine says that properties have updated. Update same and inform
1685 // the world that things have changed. 1568 // the world that things have changed.
1569 // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimLinkable which modifies updates from root and children prims.
1570 // NOTE: BSPrim.UpdateProperties is overloaded by BSPrimDisplaced which handles mapping physical position to simulator position.
1686 public override void UpdateProperties(EntityProperties entprop) 1571 public override void UpdateProperties(EntityProperties entprop)
1687 { 1572 {
1573 // Let anyone (like the actors) modify the updated properties before they are pushed into the object and the simulator.
1688 TriggerPreUpdatePropertyAction(ref entprop); 1574 TriggerPreUpdatePropertyAction(ref entprop);
1689 1575
1690 // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG 1576 // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG
1691 1577
1692 // Assign directly to the local variables so the normal set actions do not happen 1578 // Assign directly to the local variables so the normal set actions do not happen
1693 _position = entprop.Position; 1579 RawPosition = entprop.Position;
1694 _orientation = entprop.Rotation; 1580 RawOrientation = entprop.Rotation;
1695 // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be 1581 // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
1696 // very sensitive to velocity changes. 1582 // very sensitive to velocity changes.
1697 if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(_velocity, BSParam.UpdateVelocityChangeThreshold)) 1583 if (entprop.Velocity == OMV.Vector3.Zero || !entprop.Velocity.ApproxEquals(RawVelocity, BSParam.UpdateVelocityChangeThreshold))
1698 _velocity = entprop.Velocity; 1584 RawVelocity = entprop.Velocity;
1699 _acceleration = entprop.Acceleration; 1585 _acceleration = entprop.Acceleration;
1700 _rotationalVelocity = entprop.RotationalVelocity; 1586 _rotationalVelocity = entprop.RotationalVelocity;
1701 1587
@@ -1704,29 +1590,20 @@ public class BSPrim : BSPhysObject
1704 // The sanity check can change the velocity and/or position. 1590 // The sanity check can change the velocity and/or position.
1705 if (PositionSanityCheck(true /* inTaintTime */ )) 1591 if (PositionSanityCheck(true /* inTaintTime */ ))
1706 { 1592 {
1707 entprop.Position = _position; 1593 entprop.Position = RawPosition;
1708 entprop.Velocity = _velocity; 1594 entprop.Velocity = RawVelocity;
1709 entprop.RotationalVelocity = _rotationalVelocity; 1595 entprop.RotationalVelocity = _rotationalVelocity;
1710 entprop.Acceleration = _acceleration; 1596 entprop.Acceleration = _acceleration;
1711 } 1597 }
1712 1598
1713 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG 1599 OMV.Vector3 direction = OMV.Vector3.UnitX * RawOrientation; // DEBUG DEBUG DEBUG
1714 DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction); 1600 DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction);
1715 1601
1716 // remember the current and last set values 1602 // remember the current and last set values
1717 LastEntityProperties = CurrentEntityProperties; 1603 LastEntityProperties = CurrentEntityProperties;
1718 CurrentEntityProperties = entprop; 1604 CurrentEntityProperties = entprop;
1719 1605
1720 base.RequestPhysicsterseUpdate(); 1606 PhysScene.PostUpdate(this);
1721 /*
1722 else
1723 {
1724 // For debugging, report the movement of children
1725 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1726 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1727 entprop.Acceleration, entprop.RotationalVelocity);
1728 }
1729 */
1730 } 1607 }
1731} 1608}
1732} 1609}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
index f1c3b5c..2eb1440 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
@@ -23,11 +23,6 @@
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * The quotations from http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial
28 * are Copyright (c) 2009 Linden Research, Inc and are used under their license
29 * of Creative Commons Attribution-Share Alike 3.0
30 * (http://creativecommons.org/licenses/by-sa/3.0/).
31 */ 26 */
32 27
33using System; 28using System;
@@ -44,14 +39,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
44{ 39{
45public class BSPrimDisplaced : BSPrim 40public class BSPrimDisplaced : BSPrim
46{ 41{
47 // The purpose of this module is to do any mapping between what the simulator thinks 42 // The purpose of this subclass is to do any mapping between what the simulator thinks
48 // the prim position and orientation is and what the physical position/orientation. 43 // the prim position and orientation is and what the physical position/orientation.
49 // This difference happens because Bullet assumes the center-of-mass is the <0,0,0> 44 // This difference happens because Bullet assumes the center-of-mass is the <0,0,0>
50 // of the prim/linkset. The simulator tracks the location of the prim/linkset by 45 // of the prim/linkset. The simulator, on the other hand, tracks the location of
51 // the location of the root prim. So, if center-of-mass is anywhere but the origin 46 // the prim/linkset by the location of the root prim. So, if center-of-mass is anywhere
52 // of the root prim, the physical origin is displaced from the simulator origin. 47 // but the origin of the root prim, the physical origin is displaced from the simulator origin.
53 // 48 //
54 // This routine works by capturing the Force* setting of position/orientation/... and 49 // This routine works by capturing ForcePosition and
55 // adjusting the simulator values (being set) into the physical values. 50 // adjusting the simulator values (being set) into the physical values.
56 // The conversion is also done in the opposite direction (physical origin -> simulator origin). 51 // The conversion is also done in the opposite direction (physical origin -> simulator origin).
57 // 52 //
@@ -59,8 +54,8 @@ public class BSPrimDisplaced : BSPrim
59 // are converted into simulator origin values before being passed to the base 54 // are converted into simulator origin values before being passed to the base
60 // class. 55 // class.
61 56
57 // PositionDisplacement is the vehicle relative distance from the root prim position to the center-of-mass.
62 public virtual OMV.Vector3 PositionDisplacement { get; set; } 58 public virtual OMV.Vector3 PositionDisplacement { get; set; }
63 public virtual OMV.Quaternion OrientationDisplacement { get; set; }
64 59
65 public BSPrimDisplaced(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, 60 public BSPrimDisplaced(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
66 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 61 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
@@ -69,68 +64,96 @@ public class BSPrimDisplaced : BSPrim
69 ClearDisplacement(); 64 ClearDisplacement();
70 } 65 }
71 66
67 // Clears any center-of-mass displacement introduced by linksets, etc.
68 // Does not clear the displacement set by the user.
72 public void ClearDisplacement() 69 public void ClearDisplacement()
73 { 70 {
74 PositionDisplacement = OMV.Vector3.Zero; 71 if (UserSetCenterOfMassDisplacement.HasValue)
75 OrientationDisplacement = OMV.Quaternion.Identity; 72 PositionDisplacement = (OMV.Vector3)UserSetCenterOfMassDisplacement;
73 else
74 PositionDisplacement = OMV.Vector3.Zero;
76 } 75 }
77 76
78 // Set this sets and computes the displacement from the passed prim to the center-of-mass. 77 // Set this sets and computes the displacement from the passed prim to the center-of-mass.
79 // A user set value for center-of-mass overrides whatever might be passed in here. 78 // A user set value for center-of-mass overrides whatever might be passed in here.
80 // The displacement is in local coordinates (relative to root prim in linkset oriented coordinates). 79 // The displacement is in local coordinates (relative to root prim in linkset oriented coordinates).
81 public virtual void SetEffectiveCenterOfMassW(Vector3 centerOfMassDisplacement) 80 // Returns the relative offset from the root position to the center-of-mass.
81 // Called at taint time.
82 public virtual Vector3 SetEffectiveCenterOfMassDisplacement(Vector3 centerOfMassDisplacement)
82 { 83 {
84 PhysScene.AssertInTaintTime("BSPrimDisplaced.SetEffectiveCenterOfMassDisplacement");
83 Vector3 comDisp; 85 Vector3 comDisp;
84 if (UserSetCenterOfMass.HasValue) 86 if (UserSetCenterOfMassDisplacement.HasValue)
85 comDisp = (OMV.Vector3)UserSetCenterOfMass; 87 comDisp = (OMV.Vector3)UserSetCenterOfMassDisplacement;
86 else 88 else
87 comDisp = centerOfMassDisplacement; 89 comDisp = centerOfMassDisplacement;
88 90
89 if (comDisp == Vector3.Zero) 91 // Eliminate any jitter caused be very slight differences in masses and positions
90 { 92 if (comDisp.ApproxEquals(Vector3.Zero, 0.01f) )
91 // If there is no diplacement. Things get reset. 93 comDisp = Vector3.Zero;
92 PositionDisplacement = OMV.Vector3.Zero; 94
93 OrientationDisplacement = OMV.Quaternion.Identity; 95 DetailLog("{0},BSPrimDisplaced.SetEffectiveCenterOfMassDisplacement,userSet={1},comDisp={2}",
94 } 96 LocalID, UserSetCenterOfMassDisplacement.HasValue, comDisp);
95 else 97 if ( !comDisp.ApproxEquals(PositionDisplacement, 0.01f) )
96 { 98 {
97 // Remember the displacement from root as well as the origional rotation of the 99 // Displacement setting is changing.
98 // new center-of-mass. 100 // The relationship between the physical object and simulated object must be aligned.
99 PositionDisplacement = comDisp; 101 PositionDisplacement = comDisp;
100 OrientationDisplacement = OMV.Quaternion.Identity; 102 this.ForcePosition = RawPosition;
101 } 103 }
104
105 return PositionDisplacement;
102 } 106 }
103 107
108 // 'ForcePosition' is the one way to set the physical position of the body in the physics engine.
109 // Displace the simulator idea of position (center of root prim) to the physical position.
104 public override Vector3 ForcePosition 110 public override Vector3 ForcePosition
105 { 111 {
106 get { return base.ForcePosition; } 112 get {
113 OMV.Vector3 physPosition = PhysScene.PE.GetPosition(PhysBody);
114 if (PositionDisplacement != OMV.Vector3.Zero)
115 {
116 // If there is some displacement, return the physical position (center-of-mass)
117 // location minus the displacement to give the center of the root prim.
118 OMV.Vector3 displacement = PositionDisplacement * ForceOrientation;
119 DetailLog("{0},BSPrimDisplaced.ForcePosition,get,physPos={1},disp={2},simPos={3}",
120 LocalID, physPosition, displacement, physPosition - displacement);
121 physPosition -= displacement;
122 }
123 RawPosition = physPosition;
124 return physPosition;
125 }
107 set 126 set
108 { 127 {
109 if (PositionDisplacement != OMV.Vector3.Zero) 128 if (PositionDisplacement != OMV.Vector3.Zero)
110 base.ForcePosition = value - (PositionDisplacement * RawOrientation); 129 {
130 // This value is the simulator's idea of where the prim is: the center of the root prim
131 RawPosition = value;
132
133 // Move the passed root prim postion to the center-of-mass position and set in the physics engine.
134 OMV.Vector3 displacement = PositionDisplacement * RawOrientation;
135 OMV.Vector3 displacedPos = RawPosition + displacement;
136 DetailLog("{0},BSPrimDisplaced.ForcePosition,set,simPos={1},disp={2},physPos={3}",
137 LocalID, RawPosition, displacement, displacedPos);
138 if (PhysBody.HasPhysicalBody)
139 {
140 PhysScene.PE.SetTranslation(PhysBody, displacedPos, RawOrientation);
141 ActivateIfPhysical(false);
142 }
143 }
111 else 144 else
145 {
112 base.ForcePosition = value; 146 base.ForcePosition = value;
147 }
113 } 148 }
114 } 149 }
115 150
116 public override Quaternion ForceOrientation 151 // These are also overridden by BSPrimLinkable if the prim can be part of a linkset
117 {
118 get { return base.ForceOrientation; }
119 set
120 {
121 base.ForceOrientation = value;
122 }
123 }
124
125 // TODO: decide if this is the right place for these variables.
126 // Somehow incorporate the optional settability by the user.
127 // Is this used?
128 public override OMV.Vector3 CenterOfMass 152 public override OMV.Vector3 CenterOfMass
129 { 153 {
130 get { return RawPosition; } 154 get { return RawPosition; }
131 } 155 }
132 156
133 // Is this used?
134 public override OMV.Vector3 GeometricCenter 157 public override OMV.Vector3 GeometricCenter
135 { 158 {
136 get { return RawPosition; } 159 get { return RawPosition; }
@@ -139,12 +162,18 @@ public class BSPrimDisplaced : BSPrim
139 public override void UpdateProperties(EntityProperties entprop) 162 public override void UpdateProperties(EntityProperties entprop)
140 { 163 {
141 // Undo any center-of-mass displacement that might have been done. 164 // Undo any center-of-mass displacement that might have been done.
142 if (PositionDisplacement != OMV.Vector3.Zero || OrientationDisplacement != OMV.Quaternion.Identity) 165 if (PositionDisplacement != OMV.Vector3.Zero)
143 { 166 {
144 // Correct for any rotation around the center-of-mass 167 // The origional shape was offset from 'zero' by PositionDisplacement.
145 // TODO!!! 168 // These physical location must be back converted to be centered around the displaced
146 entprop.Position = entprop.Position + (PositionDisplacement * entprop.Rotation); 169 // root shape.
147 // entprop.Rotation = something; 170
171 // Move the returned center-of-mass location to the root prim location.
172 OMV.Vector3 displacement = PositionDisplacement * entprop.Rotation;
173 OMV.Vector3 displacedPos = entprop.Position - displacement;
174 DetailLog("{0},BSPrimDisplaced.UpdateProperties,physPos={1},disp={2},simPos={3}",
175 LocalID, entprop.Position, displacement, displacedPos);
176 entprop.Position = displacedPos;
148 } 177 }
149 178
150 base.UpdateProperties(entprop); 179 base.UpdateProperties(entprop);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
index d65d407..126b146 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
@@ -30,6 +30,7 @@ using System.Linq;
30using System.Text; 30using System.Text;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.OptionalModules.Scripting;
33 34
34using OMV = OpenMetaverse; 35using OMV = OpenMetaverse;
35 36
@@ -37,44 +38,49 @@ namespace OpenSim.Region.Physics.BulletSPlugin
37{ 38{
38public class BSPrimLinkable : BSPrimDisplaced 39public class BSPrimLinkable : BSPrimDisplaced
39{ 40{
41 // The purpose of this subclass is to add linkset functionality to the prim. This overrides
42 // operations necessary for keeping the linkset created and, additionally, this
43 // calls the linkset implementation for its creation and management.
44
45 private static readonly string LogHeader = "[BULLETS PRIMLINKABLE]";
46
47 // This adds the overrides for link() and delink() so the prim is linkable.
48
40 public BSLinkset Linkset { get; set; } 49 public BSLinkset Linkset { get; set; }
41 // The index of this child prim. 50 // The index of this child prim.
42 public int LinksetChildIndex { get; set; } 51 public int LinksetChildIndex { get; set; }
43 52
44 public BSLinksetInfo LinksetInfo { get; set; } 53 public BSLinkset.LinksetImplementation LinksetType { get; set; }
45 54
46 public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, 55 public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
47 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 56 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
48 : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical) 57 : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical)
49 { 58 {
50 Linkset = BSLinkset.Factory(PhysicsScene, this); 59 // Default linkset implementation for this prim
60 LinksetType = (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation;
51 61
52 PhysicsScene.TaintedObject("BSPrimLinksetCompound.Refresh", delegate() 62 Linkset = BSLinkset.Factory(PhysScene, this);
53 { 63
54 Linkset.Refresh(this); 64 Linkset.Refresh(this);
55 });
56 } 65 }
57 66
58 public override void Destroy() 67 public override void Destroy()
59 { 68 {
60 Linkset = Linkset.RemoveMeFromLinkset(this); 69 Linkset = Linkset.RemoveMeFromLinkset(this, false /* inTaintTime */);
61 base.Destroy(); 70 base.Destroy();
62 } 71 }
63 72
64 public override BSPhysicsShapeType PreferredPhysicalShape
65 { get { return Linkset.PreferredPhysicalShape(this); } }
66
67 public override void link(Manager.PhysicsActor obj) 73 public override void link(Manager.PhysicsActor obj)
68 { 74 {
69 BSPrimLinkable parent = obj as BSPrimLinkable; 75 BSPrimLinkable parent = obj as BSPrimLinkable;
70 if (parent != null) 76 if (parent != null)
71 { 77 {
72 BSPhysObject parentBefore = Linkset.LinksetRoot; 78 BSPhysObject parentBefore = Linkset.LinksetRoot; // DEBUG
73 int childrenBefore = Linkset.NumberOfChildren; 79 int childrenBefore = Linkset.NumberOfChildren; // DEBUG
74 80
75 Linkset = parent.Linkset.AddMeToLinkset(this); 81 Linkset = parent.Linkset.AddMeToLinkset(this);
76 82
77 DetailLog("{0},BSPrimLinkset.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", 83 DetailLog("{0},BSPrimLinkable.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
78 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); 84 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
79 } 85 }
80 return; 86 return;
@@ -85,12 +91,12 @@ public class BSPrimLinkable : BSPrimDisplaced
85 // TODO: decide if this parent checking needs to happen at taint time 91 // TODO: decide if this parent checking needs to happen at taint time
86 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 92 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
87 93
88 BSPhysObject parentBefore = Linkset.LinksetRoot; 94 BSPhysObject parentBefore = Linkset.LinksetRoot; // DEBUG
89 int childrenBefore = Linkset.NumberOfChildren; 95 int childrenBefore = Linkset.NumberOfChildren; // DEBUG
90 96
91 Linkset = Linkset.RemoveMeFromLinkset(this); 97 Linkset = Linkset.RemoveMeFromLinkset(this, false /* inTaintTime*/);
92 98
93 DetailLog("{0},BSPrimLinkset.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", 99 DetailLog("{0},BSPrimLinkable.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
94 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); 100 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
95 return; 101 return;
96 } 102 }
@@ -102,7 +108,7 @@ public class BSPrimLinkable : BSPrimDisplaced
102 set 108 set
103 { 109 {
104 base.Position = value; 110 base.Position = value;
105 PhysicsScene.TaintedObject("BSPrimLinkset.setPosition", delegate() 111 PhysScene.TaintedObject(LocalID, "BSPrimLinkable.setPosition", delegate()
106 { 112 {
107 Linkset.UpdateProperties(UpdatedProperties.Position, this); 113 Linkset.UpdateProperties(UpdatedProperties.Position, this);
108 }); 114 });
@@ -116,7 +122,7 @@ public class BSPrimLinkable : BSPrimDisplaced
116 set 122 set
117 { 123 {
118 base.Orientation = value; 124 base.Orientation = value;
119 PhysicsScene.TaintedObject("BSPrimLinkset.setOrientation", delegate() 125 PhysScene.TaintedObject(LocalID, "BSPrimLinkable.setOrientation", delegate()
120 { 126 {
121 Linkset.UpdateProperties(UpdatedProperties.Orientation, this); 127 Linkset.UpdateProperties(UpdatedProperties.Orientation, this);
122 }); 128 });
@@ -128,6 +134,17 @@ public class BSPrimLinkable : BSPrimDisplaced
128 get { return Linkset.LinksetMass; } 134 get { return Linkset.LinksetMass; }
129 } 135 }
130 136
137 public override OMV.Vector3 CenterOfMass
138 {
139 get { return Linkset.CenterOfMass; }
140 }
141
142 public override OMV.Vector3 GeometricCenter
143 {
144 get { return Linkset.GeometricCenter; }
145 }
146
147 // Refresh the linkset structure and parameters when the prim's physical parameters are changed.
131 public override void UpdatePhysicalParameters() 148 public override void UpdatePhysicalParameters()
132 { 149 {
133 base.UpdatePhysicalParameters(); 150 base.UpdatePhysicalParameters();
@@ -139,44 +156,193 @@ public class BSPrimLinkable : BSPrimDisplaced
139 Linkset.Refresh(this); 156 Linkset.Refresh(this);
140 } 157 }
141 158
159 // When the prim is made dynamic or static, the linkset needs to change.
142 protected override void MakeDynamic(bool makeStatic) 160 protected override void MakeDynamic(bool makeStatic)
143 { 161 {
144 base.MakeDynamic(makeStatic); 162 base.MakeDynamic(makeStatic);
145 if (makeStatic) 163 if (Linkset != null) // null can happen during initialization
146 Linkset.MakeStatic(this); 164 {
147 else 165 if (makeStatic)
148 Linkset.MakeDynamic(this); 166 Linkset.MakeStatic(this);
167 else
168 Linkset.MakeDynamic(this);
169 }
149 } 170 }
150 171
151 // Body is being taken apart. Remove physical dependencies and schedule a rebuild. 172 // Body is being taken apart. Remove physical dependencies and schedule a rebuild.
152 protected override void RemoveBodyDependencies() 173 protected override void RemoveDependencies()
153 { 174 {
154 Linkset.RemoveBodyDependencies(this); 175 Linkset.RemoveDependencies(this);
155 base.RemoveBodyDependencies(); 176 base.RemoveDependencies();
156 } 177 }
157 178
179 // Called after a simulation step for the changes in physical object properties.
180 // Do any filtering/modification needed for linksets.
158 public override void UpdateProperties(EntityProperties entprop) 181 public override void UpdateProperties(EntityProperties entprop)
159 { 182 {
160 if (Linkset.IsRoot(this)) 183 if (Linkset.IsRoot(this) || Linkset.ShouldReportPropertyUpdates(this))
161 { 184 {
162 // Properties are only updated for the roots of a linkset. 185 // Properties are only updated for the roots of a linkset.
163 // TODO: this will have to change when linksets are articulated. 186 // TODO: this will have to change when linksets are articulated.
164 base.UpdateProperties(entprop); 187 base.UpdateProperties(entprop);
165 } 188 }
189 /*
190 else
191 {
192 // For debugging, report the movement of children
193 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
194 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
195 entprop.Acceleration, entprop.RotationalVelocity);
196 }
197 */
166 // The linkset might like to know about changing locations 198 // The linkset might like to know about changing locations
167 Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this); 199 Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
168 } 200 }
169 201
202 // Called after a simulation step to post a collision with this object.
203 // This returns 'true' if the collision has been queued and the SendCollisions call must
204 // be made at the end of the simulation step.
170 public override bool Collide(uint collidingWith, BSPhysObject collidee, 205 public override bool Collide(uint collidingWith, BSPhysObject collidee,
171 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 206 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
172 { 207 {
173 // prims in the same linkset cannot collide with each other 208 bool ret = false;
174 BSPrimLinkable convCollidee = collidee as BSPrimLinkable; 209 // Ask the linkset if it wants to handle the collision
175 if (convCollidee != null && (this.Linkset.LinksetID == convCollidee.Linkset.LinksetID)) 210 if (!Linkset.HandleCollide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth))
211 {
212 // The linkset didn't handle it so pass the collision through normal processing
213 ret = base.Collide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth);
214 }
215 return ret;
216 }
217
218 // A linkset reports any collision on any part of the linkset.
219 public long SomeCollisionSimulationStep = 0;
220 public override bool HasSomeCollision
221 {
222 get
223 {
224 return (SomeCollisionSimulationStep == PhysScene.SimulationStep) || base.IsColliding;
225 }
226 set
176 { 227 {
177 return false; 228 if (value)
229 SomeCollisionSimulationStep = PhysScene.SimulationStep;
230 else
231 SomeCollisionSimulationStep = 0;
232
233 base.HasSomeCollision = value;
234 }
235 }
236
237 // Convert the existing linkset of this prim into a new type.
238 public bool ConvertLinkset(BSLinkset.LinksetImplementation newType)
239 {
240 bool ret = false;
241 if (LinksetType != newType)
242 {
243 DetailLog("{0},BSPrimLinkable.ConvertLinkset,oldT={1},newT={2}", LocalID, LinksetType, newType);
244
245 // Set the implementation type first so the call to BSLinkset.Factory gets the new type.
246 this.LinksetType = newType;
247
248 BSLinkset oldLinkset = this.Linkset;
249 BSLinkset newLinkset = BSLinkset.Factory(PhysScene, this);
250
251 this.Linkset = newLinkset;
252
253 // Pick up any physical dependencies this linkset might have in the physics engine.
254 oldLinkset.RemoveDependencies(this);
255
256 // Create a list of the children (mainly because can't interate through a list that's changing)
257 List<BSPrimLinkable> children = new List<BSPrimLinkable>();
258 oldLinkset.ForEachMember((child) =>
259 {
260 if (!oldLinkset.IsRoot(child))
261 children.Add(child);
262 return false; // 'false' says to continue to next member
263 });
264
265 // Remove the children from the old linkset and add to the new (will be a new instance from the factory)
266 foreach (BSPrimLinkable child in children)
267 {
268 oldLinkset.RemoveMeFromLinkset(child, true /*inTaintTime*/);
269 }
270 foreach (BSPrimLinkable child in children)
271 {
272 newLinkset.AddMeToLinkset(child);
273 child.Linkset = newLinkset;
274 }
275
276 // Force the shape and linkset to get reconstructed
277 newLinkset.Refresh(this);
278 this.ForceBodyShapeRebuild(true /* inTaintTime */);
279 }
280 return ret;
281 }
282
283 #region Extension
284 public override object Extension(string pFunct, params object[] pParams)
285 {
286 DetailLog("{0} BSPrimLinkable.Extension,op={1},nParam={2}", LocalID, pFunct, pParams.Length);
287 object ret = null;
288 switch (pFunct)
289 {
290 // physGetLinksetType();
291 // pParams = [ BSPhysObject root, null ]
292 case ExtendedPhysics.PhysFunctGetLinksetType:
293 {
294 ret = (object)LinksetType;
295 DetailLog("{0},BSPrimLinkable.Extension.physGetLinksetType,type={1}", LocalID, ret);
296 break;
297 }
298 // physSetLinksetType(type);
299 // pParams = [ BSPhysObject root, null, integer type ]
300 case ExtendedPhysics.PhysFunctSetLinksetType:
301 {
302 if (pParams.Length > 2)
303 {
304 BSLinkset.LinksetImplementation linksetType = (BSLinkset.LinksetImplementation)pParams[2];
305 if (Linkset.IsRoot(this))
306 {
307 PhysScene.TaintedObject(LocalID, "BSPrim.PhysFunctSetLinksetType", delegate()
308 {
309 // Cause the linkset type to change
310 DetailLog("{0},BSPrimLinkable.Extension.physSetLinksetType, oldType={1},newType={2}",
311 LocalID, Linkset.LinksetImpl, linksetType);
312 ConvertLinkset(linksetType);
313 });
314 }
315 ret = (object)(int)linksetType;
316 }
317 break;
318 }
319 // physChangeLinkType(linknum, typeCode);
320 // pParams = [ BSPhysObject root, BSPhysObject child, integer linkType ]
321 case ExtendedPhysics.PhysFunctChangeLinkType:
322 {
323 ret = Linkset.Extension(pFunct, pParams);
324 break;
325 }
326 // physGetLinkType(linknum);
327 // pParams = [ BSPhysObject root, BSPhysObject child ]
328 case ExtendedPhysics.PhysFunctGetLinkType:
329 {
330 ret = Linkset.Extension(pFunct, pParams);
331 break;
332 }
333 // physChangeLinkParams(linknum, [code, value, code, value, ...]);
334 // pParams = [ BSPhysObject root, BSPhysObject child, object[] [ string op, object opParam, string op, object opParam, ... ] ]
335 case ExtendedPhysics.PhysFunctChangeLinkParams:
336 {
337 ret = Linkset.Extension(pFunct, pParams);
338 break;
339 }
340 default:
341 ret = base.Extension(pFunct, pParams);
342 break;
178 } 343 }
179 return base.Collide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth); 344 return ret;
180 } 345 }
346 #endregion // Extension
181} 347}
182} 348}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 9818b05..b3dfa41 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -56,12 +56,23 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
56 public string BulletEngineName { get; private set; } 56 public string BulletEngineName { get; private set; }
57 public BSAPITemplate PE; 57 public BSAPITemplate PE;
58 58
59 // If the physics engine is running on a separate thread
60 public Thread m_physicsThread;
61
59 public Dictionary<uint, BSPhysObject> PhysObjects; 62 public Dictionary<uint, BSPhysObject> PhysObjects;
60 public BSShapeCollection Shapes; 63 public BSShapeCollection Shapes;
61 64
62 // Keeping track of the objects with collisions so we can report begin and end of a collision 65 // Keeping track of the objects with collisions so we can report begin and end of a collision
63 public HashSet<BSPhysObject> ObjectsWithCollisions = new HashSet<BSPhysObject>(); 66 public HashSet<BSPhysObject> ObjectsWithCollisions = new HashSet<BSPhysObject>();
64 public HashSet<BSPhysObject> ObjectsWithNoMoreCollisions = new HashSet<BSPhysObject>(); 67 public HashSet<BSPhysObject> ObjectsWithNoMoreCollisions = new HashSet<BSPhysObject>();
68
69 // All the collision processing is protected with this lock object
70 public Object CollisionLock = new Object();
71
72 // Properties are updated here
73 public Object UpdateLock = new Object();
74 public HashSet<BSPhysObject> ObjectsWithUpdates = new HashSet<BSPhysObject>();
75
65 // Keep track of all the avatars so we can send them a collision event 76 // Keep track of all the avatars so we can send them a collision event
66 // every tick so OpenSim will update its animation. 77 // every tick so OpenSim will update its animation.
67 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>(); 78 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>();
@@ -77,12 +88,22 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
77 public BSConstraintCollection Constraints { get; private set; } 88 public BSConstraintCollection Constraints { get; private set; }
78 89
79 // Simulation parameters 90 // Simulation parameters
91 internal float m_physicsStepTime; // if running independently, the interval simulated by default
92
80 internal int m_maxSubSteps; 93 internal int m_maxSubSteps;
81 internal float m_fixedTimeStep; 94 internal float m_fixedTimeStep;
82 internal long m_simulationStep = 0; 95
83 internal float NominalFrameRate { get; set; } 96 internal float m_simulatedTime; // the time simulated previously. Used for physics framerate calc.
97
98 internal long m_simulationStep = 0; // The current simulation step.
84 public long SimulationStep { get { return m_simulationStep; } } 99 public long SimulationStep { get { return m_simulationStep; } }
85 internal float LastTimeStep { get; private set; } 100 // A number to use for SimulationStep that is probably not any step value
101 // Used by the collision code (which remembers the step when a collision happens) to remember not any simulation step.
102 public static long NotASimulationStep = -1234;
103
104 internal float LastTimeStep { get; private set; } // The simulation time from the last invocation of Simulate()
105
106 internal float NominalFrameRate { get; set; } // Parameterized ideal frame rate that simulation is scaled to
86 107
87 // Physical objects can register for prestep or poststep events 108 // Physical objects can register for prestep or poststep events
88 public delegate void PreStepAction(float timeStep); 109 public delegate void PreStepAction(float timeStep);
@@ -90,7 +111,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
90 public event PreStepAction BeforeStep; 111 public event PreStepAction BeforeStep;
91 public event PostStepAction AfterStep; 112 public event PostStepAction AfterStep;
92 113
93 // A value of the time now so all the collision and update routines do not have to get their own 114 // A value of the time 'now' so all the collision and update routines do not have to get their own
94 // Set to 'now' just before all the prims and actors are called for collisions and updates 115 // Set to 'now' just before all the prims and actors are called for collisions and updates
95 public int SimulationNowTime { get; private set; } 116 public int SimulationNowTime { get; private set; }
96 117
@@ -136,12 +157,20 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
136 public delegate void TaintCallback(); 157 public delegate void TaintCallback();
137 private struct TaintCallbackEntry 158 private struct TaintCallbackEntry
138 { 159 {
160 public String originator;
139 public String ident; 161 public String ident;
140 public TaintCallback callback; 162 public TaintCallback callback;
141 public TaintCallbackEntry(string i, TaintCallback c) 163 public TaintCallbackEntry(string pIdent, TaintCallback pCallBack)
164 {
165 originator = BSScene.DetailLogZero;
166 ident = pIdent;
167 callback = pCallBack;
168 }
169 public TaintCallbackEntry(string pOrigin, string pIdent, TaintCallback pCallBack)
142 { 170 {
143 ident = i; 171 originator = pOrigin;
144 callback = c; 172 ident = pIdent;
173 callback = pCallBack;
145 } 174 }
146 } 175 }
147 private Object _taintLock = new Object(); // lock for using the next object 176 private Object _taintLock = new Object(); // lock for using the next object
@@ -188,6 +217,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
188 PhysObjects = new Dictionary<uint, BSPhysObject>(); 217 PhysObjects = new Dictionary<uint, BSPhysObject>();
189 Shapes = new BSShapeCollection(this); 218 Shapes = new BSShapeCollection(this);
190 219
220 m_simulatedTime = 0f;
221 LastTimeStep = 0.1f;
222
191 // Allocate pinned memory to pass parameters. 223 // Allocate pinned memory to pass parameters.
192 UnmanagedParams = new ConfigurationParameters[1]; 224 UnmanagedParams = new ConfigurationParameters[1];
193 225
@@ -202,8 +234,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
202 // can be left in and every call doesn't have to check for null. 234 // can be left in and every call doesn't have to check for null.
203 if (m_physicsLoggingEnabled) 235 if (m_physicsLoggingEnabled)
204 { 236 {
205 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); 237 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes, m_physicsLoggingDoFlush);
206 PhysicsLogging.ErrorLogger = m_log; // for DEBUG. Let's the logger output error messages. 238 PhysicsLogging.ErrorLogger = m_log; // for DEBUG. Let's the logger output its own error messages.
207 } 239 }
208 else 240 else
209 { 241 {
@@ -227,10 +259,20 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
227 TerrainManager = new BSTerrainManager(this); 259 TerrainManager = new BSTerrainManager(this);
228 TerrainManager.CreateInitialGroundPlaneAndTerrain(); 260 TerrainManager.CreateInitialGroundPlaneAndTerrain();
229 261
230 m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation); 262 // Put some informational messages into the log file.
263 m_log.InfoFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)BSParam.LinksetImplementation);
231 264
232 InTaintTime = false; 265 InTaintTime = false;
233 m_initialized = true; 266 m_initialized = true;
267
268 // If the physics engine runs on its own thread, start same.
269 if (BSParam.UseSeparatePhysicsThread)
270 {
271 // The physics simulation should happen independently of the heartbeat loop
272 m_physicsThread = new Thread(BulletSPluginPhysicsThread);
273 m_physicsThread.Name = BulletEngineName;
274 m_physicsThread.Start();
275 }
234 } 276 }
235 277
236 // All default parameter values are set here. There should be no values set in the 278 // All default parameter values are set here. There should be no values set in the
@@ -268,6 +310,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
268 // Do any replacements in the parameters 310 // Do any replacements in the parameters
269 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); 311 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
270 } 312 }
313 else
314 {
315 // Nothing in the configuration INI file so assume unmanaged and other defaults.
316 BulletEngineName = "BulletUnmanaged";
317 m_physicsLoggingEnabled = false;
318 VehicleLoggingEnabled = false;
319 }
271 320
272 // The material characteristics. 321 // The material characteristics.
273 BSMaterials.InitializeFromDefaults(Params); 322 BSMaterials.InitializeFromDefaults(Params);
@@ -311,11 +360,22 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
311 360
312 switch (selectionName) 361 switch (selectionName)
313 { 362 {
363 case "bullet":
314 case "bulletunmanaged": 364 case "bulletunmanaged":
315 ret = new BSAPIUnman(engineName, this); 365 ret = new BSAPIUnman(engineName, this);
316 break; 366 break;
317 case "bulletxna": 367 case "bulletxna":
318 ret = new BSAPIXNA(engineName, this); 368 ret = new BSAPIXNA(engineName, this);
369 // Disable some features that are not implemented in BulletXNA
370 m_log.InfoFormat("{0} Disabling some physics features not implemented by BulletXNA", LogHeader);
371 m_log.InfoFormat("{0} Disabling ShouldUseBulletHACD", LogHeader);
372 BSParam.ShouldUseBulletHACD = false;
373 m_log.InfoFormat("{0} Disabling ShouldUseSingleConvexHullForPrims", LogHeader);
374 BSParam.ShouldUseSingleConvexHullForPrims = false;
375 m_log.InfoFormat("{0} Disabling ShouldUseGImpactShapeForPrims", LogHeader);
376 BSParam.ShouldUseGImpactShapeForPrims = false;
377 m_log.InfoFormat("{0} Setting terrain implimentation to Heightmap", LogHeader);
378 BSParam.TerrainImplementation = (float)BSTerrainPhys.TerrainImplementation.Heightmap;
319 break; 379 break;
320 } 380 }
321 381
@@ -325,7 +385,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
325 } 385 }
326 else 386 else
327 { 387 {
328 m_log.WarnFormat("{0} Selected bullet engine {1} -> {2}/{3}", LogHeader, engineName, ret.BulletEngineName, ret.BulletEngineVersion); 388 m_log.InfoFormat("{0} Selected bullet engine {1} -> {2}/{3}", LogHeader, engineName, ret.BulletEngineName, ret.BulletEngineVersion);
329 } 389 }
330 390
331 return ret; 391 return ret;
@@ -478,25 +538,41 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
478 #endregion // Prim and Avatar addition and removal 538 #endregion // Prim and Avatar addition and removal
479 539
480 #region Simulation 540 #region Simulation
481 // Simulate one timestep 541
542 // Call from the simulator to send physics information to the simulator objects.
543 // This pushes all the collision and property update events into the objects in
544 // the simulator and, since it is on the heartbeat thread, there is an implicit
545 // locking of those data structures from other heartbeat events.
546 // If the physics engine is running on a separate thread, the update information
547 // will be in the ObjectsWithCollions and ObjectsWithUpdates structures.
482 public override float Simulate(float timeStep) 548 public override float Simulate(float timeStep)
483 { 549 {
550 if (!BSParam.UseSeparatePhysicsThread)
551 {
552 DoPhysicsStep(timeStep);
553 }
554 return SendUpdatesToSimulator(timeStep);
555 }
556
557 // Call the physics engine to do one 'timeStep' and collect collisions and updates
558 // into ObjectsWithCollisions and ObjectsWithUpdates data structures.
559 private void DoPhysicsStep(float timeStep)
560 {
484 // prevent simulation until we've been initialized 561 // prevent simulation until we've been initialized
485 if (!m_initialized) return 5.0f; 562 if (!m_initialized) return;
486 563
487 LastTimeStep = timeStep; 564 LastTimeStep = timeStep;
488 565
489 int updatedEntityCount = 0; 566 int updatedEntityCount = 0;
490 int collidersCount = 0; 567 int collidersCount = 0;
491 568
492 int beforeTime = 0; 569 int beforeTime = Util.EnvironmentTickCount();
493 int simTime = 0; 570 int simTime = 0;
494 571
495 // update the prim states while we know the physics engine is not busy
496 int numTaints = _taintOperations.Count; 572 int numTaints = _taintOperations.Count;
497
498 InTaintTime = true; // Only used for debugging so locking is not necessary. 573 InTaintTime = true; // Only used for debugging so locking is not necessary.
499 574
575 // update the prim states while we know the physics engine is not busy
500 ProcessTaints(); 576 ProcessTaints();
501 577
502 // Some of the physical objects requre individual, pre-step calls 578 // Some of the physical objects requre individual, pre-step calls
@@ -519,18 +595,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
519 int numSubSteps = 0; 595 int numSubSteps = 0;
520 try 596 try
521 { 597 {
522 if (PhysicsLogging.Enabled)
523 beforeTime = Util.EnvironmentTickCount();
524
525 numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount); 598 numSubSteps = PE.PhysicsStep(World, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out collidersCount);
526 599
527 if (PhysicsLogging.Enabled)
528 {
529 simTime = Util.EnvironmentTickCountSubtract(beforeTime);
530 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}",
531 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps,
532 updatedEntityCount, collidersCount, ObjectsWithCollisions.Count);
533 }
534 } 600 }
535 catch (Exception e) 601 catch (Exception e)
536 { 602 {
@@ -542,77 +608,63 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
542 collidersCount = 0; 608 collidersCount = 0;
543 } 609 }
544 610
611 // Make the physics engine dump useful statistics periodically
545 if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0)) 612 if (PhysicsMetricDumpFrames != 0 && ((m_simulationStep % PhysicsMetricDumpFrames) == 0))
546 PE.DumpPhysicsStatistics(World); 613 PE.DumpPhysicsStatistics(World);
547 614
548 // Get a value for 'now' so all the collision and update routines don't have to get their own. 615 // Get a value for 'now' so all the collision and update routines don't have to get their own.
549 SimulationNowTime = Util.EnvironmentTickCount(); 616 SimulationNowTime = Util.EnvironmentTickCount();
550 617
551 // If there were collisions, process them by sending the event to the prim. 618 // Send collision information to the colliding objects. The objects decide if the collision
552 // Collisions must be processed before updates. 619 // is 'real' (like linksets don't collide with themselves) and the individual objects
553 if (collidersCount > 0) 620 // know if the simulator has subscribed to collisions.
621 lock (CollisionLock)
554 { 622 {
555 for (int ii = 0; ii < collidersCount; ii++) 623 if (collidersCount > 0)
556 { 624 {
557 uint cA = m_collisionArray[ii].aID; 625 for (int ii = 0; ii < collidersCount; ii++)
558 uint cB = m_collisionArray[ii].bID;
559 Vector3 point = m_collisionArray[ii].point;
560 Vector3 normal = m_collisionArray[ii].normal;
561 float penetration = m_collisionArray[ii].penetration;
562 SendCollision(cA, cB, point, normal, penetration);
563 SendCollision(cB, cA, point, -normal, penetration);
564 }
565 }
566
567 // The above SendCollision's batch up the collisions on the objects.
568 // Now push the collisions into the simulator.
569 if (ObjectsWithCollisions.Count > 0)
570 {
571 foreach (BSPhysObject bsp in ObjectsWithCollisions)
572 if (!bsp.SendCollisions())
573 { 626 {
574 // If the object is done colliding, see that it's removed from the colliding list 627 uint cA = m_collisionArray[ii].aID;
575 ObjectsWithNoMoreCollisions.Add(bsp); 628 uint cB = m_collisionArray[ii].bID;
629 Vector3 point = m_collisionArray[ii].point;
630 Vector3 normal = m_collisionArray[ii].normal;
631 float penetration = m_collisionArray[ii].penetration;
632 SendCollision(cA, cB, point, normal, penetration);
633 SendCollision(cB, cA, point, -normal, penetration);
576 } 634 }
635 }
577 } 636 }
578 637
579 // This is a kludge to get avatar movement updates. 638 // If any of the objects had updated properties, tell the managed objects about the update
580 // The simulator expects collisions for avatars even if there are have been no collisions. 639 // and remember that there was a change so it will be passed to the simulator.
581 // The event updates avatar animations and stuff. 640 lock (UpdateLock)
582 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
583 foreach (BSPhysObject bsp in m_avatars)
584 if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice
585 bsp.SendCollisions();
586
587 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
588 // Not done above because it is inside an iteration of ObjectWithCollisions.
589 // This complex collision processing is required to create an empty collision
590 // event call after all real collisions have happened on an object. This enables
591 // the simulator to generate the 'collision end' event.
592 if (ObjectsWithNoMoreCollisions.Count > 0)
593 {
594 foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
595 ObjectsWithCollisions.Remove(po);
596 ObjectsWithNoMoreCollisions.Clear();
597 }
598 // Done with collisions.
599
600 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
601 if (updatedEntityCount > 0)
602 { 641 {
603 for (int ii = 0; ii < updatedEntityCount; ii++) 642 if (updatedEntityCount > 0)
604 { 643 {
605 EntityProperties entprop = m_updateArray[ii]; 644 for (int ii = 0; ii < updatedEntityCount; ii++)
606 BSPhysObject pobj;
607 if (PhysObjects.TryGetValue(entprop.ID, out pobj))
608 { 645 {
609 pobj.UpdateProperties(entprop); 646 EntityProperties entprop = m_updateArray[ii];
647 BSPhysObject pobj;
648 if (PhysObjects.TryGetValue(entprop.ID, out pobj))
649 {
650 if (pobj.IsInitialized)
651 pobj.UpdateProperties(entprop);
652 }
610 } 653 }
611 } 654 }
612 } 655 }
613 656
657 // Some actors want to know when the simulation step is complete.
614 TriggerPostStepEvent(timeStep); 658 TriggerPostStepEvent(timeStep);
615 659
660 simTime = Util.EnvironmentTickCountSubtract(beforeTime);
661 if (PhysicsLogging.Enabled)
662 {
663 DetailLog("{0},DoPhysicsStep,complete,frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}, objWColl={7}",
664 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps,
665 updatedEntityCount, collidersCount, ObjectsWithCollisions.Count);
666 }
667
616 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world. 668 // The following causes the unmanaged code to output ALL the values found in ALL the objects in the world.
617 // Only enable this in a limited test world with few objects. 669 // Only enable this in a limited test world with few objects.
618 if (m_physicsPhysicalDumpEnabled) 670 if (m_physicsPhysicalDumpEnabled)
@@ -621,7 +673,84 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
621 // The physics engine returns the number of milliseconds it simulated this call. 673 // The physics engine returns the number of milliseconds it simulated this call.
622 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. 674 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
623 // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55). 675 // Multiply by a fixed nominal frame rate to give a rate similar to the simulator (usually 55).
624 return (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate; 676 m_simulatedTime += (float)numSubSteps * m_fixedTimeStep * 1000f * NominalFrameRate;
677 }
678
679 // Called by a BSPhysObject to note that it has changed properties and this information
680 // should be passed up to the simulator at the proper time.
681 // Note: this is called by the BSPhysObject from invocation via DoPhysicsStep() above so
682 // this is is under UpdateLock.
683 public void PostUpdate(BSPhysObject updatee)
684 {
685 ObjectsWithUpdates.Add(updatee);
686 }
687
688 // The simulator thinks it is physics time so return all the collisions and position
689 // updates that were collected in actual physics simulation.
690 private float SendUpdatesToSimulator(float timeStep)
691 {
692 if (!m_initialized) return 5.0f;
693
694 DetailLog("{0},SendUpdatesToSimulator,collisions={1},updates={2},simedTime={3}",
695 BSScene.DetailLogZero, ObjectsWithCollisions.Count, ObjectsWithUpdates.Count, m_simulatedTime);
696 // Push the collisions into the simulator.
697 lock (CollisionLock)
698 {
699 if (ObjectsWithCollisions.Count > 0)
700 {
701 foreach (BSPhysObject bsp in ObjectsWithCollisions)
702 if (!bsp.SendCollisions())
703 {
704 // If the object is done colliding, see that it's removed from the colliding list
705 ObjectsWithNoMoreCollisions.Add(bsp);
706 }
707 }
708
709 // This is a kludge to get avatar movement updates.
710 // The simulator expects collisions for avatars even if there are have been no collisions.
711 // The event updates avatar animations and stuff.
712 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
713 foreach (BSPhysObject bsp in m_avatars)
714 if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice
715 bsp.SendCollisions();
716
717 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
718 // Not done above because it is inside an iteration of ObjectWithCollisions.
719 // This complex collision processing is required to create an empty collision
720 // event call after all real collisions have happened on an object. This allows
721 // the simulator to generate the 'collision end' event.
722 if (ObjectsWithNoMoreCollisions.Count > 0)
723 {
724 foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
725 ObjectsWithCollisions.Remove(po);
726 ObjectsWithNoMoreCollisions.Clear();
727 }
728 }
729
730 // Call the simulator for each object that has physics property updates.
731 HashSet<BSPhysObject> updatedObjects = null;
732 lock (UpdateLock)
733 {
734 if (ObjectsWithUpdates.Count > 0)
735 {
736 updatedObjects = ObjectsWithUpdates;
737 ObjectsWithUpdates = new HashSet<BSPhysObject>();
738 }
739 }
740 if (updatedObjects != null)
741 {
742 foreach (BSPhysObject obj in updatedObjects)
743 {
744 obj.RequestPhysicsterseUpdate();
745 }
746 updatedObjects.Clear();
747 }
748
749 // Return the framerate simulated to give the above returned results.
750 // (Race condition here but this is just bookkeeping so rare mistakes do not merit a lock).
751 float simTime = m_simulatedTime;
752 m_simulatedTime = 0f;
753 return simTime;
625 } 754 }
626 755
627 // Something has collided 756 // Something has collided
@@ -640,21 +769,49 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
640 return; 769 return;
641 } 770 }
642 771
643 // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called. 772 // Note: the terrain is not in the physical object list so 'collidee' can be null when Collide() is called.
644 BSPhysObject collidee = null; 773 BSPhysObject collidee = null;
645 PhysObjects.TryGetValue(collidingWith, out collidee); 774 PhysObjects.TryGetValue(collidingWith, out collidee);
646 775
647 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); 776 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
648 777
649 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) 778 if (collider.IsInitialized)
650 { 779 {
651 // If a collision was posted, remember to send it to the simulator 780 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
652 ObjectsWithCollisions.Add(collider); 781 {
782 // If a collision was 'good', remember to send it to the simulator
783 ObjectsWithCollisions.Add(collider);
784 }
653 } 785 }
654 786
655 return; 787 return;
656 } 788 }
657 789
790 public void BulletSPluginPhysicsThread()
791 {
792 while (m_initialized)
793 {
794 int beginSimulationRealtimeMS = Util.EnvironmentTickCount();
795 DoPhysicsStep(BSParam.PhysicsTimeStep);
796 int simulationRealtimeMS = Util.EnvironmentTickCountSubtract(beginSimulationRealtimeMS);
797 int simulationTimeVsRealtimeDifferenceMS = ((int)(BSParam.PhysicsTimeStep*1000f)) - simulationRealtimeMS;
798
799 if (simulationTimeVsRealtimeDifferenceMS > 0)
800 {
801 // The simulation of the time interval took less than realtime.
802 // Do a sleep for the rest of realtime.
803 Thread.Sleep(simulationTimeVsRealtimeDifferenceMS);
804 }
805 else
806 {
807 // The simulation took longer than realtime.
808 // Do some scaling of simulation time.
809 // TODO.
810 DetailLog("{0},BulletSPluginPhysicsThread,longerThanRealtime={1}", BSScene.DetailLogZero, simulationTimeVsRealtimeDifferenceMS);
811 }
812 }
813 }
814
658 #endregion // Simulation 815 #endregion // Simulation
659 816
660 public override void GetResults() { } 817 public override void GetResults() { }
@@ -717,6 +874,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
717 874
718 public override bool IsThreaded { get { return false; } } 875 public override bool IsThreaded { get { return false; } }
719 876
877 #region Extensions
878 public override object Extension(string pFunct, params object[] pParams)
879 {
880 DetailLog("{0} BSScene.Extension,op={1}", DetailLogZero, pFunct);
881 return base.Extension(pFunct, pParams);
882 }
883 #endregion // Extensions
884
720 #region Taints 885 #region Taints
721 // The simulation execution order is: 886 // The simulation execution order is:
722 // Simulate() 887 // Simulate()
@@ -731,26 +896,37 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
731 // Calls to the PhysicsActors can't directly call into the physics engine 896 // Calls to the PhysicsActors can't directly call into the physics engine
732 // because it might be busy. We delay changes to a known time. 897 // because it might be busy. We delay changes to a known time.
733 // We rely on C#'s closure to save and restore the context for the delegate. 898 // We rely on C#'s closure to save and restore the context for the delegate.
734 public void TaintedObject(String ident, TaintCallback callback) 899 public void TaintedObject(string pOriginator, string pIdent, TaintCallback pCallback)
735 { 900 {
736 if (!m_initialized) return; 901 TaintedObject(false /*inTaintTime*/, pOriginator, pIdent, pCallback);
737 902 }
738 lock (_taintLock) 903 public void TaintedObject(uint pOriginator, String pIdent, TaintCallback pCallback)
739 { 904 {
740 _taintOperations.Add(new TaintCallbackEntry(ident, callback)); 905 TaintedObject(false /*inTaintTime*/, m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback);
741 } 906 }
742 907 public void TaintedObject(bool inTaintTime, String pIdent, TaintCallback pCallback)
743 return; 908 {
909 TaintedObject(inTaintTime, BSScene.DetailLogZero, pIdent, pCallback);
910 }
911 public void TaintedObject(bool inTaintTime, uint pOriginator, String pIdent, TaintCallback pCallback)
912 {
913 TaintedObject(inTaintTime, m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback);
744 } 914 }
745
746 // Sometimes a potentially tainted operation can be used in and out of taint time. 915 // Sometimes a potentially tainted operation can be used in and out of taint time.
747 // This routine executes the command immediately if in taint-time otherwise it is queued. 916 // This routine executes the command immediately if in taint-time otherwise it is queued.
748 public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback) 917 public void TaintedObject(bool inTaintTime, string pOriginator, string pIdent, TaintCallback pCallback)
749 { 918 {
919 if (!m_initialized) return;
920
750 if (inTaintTime) 921 if (inTaintTime)
751 callback(); 922 pCallback();
752 else 923 else
753 TaintedObject(ident, callback); 924 {
925 lock (_taintLock)
926 {
927 _taintOperations.Add(new TaintCallbackEntry(pOriginator, pIdent, pCallback));
928 }
929 }
754 } 930 }
755 931
756 private void TriggerPreStepEvent(float timeStep) 932 private void TriggerPreStepEvent(float timeStep)
@@ -780,7 +956,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
780 956
781 private void ProcessRegularTaints() 957 private void ProcessRegularTaints()
782 { 958 {
783 if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process 959 if (m_initialized && _taintOperations.Count > 0) // save allocating new list if there is nothing to process
784 { 960 {
785 // swizzle a new list into the list location so we can process what's there 961 // swizzle a new list into the list location so we can process what's there
786 List<TaintCallbackEntry> oldList; 962 List<TaintCallbackEntry> oldList;
@@ -794,7 +970,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
794 { 970 {
795 try 971 try
796 { 972 {
797 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG 973 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", tcbe.originator, tcbe.ident); // DEBUG DEBUG DEBUG
798 tcbe.callback(); 974 tcbe.callback();
799 } 975 }
800 catch (Exception e) 976 catch (Exception e)
@@ -811,10 +987,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
811 // will replace any previous operation by the same object. 987 // will replace any previous operation by the same object.
812 public void PostTaintObject(String ident, uint ID, TaintCallback callback) 988 public void PostTaintObject(String ident, uint ID, TaintCallback callback)
813 { 989 {
814 string uniqueIdent = ident + "-" + ID.ToString(); 990 string IDAsString = ID.ToString();
991 string uniqueIdent = ident + "-" + IDAsString;
815 lock (_taintLock) 992 lock (_taintLock)
816 { 993 {
817 _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback); 994 _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(IDAsString, uniqueIdent, callback);
818 } 995 }
819 996
820 return; 997 return;
@@ -823,7 +1000,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
823 // Taints that happen after the normal taint processing but before the simulation step. 1000 // Taints that happen after the normal taint processing but before the simulation step.
824 private void ProcessPostTaintTaints() 1001 private void ProcessPostTaintTaints()
825 { 1002 {
826 if (_postTaintOperations.Count > 0) 1003 if (m_initialized && _postTaintOperations.Count > 0)
827 { 1004 {
828 Dictionary<string, TaintCallbackEntry> oldList; 1005 Dictionary<string, TaintCallbackEntry> oldList;
829 lock (_taintLock) 1006 lock (_taintLock)
@@ -924,7 +1101,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
924 string xval = val; 1101 string xval = val;
925 List<uint> xlIDs = lIDs; 1102 List<uint> xlIDs = lIDs;
926 string xparm = parm; 1103 string xparm = parm;
927 TaintedObject("BSScene.UpdateParameterSet", delegate() { 1104 TaintedObject(DetailLogZero, "BSScene.UpdateParameterSet", delegate() {
928 BSParam.ParameterDefnBase thisParam; 1105 BSParam.ParameterDefnBase thisParam;
929 if (BSParam.TryGetParameter(xparm, out thisParam)) 1106 if (BSParam.TryGetParameter(xparm, out thisParam))
930 { 1107 {
@@ -963,8 +1140,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
963 public void DetailLog(string msg, params Object[] args) 1140 public void DetailLog(string msg, params Object[] args)
964 { 1141 {
965 PhysicsLogging.Write(msg, args); 1142 PhysicsLogging.Write(msg, args);
966 // Add the Flush() if debugging crashes. Gets all the messages written out.
967 if (m_physicsLoggingDoFlush) PhysicsLogging.Flush();
968 } 1143 }
969 // Used to fill in the LocalID when there isn't one. It's the correct number of characters. 1144 // Used to fill in the LocalID when there isn't one. It's the correct number of characters.
970 public const string DetailLogZero = "0000000000"; 1145 public const string DetailLogZero = "0000000000";
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 220fbbc..32bbc8f 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -38,38 +38,15 @@ public sealed class BSShapeCollection : IDisposable
38{ 38{
39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; 39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
40 40
41 private BSScene PhysicsScene { get; set; } 41 private BSScene m_physicsScene { get; set; }
42 42
43 private Object m_collectionActivityLock = new Object(); 43 private Object m_collectionActivityLock = new Object();
44 44
45 // Description of a Mesh
46 private struct MeshDesc
47 {
48 public BulletShape shape;
49 public int referenceCount;
50 public DateTime lastReferenced;
51 public UInt64 shapeKey;
52 }
53
54 // Description of a hull.
55 // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations.
56 private struct HullDesc
57 {
58 public BulletShape shape;
59 public int referenceCount;
60 public DateTime lastReferenced;
61 public UInt64 shapeKey;
62 }
63
64 // The sharable set of meshes and hulls. Indexed by their shape hash.
65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
67
68 private bool DDetail = false; 45 private bool DDetail = false;
69 46
70 public BSShapeCollection(BSScene physScene) 47 public BSShapeCollection(BSScene physScene)
71 { 48 {
72 PhysicsScene = physScene; 49 m_physicsScene = physScene;
73 // Set the next to 'true' for very detailed shape update detailed logging (detailed details?) 50 // Set the next to 'true' for very detailed shape update detailed logging (detailed details?)
74 // While detailed debugging is still active, this is better than commenting out all the 51 // While detailed debugging is still active, this is better than commenting out all the
75 // DetailLog statements. When debugging slows down, this and the protected logging 52 // DetailLog statements. When debugging slows down, this and the protected logging
@@ -86,22 +63,18 @@ public sealed class BSShapeCollection : IDisposable
86 // Mostly used for changing bodies out from under Linksets. 63 // Mostly used for changing bodies out from under Linksets.
87 // Useful for other cases where parameters need saving. 64 // Useful for other cases where parameters need saving.
88 // Passing 'null' says no callback. 65 // Passing 'null' says no callback.
89 public delegate void ShapeDestructionCallback(BulletShape shape); 66 public delegate void PhysicalDestructionCallback(BulletBody pBody, BulletShape pShape);
90 public delegate void BodyDestructionCallback(BulletBody body);
91 67
92 // Called to update/change the body and shape for an object. 68 // Called to update/change the body and shape for an object.
93 // First checks the shape and updates that if necessary then makes 69 // The object has some shape and body on it. Here we decide if that is the correct shape
94 // sure the body is of the right type. 70 // for the current state of the object (static/dynamic/...).
71 // If bodyCallback is not null, it is called if either the body or the shape are changed
72 // so dependencies (like constraints) can be removed before the physical object is dereferenced.
95 // Return 'true' if either the body or the shape changed. 73 // Return 'true' if either the body or the shape changed.
96 // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before 74 // Called at taint-time.
97 // the current shape or body is destroyed. This allows the caller to remove any 75 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, PhysicalDestructionCallback bodyCallback)
98 // higher level dependencies on the shape or body. Mostly used for LinkSets to
99 // remove the physical constraints before the body is destroyed.
100 // Called at taint-time!!
101 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim,
102 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
103 { 76 {
104 PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); 77 m_physicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
105 78
106 bool ret = false; 79 bool ret = false;
107 80
@@ -111,12 +84,12 @@ public sealed class BSShapeCollection : IDisposable
111 // Do we have the correct geometry for this type of object? 84 // Do we have the correct geometry for this type of object?
112 // Updates prim.BSShape with information/pointers to shape. 85 // Updates prim.BSShape with information/pointers to shape.
113 // Returns 'true' of BSShape is changed to a new shape. 86 // Returns 'true' of BSShape is changed to a new shape.
114 bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); 87 bool newGeom = CreateGeom(forceRebuild, prim, bodyCallback);
115 // If we had to select a new shape geometry for the object, 88 // If we had to select a new shape geometry for the object,
116 // rebuild the body around it. 89 // rebuild the body around it.
117 // Updates prim.BSBody with information/pointers to requested body 90 // Updates prim.BSBody with information/pointers to requested body
118 // Returns 'true' if BSBody was changed. 91 // Returns 'true' if BSBody was changed.
119 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, bodyCallback); 92 bool newBody = CreateBody((newGeom || forceRebuild), prim, m_physicsScene.World, bodyCallback);
120 ret = newGeom || newBody; 93 ret = newGeom || newBody;
121 } 94 }
122 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", 95 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}",
@@ -127,274 +100,20 @@ public sealed class BSShapeCollection : IDisposable
127 100
128 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim) 101 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
129 { 102 {
130 return GetBodyAndShape(forceRebuild, sim, prim, null, null); 103 return GetBodyAndShape(forceRebuild, sim, prim, null);
131 }
132
133 // Track another user of a body.
134 // We presume the caller has allocated the body.
135 // Bodies only have one user so the body is just put into the world if not already there.
136 private void ReferenceBody(BulletBody body)
137 {
138 lock (m_collectionActivityLock)
139 {
140 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
141 if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
142 {
143 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body);
144 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
145 }
146 }
147 }
148
149 // Release the usage of a body.
150 // Called when releasing use of a BSBody. BSShape is handled separately.
151 // Called in taint time.
152 public void DereferenceBody(BulletBody body, BodyDestructionCallback bodyCallback )
153 {
154 if (!body.HasPhysicalBody)
155 return;
156
157 PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
158
159 lock (m_collectionActivityLock)
160 {
161 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body);
162 // If the caller needs to know the old body is going away, pass the event up.
163 if (bodyCallback != null) bodyCallback(body);
164
165 if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
166 {
167 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body);
168 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
169 }
170
171 // Zero any reference to the shape so it is not freed when the body is deleted.
172 PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null);
173 PhysicsScene.PE.DestroyObject(PhysicsScene.World, body);
174 }
175 }
176
177 // Track the datastructures and use count for a shape.
178 // When creating a hull, this is called first to reference the mesh
179 // and then again to reference the hull.
180 // Meshes and hulls for the same shape have the same hash key.
181 // NOTE that native shapes are not added to the mesh list or removed.
182 // Returns 'true' if this is the initial reference to the shape. Otherwise reused.
183 public bool ReferenceShape(BulletShape shape)
184 {
185 bool ret = false;
186 switch (shape.type)
187 {
188 case BSPhysicsShapeType.SHAPE_MESH:
189 MeshDesc meshDesc;
190 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
191 {
192 // There is an existing instance of this mesh.
193 meshDesc.referenceCount++;
194 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
195 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
196 }
197 else
198 {
199 // This is a new reference to a mesh
200 meshDesc.shape = shape.Clone();
201 meshDesc.shapeKey = shape.shapeKey;
202 // We keep a reference to the underlying IMesh data so a hull can be built
203 meshDesc.referenceCount = 1;
204 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
205 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
206 ret = true;
207 }
208 meshDesc.lastReferenced = System.DateTime.Now;
209 Meshes[shape.shapeKey] = meshDesc;
210 break;
211 case BSPhysicsShapeType.SHAPE_HULL:
212 HullDesc hullDesc;
213 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
214 {
215 // There is an existing instance of this hull.
216 hullDesc.referenceCount++;
217 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
218 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
219 }
220 else
221 {
222 // This is a new reference to a hull
223 hullDesc.shape = shape.Clone();
224 hullDesc.shapeKey = shape.shapeKey;
225 hullDesc.referenceCount = 1;
226 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
227 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
228 ret = true;
229
230 }
231 hullDesc.lastReferenced = System.DateTime.Now;
232 Hulls[shape.shapeKey] = hullDesc;
233 break;
234 case BSPhysicsShapeType.SHAPE_UNKNOWN:
235 break;
236 default:
237 // Native shapes are not tracked and they don't go into any list
238 break;
239 }
240 return ret;
241 } 104 }
242 105
243 // Release the usage of a shape. 106 // If the existing prim's shape is to be replaced, remove the tie to the existing shape
244 public void DereferenceShape(BulletShape shape, ShapeDestructionCallback shapeCallback) 107 // before replacing it.
108 private void DereferenceExistingShape(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
245 { 109 {
246 if (!shape.HasPhysicalShape) 110 if (prim.PhysShape.HasPhysicalShape)
247 return;
248
249 PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceShape");
250
251 if (shape.HasPhysicalShape)
252 {
253 if (shape.isNativeShape)
254 {
255 // Native shapes are not tracked and are released immediately
256 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1}",
257 BSScene.DetailLogZero, shape.AddrString);
258 if (shapeCallback != null) shapeCallback(shape);
259 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
260 }
261 else
262 {
263 switch (shape.type)
264 {
265 case BSPhysicsShapeType.SHAPE_HULL:
266 DereferenceHull(shape, shapeCallback);
267 break;
268 case BSPhysicsShapeType.SHAPE_MESH:
269 DereferenceMesh(shape, shapeCallback);
270 break;
271 case BSPhysicsShapeType.SHAPE_COMPOUND:
272 DereferenceCompound(shape, shapeCallback);
273 break;
274 case BSPhysicsShapeType.SHAPE_UNKNOWN:
275 break;
276 default:
277 break;
278 }
279 }
280 }
281 }
282
283 // Count down the reference count for a mesh shape
284 // Called at taint-time.
285 private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback)
286 {
287 MeshDesc meshDesc;
288 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
289 { 111 {
290 meshDesc.referenceCount--; 112 if (shapeCallback != null)
291 // TODO: release the Bullet storage 113 shapeCallback(prim.PhysBody, prim.PhysShape.physShapeInfo);
292 if (shapeCallback != null) shapeCallback(shape); 114 prim.PhysShape.Dereference(m_physicsScene);
293 meshDesc.lastReferenced = System.DateTime.Now;
294 Meshes[shape.shapeKey] = meshDesc;
295 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
296 BSScene.DetailLogZero, shape, meshDesc.referenceCount);
297
298 }
299 }
300
301 // Count down the reference count for a hull shape
302 // Called at taint-time.
303 private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback)
304 {
305 HullDesc hullDesc;
306 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
307 {
308 hullDesc.referenceCount--;
309 // TODO: release the Bullet storage (aging old entries?)
310
311 // Tell upper layers that, if they have dependencies on this shape, this link is going away
312 if (shapeCallback != null) shapeCallback(shape);
313
314 hullDesc.lastReferenced = System.DateTime.Now;
315 Hulls[shape.shapeKey] = hullDesc;
316 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
317 BSScene.DetailLogZero, shape, hullDesc.referenceCount);
318 }
319 }
320
321 // Remove a reference to a compound shape.
322 // Taking a compound shape apart is a little tricky because if you just delete the
323 // physical shape, it will free all the underlying children. We can't do that because
324 // they could be shared. So, this removes each of the children from the compound and
325 // dereferences them separately before destroying the compound collision object itself.
326 // Called at taint-time.
327 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback)
328 {
329 if (!PhysicsScene.PE.IsCompound(shape))
330 {
331 // Failed the sanity check!!
332 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
333 LogHeader, shape.type, shape.AddrString);
334 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
335 BSScene.DetailLogZero, shape.type, shape.AddrString);
336 return;
337 }
338
339 int numChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(shape);
340 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
341
342 for (int ii = numChildren - 1; ii >= 0; ii--)
343 {
344 BulletShape childShape = PhysicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(shape, ii);
345 DereferenceAnonCollisionShape(childShape);
346 }
347 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
348 }
349
350 // Sometimes we have a pointer to a collision shape but don't know what type it is.
351 // Figure out type and call the correct dereference routine.
352 // Called at taint-time.
353 private void DereferenceAnonCollisionShape(BulletShape shapeInfo)
354 {
355 MeshDesc meshDesc;
356 HullDesc hullDesc;
357
358 if (TryGetMeshByPtr(shapeInfo, out meshDesc))
359 {
360 shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH;
361 shapeInfo.shapeKey = meshDesc.shapeKey;
362 }
363 else
364 {
365 if (TryGetHullByPtr(shapeInfo, out hullDesc))
366 {
367 shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL;
368 shapeInfo.shapeKey = hullDesc.shapeKey;
369 }
370 else
371 {
372 if (PhysicsScene.PE.IsCompound(shapeInfo))
373 {
374 shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND;
375 }
376 else
377 {
378 if (PhysicsScene.PE.IsNativeShape(shapeInfo))
379 {
380 shapeInfo.isNativeShape = true;
381 shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
382 }
383 }
384 }
385 }
386
387 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
388
389 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
390 {
391 DereferenceShape(shapeInfo, null);
392 }
393 else
394 {
395 PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}",
396 LogHeader, PhysicsScene.RegionName, shapeInfo.AddrString);
397 } 115 }
116 prim.PhysShape = new BSShapeNull();
398 } 117 }
399 118
400 // Create the geometry information in Bullet for later use. 119 // Create the geometry information in Bullet for later use.
@@ -405,60 +124,41 @@ public sealed class BSShapeCollection : IDisposable
405 // Info in prim.BSShape is updated to the new shape. 124 // Info in prim.BSShape is updated to the new shape.
406 // Returns 'true' if the geometry was rebuilt. 125 // Returns 'true' if the geometry was rebuilt.
407 // Called at taint-time! 126 // Called at taint-time!
408 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) 127 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
409 { 128 {
410 bool ret = false; 129 bool ret = false;
411 bool haveShape = false; 130 bool haveShape = false;
131 bool nativeShapePossible = true;
132 PrimitiveBaseShape pbs = prim.BaseShape;
412 133
413 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) 134 // Kludge to create the capsule for the avatar.
135 // TDOD: Remove/redo this when BSShapeAvatar is working!!
136 BSCharacter theChar = prim as BSCharacter;
137 if (theChar != null)
414 { 138 {
415 // an avatar capsule is close to a native shape (it is not shared) 139 DereferenceExistingShape(prim, shapeCallback);
416 GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback); 140 prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
417 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); 141 BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE);
418 ret = true; 142 ret = true;
419 haveShape = true; 143 haveShape = true;
420 } 144 }
421 145
422 // Compound shapes are handled special as they are rebuilt from scratch.
423 // This isn't too great a hardship since most of the child shapes will have already been created.
424 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
425 {
426 ret = GetReferenceToCompoundShape(prim, shapeCallback);
427 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
428 haveShape = true;
429 }
430
431 if (!haveShape)
432 {
433 ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback);
434 }
435
436 return ret;
437 }
438
439 // Create a mesh, hull or native shape.
440 // Return 'true' if the prim's shape was changed.
441 public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
442 {
443 bool ret = false;
444 bool haveShape = false;
445 bool nativeShapePossible = true;
446 PrimitiveBaseShape pbs = prim.BaseShape;
447
448 // If the prim attributes are simple, this could be a simple Bullet native shape 146 // If the prim attributes are simple, this could be a simple Bullet native shape
147 // Native shapes work whether to object is static or physical.
449 if (!haveShape 148 if (!haveShape
450 && nativeShapePossible 149 && nativeShapePossible
451 && pbs != null 150 && pbs != null
452 && !pbs.SculptEntry 151 && PrimHasNoCuts(pbs)
453 && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) ) 152 && ( !pbs.SculptEntry || (pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) )
153 )
454 { 154 {
455 // Get the scale of any existing shape so we can see if the new shape is same native type and same size. 155 // Get the scale of any existing shape so we can see if the new shape is same native type and same size.
456 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero; 156 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
457 if (prim.PhysShape.HasPhysicalShape) 157 if (prim.PhysShape.HasPhysicalShape)
458 scaleOfExistingShape = PhysicsScene.PE.GetLocalScaling(prim.PhysShape); 158 scaleOfExistingShape = m_physicsScene.PE.GetLocalScaling(prim.PhysShape.physShapeInfo);
459 159
460 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}", 160 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}",
461 prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type); 161 prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.physShapeInfo.shapeType);
462 162
463 // It doesn't look like Bullet scales native spheres so make sure the scales are all equal 163 // It doesn't look like Bullet scales native spheres so make sure the scales are all equal
464 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) 164 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
@@ -466,26 +166,30 @@ public sealed class BSShapeCollection : IDisposable
466 { 166 {
467 haveShape = true; 167 haveShape = true;
468 if (forceRebuild 168 if (forceRebuild
469 || prim.Scale != scaleOfExistingShape 169 || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_SPHERE
470 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE 170 )
471 )
472 { 171 {
473 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, 172 DereferenceExistingShape(prim, shapeCallback);
474 FixedShapeKey.KEY_SPHERE, shapeCallback); 173 prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
174 BSPhysicsShapeType.SHAPE_SPHERE, FixedShapeKey.KEY_SPHERE);
175 ret = true;
475 } 176 }
476 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}", 177 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}",
477 prim.LocalID, forceRebuild, ret, prim.PhysShape); 178 prim.LocalID, forceRebuild, ret, prim.PhysShape);
478 } 179 }
180 // If we didn't make a sphere, maybe a box will work.
479 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) 181 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
480 { 182 {
481 haveShape = true; 183 haveShape = true;
482 if (forceRebuild 184 if (forceRebuild
483 || prim.Scale != scaleOfExistingShape 185 || prim.Scale != scaleOfExistingShape
484 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX 186 || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_BOX
485 ) 187 )
486 { 188 {
487 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, 189 DereferenceExistingShape(prim, shapeCallback);
488 FixedShapeKey.KEY_BOX, shapeCallback); 190 prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
191 BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
192 ret = true;
489 } 193 }
490 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}", 194 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}",
491 prim.LocalID, forceRebuild, ret, prim.PhysShape); 195 prim.LocalID, forceRebuild, ret, prim.PhysShape);
@@ -502,7 +206,7 @@ public sealed class BSShapeCollection : IDisposable
502 } 206 }
503 207
504 // return 'true' if this shape description does not include any cutting or twisting. 208 // return 'true' if this shape description does not include any cutting or twisting.
505 private bool PrimHasNoCuts(PrimitiveBaseShape pbs) 209 public static bool PrimHasNoCuts(PrimitiveBaseShape pbs)
506 { 210 {
507 return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 211 return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
508 && pbs.ProfileHollow == 0 212 && pbs.ProfileHollow == 0
@@ -514,7 +218,7 @@ public sealed class BSShapeCollection : IDisposable
514 } 218 }
515 219
516 // return 'true' if the prim's shape was changed. 220 // return 'true' if the prim's shape was changed.
517 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 221 private bool CreateGeomMeshOrHull(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
518 { 222 {
519 223
520 bool ret = false; 224 bool ret = false;
@@ -522,503 +226,121 @@ public sealed class BSShapeCollection : IDisposable
522 // made. Native shapes work in either case. 226 // made. Native shapes work in either case.
523 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) 227 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
524 { 228 {
525 // Update prim.BSShape to reference a hull of this shape. 229 // Use a simple, single mesh convex hull shape if the object is simple enough
526 ret = GetReferenceToHull(prim, shapeCallback); 230 BSShape potentialHull = null;
527 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
528 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
529 }
530 else
531 {
532 ret = GetReferenceToMesh(prim, shapeCallback);
533 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
534 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
535 }
536 return ret;
537 }
538
539 // Creates a native shape and assignes it to prim.BSShape.
540 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape().
541 private bool GetReferenceToNativeShape(BSPhysObject prim,
542 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey,
543 ShapeDestructionCallback shapeCallback)
544 {
545 // release any previous shape
546 DereferenceShape(prim.PhysShape, shapeCallback);
547
548 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
549
550 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
551 if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
552 prim.LocalID, newShape, prim.Scale);
553
554 // native shapes are scaled by Bullet
555 prim.PhysShape = newShape;
556 return true;
557 }
558
559 private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType,
560 FixedShapeKey shapeKey)
561 {
562 BulletShape newShape;
563 // Need to make sure the passed shape information is for the native type.
564 ShapeData nativeShapeData = new ShapeData();
565 nativeShapeData.Type = shapeType;
566 nativeShapeData.ID = prim.LocalID;
567 nativeShapeData.Scale = prim.Scale;
568 nativeShapeData.Size = prim.Scale; // unneeded, I think.
569 nativeShapeData.MeshKey = (ulong)shapeKey;
570 nativeShapeData.HullKey = (ulong)shapeKey;
571
572 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
573 {
574 231
575 newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale); 232 PrimitiveBaseShape pbs = prim.BaseShape;
576 if (DDetail) DetailLog("{0},BSShapeCollection.BuildPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); 233 // Use a simple, one section convex shape for prims that are probably convex (no cuts or twists)
577 } 234 if (BSParam.ShouldUseSingleConvexHullForPrims
578 else 235 && pbs != null
579 { 236 && !pbs.SculptEntry
580 // Native shapes are scaled in Bullet so set the scaling to the size 237 && PrimHasNoCuts(pbs)
581 newShape = PhysicsScene.PE.BuildNativeShape(PhysicsScene.World, nativeShapeData); 238 )
582 239 {
583 } 240 potentialHull = BSShapeConvexHull.GetReference(m_physicsScene, false /* forceRebuild */, prim);
584 if (!newShape.HasPhysicalShape) 241 }
585 { 242 // Use the GImpact shape if it is a prim that has some concaveness
586 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", 243 if (potentialHull == null
587 LogHeader, prim.LocalID, shapeType); 244 && BSParam.ShouldUseGImpactShapeForPrims
588 } 245 && pbs != null
589 newShape.shapeKey = (System.UInt64)shapeKey; 246 && !pbs.SculptEntry
590 newShape.isNativeShape = true; 247 )
591 248 {
592 return newShape; 249 potentialHull = BSShapeGImpact.GetReference(m_physicsScene, false /* forceRebuild */, prim);
593 } 250 }
594 251 // If not any of the simple cases, just make a hull
595 // Builds a mesh shape in the physical world and updates prim.BSShape. 252 if (potentialHull == null)
596 // Dereferences previous shape in BSShape and adds a reference for this new shape. 253 {
597 // Returns 'true' of a mesh was actually built. Otherwise . 254 potentialHull = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
598 // Called at taint-time! 255 }
599 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
600 {
601 BulletShape newShape = new BulletShape();
602
603 float lod;
604 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
605
606 // if this new shape is the same as last time, don't recreate the mesh
607 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
608 return false;
609
610 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2},size={3},lod={4}",
611 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
612
613 // Since we're recreating new, get rid of the reference to the previous shape
614 DereferenceShape(prim.PhysShape, shapeCallback);
615
616 newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod);
617 // Take evasive action if the mesh was not constructed.
618 newShape = VerifyMeshCreated(newShape, prim);
619
620 ReferenceShape(newShape);
621
622 prim.PhysShape = newShape;
623
624 return true; // 'true' means a new shape has been added to this prim
625 }
626
627 private BulletShape CreatePhysicalMesh(BSPhysObject prim, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
628 {
629 BulletShape newShape = new BulletShape();
630 256
631 MeshDesc meshDesc; 257 // If the current shape is not what is on the prim at the moment, time to change.
632 if (Meshes.TryGetValue(newMeshKey, out meshDesc)) 258 if (!prim.PhysShape.HasPhysicalShape
633 { 259 || potentialHull.ShapeType != prim.PhysShape.ShapeType
634 // If the mesh has already been built just use it. 260 || potentialHull.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
635 newShape = meshDesc.shape.Clone(); 261 {
262 DereferenceExistingShape(prim, shapeCallback);
263 prim.PhysShape = potentialHull;
264 ret = true;
265 }
266 else
267 {
268 // The current shape on the prim is the correct one. We don't need the potential reference.
269 potentialHull.Dereference(m_physicsScene);
270 }
271 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1}", prim.LocalID, prim.PhysShape);
636 } 272 }
637 else 273 else
638 { 274 {
639 IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, 275 // Non-physical objects should be just meshes.
640 true, 276 BSShape potentialMesh = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
641 false, // say it is not physical so a bounding box is not built 277 // If the current shape is not what is on the prim at the moment, time to change.
642 false, // do not cache the mesh and do not use previously built versions 278 if (!prim.PhysShape.HasPhysicalShape
643 false // It's NOT for ODE 279 || potentialMesh.ShapeType != prim.PhysShape.ShapeType
644 ); 280 || potentialMesh.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
645
646 if (meshData != null)
647 { 281 {
648 282 DereferenceExistingShape(prim, shapeCallback);
649 int[] indices = meshData.getIndexListAsInt(); 283 prim.PhysShape = potentialMesh;
650 int realIndicesIndex = indices.Length; 284 ret = true;
651 float[] verticesAsFloats = meshData.getVertexListAsFloat();
652
653 if (BSParam.ShouldRemoveZeroWidthTriangles)
654 {
655 // Remove degenerate triangles. These are triangles with two of the vertices
656 // are the same. This is complicated by the problem that vertices are not
657 // made unique in sculpties so we have to compare the values in the vertex.
658 realIndicesIndex = 0;
659 for (int tri = 0; tri < indices.Length; tri += 3)
660 {
661 // Compute displacements into vertex array for each vertex of the triangle
662 int v1 = indices[tri + 0] * 3;
663 int v2 = indices[tri + 1] * 3;
664 int v3 = indices[tri + 2] * 3;
665 // Check to see if any two of the vertices are the same
666 if (!( ( verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
667 && verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1]
668 && verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2])
669 || ( verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
670 && verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1]
671 && verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2])
672 || ( verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
673 && verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1]
674 && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) )
675 )
676 {
677 // None of the vertices of the triangles are the same. This is a good triangle;
678 indices[realIndicesIndex + 0] = indices[tri + 0];
679 indices[realIndicesIndex + 1] = indices[tri + 1];
680 indices[realIndicesIndex + 2] = indices[tri + 2];
681 realIndicesIndex += 3;
682 }
683 }
684 }
685 DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}",
686 BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
687
688 if (realIndicesIndex != 0)
689 {
690 newShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World,
691 realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
692 }
693 else
694 {
695 PhysicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}",
696 LogHeader, prim.PhysObjectName, prim.RawPosition, PhysicsScene.Name);
697 }
698 } 285 }
286 else
287 {
288 // We don't need this reference to the mesh that is already being using.
289 potentialMesh.Dereference(m_physicsScene);
290 }
291 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1}", prim.LocalID, prim.PhysShape);
699 } 292 }
700 newShape.shapeKey = newMeshKey; 293 return ret;
701
702 return newShape;
703 }
704
705 // See that hull shape exists in the physical world and update prim.BSShape.
706 // We could be creating the hull because scale changed or whatever.
707 // Return 'true' if a new hull was built. Otherwise, returning a shared hull instance.
708 private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
709 {
710 BulletShape newShape;
711
712 float lod;
713 System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
714
715 // if the hull hasn't changed, don't rebuild it
716 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
717 return false;
718
719 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
720 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
721
722 // Remove usage of the previous shape.
723 DereferenceShape(prim.PhysShape, shapeCallback);
724
725 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
726 // It might not have been created if we're waiting for an asset.
727 newShape = VerifyMeshCreated(newShape, prim);
728
729 ReferenceShape(newShape);
730
731 prim.PhysShape = newShape;
732 return true; // 'true' means a new shape has been added to this prim
733 } 294 }
734 295
735 List<ConvexResult> m_hulls; 296 // Track another user of a body.
736 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 297 // We presume the caller has allocated the body.
298 // Bodies only have one user so the body is just put into the world if not already there.
299 private void ReferenceBody(BulletBody body)
737 { 300 {
738 301 lock (m_collectionActivityLock)
739 BulletShape newShape = new BulletShape();
740 IntPtr hullPtr = IntPtr.Zero;
741
742 HullDesc hullDesc;
743 if (Hulls.TryGetValue(newHullKey, out hullDesc))
744 {
745 // If the hull shape already has been created, just use the one shared instance.
746 newShape = hullDesc.shape.Clone();
747 }
748 else
749 { 302 {
750 // Build a new hull in the physical world. 303 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
751 // Pass true for physicalness as this prevents the creation of bounding box which is not needed 304 if (!m_physicsScene.PE.IsInWorld(m_physicsScene.World, body))
752 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
753 if (meshData != null)
754 { 305 {
755 306 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, body);
756 int[] indices = meshData.getIndexListAsInt(); 307 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
757 List<OMV.Vector3> vertices = meshData.getVertexList();
758
759 //format conversion from IMesh format to DecompDesc format
760 List<int> convIndices = new List<int>();
761 List<float3> convVertices = new List<float3>();
762 for (int ii = 0; ii < indices.GetLength(0); ii++)
763 {
764 convIndices.Add(indices[ii]);
765 }
766 foreach (OMV.Vector3 vv in vertices)
767 {
768 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
769 }
770
771 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
772 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
773 {
774 // Simple primitive shapes we know are convex so they are better implemented with
775 // fewer hulls.
776 // Check for simple shape (prim without cuts) and reduce split parameter if so.
777 if (PrimHasNoCuts(pbs))
778 {
779 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
780 }
781 }
782
783 // setup and do convex hull conversion
784 m_hulls = new List<ConvexResult>();
785 DecompDesc dcomp = new DecompDesc();
786 dcomp.mIndices = convIndices;
787 dcomp.mVertices = convVertices;
788 dcomp.mDepth = maxDepthSplit;
789 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
790 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
791 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
792 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
793 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
794 // create the hull into the _hulls variable
795 convexBuilder.process(dcomp);
796
797 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
798 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
799
800 // Convert the vertices and indices for passing to unmanaged.
801 // The hull information is passed as a large floating point array.
802 // The format is:
803 // convHulls[0] = number of hulls
804 // convHulls[1] = number of vertices in first hull
805 // convHulls[2] = hull centroid X coordinate
806 // convHulls[3] = hull centroid Y coordinate
807 // convHulls[4] = hull centroid Z coordinate
808 // convHulls[5] = first hull vertex X
809 // convHulls[6] = first hull vertex Y
810 // convHulls[7] = first hull vertex Z
811 // convHulls[8] = second hull vertex X
812 // ...
813 // convHulls[n] = number of vertices in second hull
814 // convHulls[n+1] = second hull centroid X coordinate
815 // ...
816 //
817 // TODO: is is very inefficient. Someday change the convex hull generator to return
818 // data structures that do not need to be converted in order to pass to Bullet.
819 // And maybe put the values directly into pinned memory rather than marshaling.
820 int hullCount = m_hulls.Count;
821 int totalVertices = 1; // include one for the count of the hulls
822 foreach (ConvexResult cr in m_hulls)
823 {
824 totalVertices += 4; // add four for the vertex count and centroid
825 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
826 }
827 float[] convHulls = new float[totalVertices];
828
829 convHulls[0] = (float)hullCount;
830 int jj = 1;
831 foreach (ConvexResult cr in m_hulls)
832 {
833 // copy vertices for index access
834 float3[] verts = new float3[cr.HullVertices.Count];
835 int kk = 0;
836 foreach (float3 ff in cr.HullVertices)
837 {
838 verts[kk++] = ff;
839 }
840
841 // add to the array one hull's worth of data
842 convHulls[jj++] = cr.HullIndices.Count;
843 convHulls[jj++] = 0f; // centroid x,y,z
844 convHulls[jj++] = 0f;
845 convHulls[jj++] = 0f;
846 foreach (int ind in cr.HullIndices)
847 {
848 convHulls[jj++] = verts[ind].x;
849 convHulls[jj++] = verts[ind].y;
850 convHulls[jj++] = verts[ind].z;
851 }
852 }
853 // create the hull data structure in Bullet
854 newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
855 } 308 }
856 } 309 }
857
858 newShape.shapeKey = newHullKey;
859
860 return newShape;
861 }
862
863 // Callback from convex hull creater with a newly created hull.
864 // Just add it to our collection of hulls for this shape.
865 private void HullReturn(ConvexResult result)
866 {
867 m_hulls.Add(result);
868 return;
869 } 310 }
870 311
871 // Compound shapes are always built from scratch. 312 // Release the usage of a body.
872 // This shouldn't be to bad since most of the parts will be meshes that had been built previously. 313 // Called when releasing use of a BSBody. BSShape is handled separately.
873 private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 314 // Called in taint time.
874 { 315 public void DereferenceBody(BulletBody body, PhysicalDestructionCallback bodyCallback )
875 // Remove reference to the old shape
876 // Don't need to do this as the shape is freed when the new root shape is created below.
877 // DereferenceShape(prim.PhysShape, true, shapeCallback);
878
879 BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false);
880
881 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
882 CreateGeomMeshOrHull(prim, shapeCallback);
883 PhysicsScene.PE.AddChildShapeToCompoundShape(cShape, prim.PhysShape, OMV.Vector3.Zero, OMV.Quaternion.Identity);
884 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
885 prim.LocalID, cShape, prim.PhysShape);
886
887 prim.PhysShape = cShape;
888
889 return true;
890 }
891
892 // Create a hash of all the shape parameters to be used as a key
893 // for this particular shape.
894 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
895 {
896 // level of detail based on size and type of the object
897 float lod = BSParam.MeshLOD;
898
899 // prims with curvy internal cuts need higher lod
900 if (pbs.HollowShape == HollowShape.Circle)
901 lod = BSParam.MeshCircularLOD;
902
903 if (pbs.SculptEntry)
904 lod = BSParam.SculptLOD;
905
906 // Mega prims usually get more detail because one can interact with shape approximations at this size.
907 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
908 if (maxAxis > BSParam.MeshMegaPrimThreshold)
909 lod = BSParam.MeshMegaPrimLOD;
910
911 retLod = lod;
912 return pbs.GetMeshKey(size, lod);
913 }
914 // For those who don't want the LOD
915 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
916 { 316 {
917 float lod; 317 if (!body.HasPhysicalBody)
918 return ComputeShapeKey(size, pbs, out lod); 318 return;
919 }
920 319
921 // The creation of a mesh or hull can fail if an underlying asset is not available. 320 m_physicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
922 // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
923 // and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
924 // The first case causes the asset to be fetched. The second case requires
925 // us to not loop forever.
926 // Called after creating a physical mesh or hull. If the physical shape was created,
927 // just return.
928 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
929 {
930 // If the shape was successfully created, nothing more to do
931 if (newShape.HasPhysicalShape)
932 return newShape;
933 321
934 // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been 322 lock (m_collectionActivityLock)
935 // fetched but we end up here again, the meshing of the asset must have failed.
936 // Prevent trying to keep fetching the mesh by declaring failure.
937 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
938 {
939 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
940 PhysicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
941 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
942 }
943 else
944 { 323 {
945 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset 324 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body);
946 if (prim.BaseShape.SculptEntry 325 // If the caller needs to know the old body is going away, pass the event up.
947 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed 326 if (bodyCallback != null)
948 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting 327 bodyCallback(body, null);
949 && prim.BaseShape.SculptTexture != OMV.UUID.Zero
950 )
951 {
952 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
953 // Multiple requestors will know we're waiting for this asset
954 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
955
956 BSPhysObject xprim = prim;
957 Util.FireAndForget(delegate
958 {
959 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
960 if (assetProvider != null)
961 {
962 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
963 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
964 {
965 bool assetFound = false;
966 string mismatchIDs = String.Empty; // DEBUG DEBUG
967 if (asset != null && yprim.BaseShape.SculptEntry)
968 {
969 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
970 {
971 yprim.BaseShape.SculptData = asset.Data;
972 // This will cause the prim to see that the filler shape is not the right
973 // one and try again to build the object.
974 // No race condition with the normal shape setting since the rebuild is at taint time.
975 yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
976 assetFound = true;
977 }
978 else
979 {
980 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
981 }
982 }
983 if (assetFound)
984 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
985 else
986 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
987 DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
988 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
989 328
990 }); 329 // Removing an object not in the world is a NOOP
991 } 330 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, body);
992 else
993 {
994 xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
995 PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
996 LogHeader, PhysicsScene.Name);
997 }
998 });
999 }
1000 else
1001 {
1002 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
1003 {
1004 PhysicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
1005 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
1006 }
1007 }
1008 }
1009 331
1010 // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object. 332 // Zero any reference to the shape so it is not freed when the body is deleted.
1011 BulletShape fillinShape = BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); 333 m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, body, null);
1012 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
1013 334
1014 return fillinShape; 335 m_physicsScene.PE.DestroyObject(m_physicsScene.World, body);
336 }
1015 } 337 }
1016 338
1017 // Create a body object in Bullet. 339 // Create a body object in Bullet.
1018 // Updates prim.BSBody with the information about the new body if one is created. 340 // Updates prim.BSBody with the information about the new body if one is created.
1019 // Returns 'true' if an object was actually created. 341 // Returns 'true' if an object was actually created.
1020 // Called at taint-time. 342 // Called at taint-time.
1021 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BodyDestructionCallback bodyCallback) 343 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, PhysicalDestructionCallback bodyCallback)
1022 { 344 {
1023 bool ret = false; 345 bool ret = false;
1024 346
@@ -1029,7 +351,7 @@ public sealed class BSShapeCollection : IDisposable
1029 // If not a solid object, body is a GhostObject. Otherwise a RigidBody. 351 // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
1030 if (!mustRebuild) 352 if (!mustRebuild)
1031 { 353 {
1032 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(prim.PhysBody); 354 CollisionObjectTypes bodyType = (CollisionObjectTypes)m_physicsScene.PE.GetBodyType(prim.PhysBody);
1033 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY 355 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY
1034 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) 356 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT)
1035 { 357 {
@@ -1047,12 +369,12 @@ public sealed class BSShapeCollection : IDisposable
1047 BulletBody aBody; 369 BulletBody aBody;
1048 if (prim.IsSolid) 370 if (prim.IsSolid)
1049 { 371 {
1050 aBody = PhysicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); 372 aBody = m_physicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation);
1051 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody); 373 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,rigid,body={1}", prim.LocalID, aBody);
1052 } 374 }
1053 else 375 else
1054 { 376 {
1055 aBody = PhysicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); 377 aBody = m_physicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation);
1056 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody); 378 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody);
1057 } 379 }
1058 380
@@ -1066,46 +388,10 @@ public sealed class BSShapeCollection : IDisposable
1066 return ret; 388 return ret;
1067 } 389 }
1068 390
1069 private bool TryGetMeshByPtr(BulletShape shape, out MeshDesc outDesc)
1070 {
1071 bool ret = false;
1072 MeshDesc foundDesc = new MeshDesc();
1073 foreach (MeshDesc md in Meshes.Values)
1074 {
1075 if (md.shape.ReferenceSame(shape))
1076 {
1077 foundDesc = md;
1078 ret = true;
1079 break;
1080 }
1081
1082 }
1083 outDesc = foundDesc;
1084 return ret;
1085 }
1086
1087 private bool TryGetHullByPtr(BulletShape shape, out HullDesc outDesc)
1088 {
1089 bool ret = false;
1090 HullDesc foundDesc = new HullDesc();
1091 foreach (HullDesc hd in Hulls.Values)
1092 {
1093 if (hd.shape.ReferenceSame(shape))
1094 {
1095 foundDesc = hd;
1096 ret = true;
1097 break;
1098 }
1099
1100 }
1101 outDesc = foundDesc;
1102 return ret;
1103 }
1104
1105 private void DetailLog(string msg, params Object[] args) 391 private void DetailLog(string msg, params Object[] args)
1106 { 392 {
1107 if (PhysicsScene.PhysicsLogging.Enabled) 393 if (m_physicsScene.PhysicsLogging.Enabled)
1108 PhysicsScene.DetailLog(msg, args); 394 m_physicsScene.DetailLog(msg, args);
1109 } 395 }
1110} 396}
1111} 397}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
index ee18379..fe5ff6c 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -29,115 +29,312 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Text; 30using System.Text;
31 31
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34using OpenSim.Region.Physics.Meshing;
35using OpenSim.Region.Physics.ConvexDecompositionDotNet;
36
32using OMV = OpenMetaverse; 37using OMV = OpenMetaverse;
33 38
34namespace OpenSim.Region.Physics.BulletSPlugin 39namespace OpenSim.Region.Physics.BulletSPlugin
35{ 40{
36public abstract class BSShape 41public abstract class BSShape
37{ 42{
43 private static string LogHeader = "[BULLETSIM SHAPE]";
44
38 public int referenceCount { get; set; } 45 public int referenceCount { get; set; }
39 public DateTime lastReferenced { get; set; } 46 public DateTime lastReferenced { get; set; }
47 public BulletShape physShapeInfo { get; set; }
40 48
41 public BSShape() 49 public BSShape()
42 { 50 {
43 referenceCount = 0; 51 referenceCount = 1;
44 lastReferenced = DateTime.Now; 52 lastReferenced = DateTime.Now;
53 physShapeInfo = new BulletShape();
45 } 54 }
46 55 public BSShape(BulletShape pShape)
47 // Get a reference to a physical shape. Create if it doesn't exist
48 public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
49 { 56 {
50 BSShape ret = null; 57 referenceCount = 1;
51 58 lastReferenced = DateTime.Now;
52 if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) 59 physShapeInfo = pShape;
53 { 60 }
54 // an avatar capsule is close to a native shape (it is not shared)
55 ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE,
56 FixedShapeKey.KEY_CAPSULE);
57 physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret);
58 }
59
60 // Compound shapes are handled special as they are rebuilt from scratch.
61 // This isn't too great a hardship since most of the child shapes will have already been created.
62 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
63 {
64 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
65 ret = BSShapeCompound.GetReference(prim);
66 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
67 }
68
69 // Avatars have their own unique shape
70 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_AVATAR)
71 {
72 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
73 ret = BSShapeAvatar.GetReference(prim);
74 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,avatarShape,shape={1}", prim.LocalID, ret);
75 }
76 61
77 if (ret == null) 62 // Get another reference to this shape.
78 ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim); 63 public abstract BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim);
79 64
80 return ret; 65 // Called when this shape is being used again.
81 } 66 // Used internally. External callers should call instance.GetReference() to properly copy/reference
82 public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 67 // the shape.
68 protected virtual void IncrementReference()
83 { 69 {
84 return null; 70 referenceCount++;
71 lastReferenced = DateTime.Now;
85 } 72 }
86 public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 73
74 // Called when this shape is done being used.
75 protected virtual void DecrementReference()
87 { 76 {
88 return null; 77 referenceCount--;
78 lastReferenced = DateTime.Now;
89 } 79 }
90 80
91 // Release the use of a physical shape. 81 // Release the use of a physical shape.
92 public abstract void Dereference(BSScene physicsScene); 82 public abstract void Dereference(BSScene physicsScene);
93 83
94 // All shapes have a static call to get a reference to the physical shape 84 // Return 'true' if there is an allocated physics physical shape under this class instance.
95 // protected abstract static BSShape GetReference(); 85 public virtual bool HasPhysicalShape
86 {
87 get
88 {
89 if (physShapeInfo != null)
90 return physShapeInfo.HasPhysicalShape;
91 return false;
92 }
93 }
94 public virtual BSPhysicsShapeType ShapeType
95 {
96 get
97 {
98 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
99 if (physShapeInfo != null && physShapeInfo.HasPhysicalShape)
100 ret = physShapeInfo.shapeType;
101 return ret;
102 }
103 }
96 104
97 // Returns a string for debugging that uniquily identifies the memory used by this instance 105 // Returns a string for debugging that uniquily identifies the memory used by this instance
98 public virtual string AddrString 106 public virtual string AddrString
99 { 107 {
100 get { return "unknown"; } 108 get
109 {
110 if (physShapeInfo != null)
111 return physShapeInfo.AddrString;
112 return "unknown";
113 }
101 } 114 }
102 115
103 public override string ToString() 116 public override string ToString()
104 { 117 {
105 StringBuilder buff = new StringBuilder(); 118 StringBuilder buff = new StringBuilder();
106 buff.Append("<p="); 119 if (physShapeInfo == null)
107 buff.Append(AddrString); 120 {
121 buff.Append("<noPhys");
122 }
123 else
124 {
125 buff.Append("<phy=");
126 buff.Append(physShapeInfo.ToString());
127 }
108 buff.Append(",c="); 128 buff.Append(",c=");
109 buff.Append(referenceCount.ToString()); 129 buff.Append(referenceCount.ToString());
110 buff.Append(">"); 130 buff.Append(">");
111 return buff.ToString(); 131 return buff.ToString();
112 } 132 }
133
134 #region Common shape routines
135 // Create a hash of all the shape parameters to be used as a key for this particular shape.
136 public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
137 {
138 // level of detail based on size and type of the object
139 float lod = BSParam.MeshLOD;
140 if (pbs.SculptEntry)
141 lod = BSParam.SculptLOD;
142
143 // Mega prims usually get more detail because one can interact with shape approximations at this size.
144 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
145 if (maxAxis > BSParam.MeshMegaPrimThreshold)
146 lod = BSParam.MeshMegaPrimLOD;
147
148 retLod = lod;
149 return pbs.GetMeshKey(size, lod);
150 }
151
152 // The creation of a mesh or hull can fail if an underlying asset is not available.
153 // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
154 // and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
155 // The first case causes the asset to be fetched. The second case requires
156 // us to not loop forever.
157 // Called after creating a physical mesh or hull. If the physical shape was created,
158 // just return.
159 public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim)
160 {
161 // If the shape was successfully created, nothing more to do
162 if (newShape.HasPhysicalShape)
163 return newShape;
164
165 // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been
166 // fetched but we end up here again, the meshing of the asset must have failed.
167 // Prevent trying to keep fetching the mesh by declaring failure.
168 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
169 {
170 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.FailedMeshing;
171 physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. prim={1}, texture={2}",
172 LogHeader, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
173 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,setFailed,prim={1},tex={2}",
174 prim.LocalID, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
175 }
176 else
177 {
178 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
179 if (prim.BaseShape.SculptEntry
180 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.FailedAssetFetch
181 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.FailedMeshing
182 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting
183 && prim.BaseShape.SculptTexture != OMV.UUID.Zero
184 )
185 {
186 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,fetchAsset,objNam={1},tex={2}",
187 prim.LocalID, prim.PhysObjectName, prim.BaseShape.SculptTexture);
188 // Multiple requestors will know we're waiting for this asset
189 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
190
191 BSPhysObject xprim = prim;
192 Util.FireAndForget(delegate
193 {
194 // physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,inFireAndForget", xprim.LocalID);
195 RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
196 if (assetProvider != null)
197 {
198 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
199 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
200 {
201 // physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,assetProviderCallback", xprim.LocalID);
202 bool assetFound = false;
203 string mismatchIDs = String.Empty; // DEBUG DEBUG
204 if (asset != null && yprim.BaseShape.SculptEntry)
205 {
206 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
207 {
208 yprim.BaseShape.SculptData = asset.Data;
209 // This will cause the prim to see that the filler shape is not the right
210 // one and try again to build the object.
211 // No race condition with the normal shape setting since the rebuild is at taint time.
212 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
213 yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
214 assetFound = true;
215 }
216 else
217 {
218 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
219 }
220 }
221 if (!assetFound)
222 {
223 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.FailedAssetFetch;
224 }
225 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
226 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
227 });
228 }
229 else
230 {
231 xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.FailedAssetFetch;
232 physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
233 LogHeader, physicsScene.Name);
234 }
235 });
236 }
237 else
238 {
239 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedAssetFetch)
240 {
241 physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. prim={1}, texture={2}",
242 LogHeader, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
243 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,wasFailed,prim={1},tex={2}",
244 prim.LocalID, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
245 }
246 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedMeshing)
247 {
248 physicsScene.Logger.WarnFormat("{0} Mesh asset would not mesh. prim={1}, texture={2}",
249 LogHeader, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
250 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,wasFailedMeshing,prim={1},tex={2}",
251 prim.LocalID, UsefulPrimInfo(physicsScene, prim), prim.BaseShape.SculptTexture);
252 }
253 }
254 }
255
256 // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object.
257 BSShape fillShape = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
258 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,boxTempShape", prim.LocalID);
259
260 return fillShape.physShapeInfo;
261 }
262
263 public static String UsefulPrimInfo(BSScene pScene, BSPhysObject prim)
264 {
265 StringBuilder buff = new StringBuilder(prim.PhysObjectName);
266 buff.Append("/pos=");
267 buff.Append(prim.RawPosition.ToString());
268 if (pScene != null)
269 {
270 buff.Append("/rgn=");
271 buff.Append(pScene.Name);
272 }
273 return buff.ToString();
274 }
275
276 #endregion // Common shape routines
113} 277}
114 278
279// ============================================================================================================
115public class BSShapeNull : BSShape 280public class BSShapeNull : BSShape
116{ 281{
117 public BSShapeNull() : base() 282 public BSShapeNull() : base()
118 { 283 {
119 } 284 }
120 public static BSShape GetReference() { return new BSShapeNull(); } 285 public static BSShape GetReference() { return new BSShapeNull(); }
286 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim) { return new BSShapeNull(); }
121 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ } 287 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ }
122} 288}
123 289
290// ============================================================================================================
124public class BSShapeNative : BSShape 291public class BSShapeNative : BSShape
125{ 292{
126 private static string LogHeader = "[BULLETSIM SHAPE NATIVE]"; 293 private static string LogHeader = "[BULLETSIM SHAPE NATIVE]";
127 public BSShapeNative() : base() 294 public BSShapeNative(BulletShape pShape) : base(pShape)
128 { 295 {
129 } 296 }
130 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, 297
131 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) 298 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
299 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
132 { 300 {
133 // Native shapes are not shared and are always built anew. 301 // Native shapes are not shared and are always built anew.
134 //return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); 302 return new BSShapeNative(CreatePhysicalNativeShape(physicsScene, prim, shapeType, shapeKey));
135 return null;
136 } 303 }
137 304
138 private BSShapeNative(BSScene physicsScene, BSPhysObject prim, 305 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
139 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
140 { 306 {
307 // Native shapes are not shared so we return a new shape.
308 BSShape ret = null;
309 lock (physShapeInfo)
310 {
311 ret = new BSShapeNative(CreatePhysicalNativeShape(pPhysicsScene, pPrim,
312 physShapeInfo.shapeType, (FixedShapeKey)physShapeInfo.shapeKey));
313 }
314 return ret;
315 }
316
317 // Make this reference to the physical shape go away since native shapes are not shared.
318 public override void Dereference(BSScene physicsScene)
319 {
320 // Native shapes are not tracked and are released immediately
321 lock (physShapeInfo)
322 {
323 if (physShapeInfo.HasPhysicalShape)
324 {
325 physicsScene.DetailLog("{0},BSShapeNative.Dereference,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
326 physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
327 }
328 physShapeInfo.Clear();
329 // Garbage collection will free up this instance.
330 }
331 }
332
333 private static BulletShape CreatePhysicalNativeShape(BSScene physicsScene, BSPhysObject prim,
334 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
335 {
336 BulletShape newShape;
337
141 ShapeData nativeShapeData = new ShapeData(); 338 ShapeData nativeShapeData = new ShapeData();
142 nativeShapeData.Type = shapeType; 339 nativeShapeData.Type = shapeType;
143 nativeShapeData.ID = prim.LocalID; 340 nativeShapeData.ID = prim.LocalID;
@@ -146,84 +343,880 @@ public class BSShapeNative : BSShape
146 nativeShapeData.MeshKey = (ulong)shapeKey; 343 nativeShapeData.MeshKey = (ulong)shapeKey;
147 nativeShapeData.HullKey = (ulong)shapeKey; 344 nativeShapeData.HullKey = (ulong)shapeKey;
148 345
149
150 /*
151 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) 346 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
152 { 347 {
153 ptr = PhysicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale); 348 newShape = physicsScene.PE.BuildCapsuleShape(physicsScene.World, 1f, 1f, prim.Scale);
154 physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); 349 physicsScene.DetailLog("{0},BSShapeNative,capsule,scale={1}", prim.LocalID, prim.Scale);
155 } 350 }
156 else 351 else
157 { 352 {
158 ptr = PhysicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData); 353 newShape = physicsScene.PE.BuildNativeShape(physicsScene.World, nativeShapeData);
159 } 354 }
160 if (ptr == IntPtr.Zero) 355 if (!newShape.HasPhysicalShape)
161 { 356 {
162 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", 357 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
163 LogHeader, prim.LocalID, shapeType); 358 LogHeader, prim.LocalID, shapeType);
164 } 359 }
165 type = shapeType; 360 newShape.shapeType = shapeType;
166 key = (UInt64)shapeKey; 361 newShape.isNativeShape = true;
167 */ 362 newShape.shapeKey = (UInt64)shapeKey;
168 } 363 return newShape;
169 // Make this reference to the physical shape go away since native shapes are not shared.
170 public override void Dereference(BSScene physicsScene)
171 {
172 /*
173 // Native shapes are not tracked and are released immediately
174 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
175 PhysicsScene.PE.DeleteCollisionShape(physicsScene.World, this);
176 ptr = IntPtr.Zero;
177 // Garbage collection will free up this instance.
178 */
179 } 364 }
365
180} 366}
181 367
368// ============================================================================================================
182public class BSShapeMesh : BSShape 369public class BSShapeMesh : BSShape
183{ 370{
184 private static string LogHeader = "[BULLETSIM SHAPE MESH]"; 371 private static string LogHeader = "[BULLETSIM SHAPE MESH]";
185 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>(); 372 public static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>();
186 373
187 public BSShapeMesh() : base() 374 public BSShapeMesh(BulletShape pShape) : base(pShape)
188 { 375 {
189 } 376 }
190 public static BSShape GetReference() { return new BSShapeNull(); } 377 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
191 public override void Dereference(BSScene physicsScene) { } 378 {
379 float lod;
380 System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
381
382 BSShapeMesh retMesh = null;
383 lock (Meshes)
384 {
385 if (Meshes.TryGetValue(newMeshKey, out retMesh))
386 {
387 // The mesh has already been created. Return a new reference to same.
388 retMesh.IncrementReference();
389 }
390 else
391 {
392 retMesh = new BSShapeMesh(new BulletShape());
393 // An instance of this mesh has not been created. Build and remember same.
394 BulletShape newShape = retMesh.CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
395
396 // Check to see if mesh was created (might require an asset).
397 newShape = VerifyMeshCreated(physicsScene, newShape, prim);
398 if (!newShape.isNativeShape
399 || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedMeshing
400 || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedAssetFetch)
401 {
402 // If a mesh was what was created, remember the built shape for later sharing.
403 // Also note that if meshing failed we put it in the mesh list as there is nothing else to do about the mesh.
404 Meshes.Add(newMeshKey, retMesh);
405 }
406
407 retMesh.physShapeInfo = newShape;
408 }
409 }
410 physicsScene.DetailLog("{0},BSShapeMesh,getReference,mesh={1},size={2},lod={3}", prim.LocalID, retMesh, prim.Size, lod);
411 return retMesh;
412 }
413 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
414 {
415 BSShape ret = null;
416 // If the underlying shape is native, the actual shape has not been build (waiting for asset)
417 // and we must create a copy of the native shape since they are never shared.
418 if (physShapeInfo.HasPhysicalShape && physShapeInfo.isNativeShape)
419 {
420 // TODO: decide when the native shapes should be freed. Check in Dereference?
421 ret = BSShapeNative.GetReference(pPhysicsScene, pPrim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
422 }
423 else
424 {
425 // Another reference to this shape is just counted.
426 IncrementReference();
427 ret = this;
428 }
429 return ret;
430 }
431 public override void Dereference(BSScene physicsScene)
432 {
433 lock (Meshes)
434 {
435 this.DecrementReference();
436 physicsScene.DetailLog("{0},BSShapeMesh.Dereference,shape={1}", BSScene.DetailLogZero, this);
437 // TODO: schedule aging and destruction of unused meshes.
438 }
439 }
440 // Loop through all the known meshes and return the description based on the physical address.
441 public static bool TryGetMeshByPtr(BulletShape pShape, out BSShapeMesh outMesh)
442 {
443 bool ret = false;
444 BSShapeMesh foundDesc = null;
445 lock (Meshes)
446 {
447 foreach (BSShapeMesh sm in Meshes.Values)
448 {
449 if (sm.physShapeInfo.ReferenceSame(pShape))
450 {
451 foundDesc = sm;
452 ret = true;
453 break;
454 }
455
456 }
457 }
458 outMesh = foundDesc;
459 return ret;
460 }
461
462 public delegate BulletShape CreateShapeCall(BulletWorld world, int indicesCount, int[] indices, int verticesCount, float[] vertices );
463 private BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
464 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
465 {
466 return BSShapeMesh.CreatePhysicalMeshShape(physicsScene, prim, newMeshKey, pbs, size, lod,
467 (w, iC, i, vC, v) => physicsScene.PE.CreateMeshShape(w, iC, i, vC, v) );
468 }
469
470 // Code that uses the mesher to create the index/vertices info for a trimesh shape.
471 // This is used by the passed 'makeShape' call to create the Bullet mesh shape.
472 // The actual build call is passed so this logic can be used by several of the shapes that use a
473 // simple mesh as their base shape.
474 public static BulletShape CreatePhysicalMeshShape(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
475 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod, CreateShapeCall makeShape)
476 {
477 BulletShape newShape = new BulletShape();
478
479 IMesh meshData = null;
480 lock (physicsScene.mesher)
481 {
482 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
483 false, // say it is not physical so a bounding box is not built
484 false, // do not cache the mesh and do not use previously built versions
485 false,
486 false
487 );
488 }
489
490 if (meshData != null)
491 {
492 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
493 {
494 // Release the fetched asset data once it has been used.
495 pbs.SculptData = new byte[0];
496 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
497 }
498
499 int[] indices = meshData.getIndexListAsInt();
500 int realIndicesIndex = indices.Length;
501 float[] verticesAsFloats = meshData.getVertexListAsFloat();
502
503 if (BSParam.ShouldRemoveZeroWidthTriangles)
504 {
505 // Remove degenerate triangles. These are triangles with two of the vertices
506 // are the same. This is complicated by the problem that vertices are not
507 // made unique in sculpties so we have to compare the values in the vertex.
508 realIndicesIndex = 0;
509 for (int tri = 0; tri < indices.Length; tri += 3)
510 {
511 // Compute displacements into vertex array for each vertex of the triangle
512 int v1 = indices[tri + 0] * 3;
513 int v2 = indices[tri + 1] * 3;
514 int v3 = indices[tri + 2] * 3;
515 // Check to see if any two of the vertices are the same
516 if (!( ( verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
517 && verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1]
518 && verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2])
519 || ( verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
520 && verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1]
521 && verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2])
522 || ( verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
523 && verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1]
524 && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) )
525 )
526 {
527 // None of the vertices of the triangles are the same. This is a good triangle;
528 indices[realIndicesIndex + 0] = indices[tri + 0];
529 indices[realIndicesIndex + 1] = indices[tri + 1];
530 indices[realIndicesIndex + 2] = indices[tri + 2];
531 realIndicesIndex += 3;
532 }
533 }
534 }
535 physicsScene.DetailLog("{0},BSShapeMesh.CreatePhysicalMesh,key={1},origTri={2},realTri={3},numVerts={4}",
536 BSScene.DetailLogZero, newMeshKey.ToString("X"), indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
537
538 if (realIndicesIndex != 0)
539 {
540 newShape = makeShape(physicsScene.World, realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
541 }
542 else
543 {
544 // Force the asset condition to 'failed' so we won't try to keep fetching and processing this mesh.
545 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.FailedMeshing;
546 physicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim={1}", LogHeader, UsefulPrimInfo(physicsScene, prim) );
547 physicsScene.DetailLog("{0},BSShapeMesh.CreatePhysicalMesh,allDegenerate,key={1}", prim.LocalID, newMeshKey);
548 }
549 }
550 newShape.shapeKey = newMeshKey;
551
552 return newShape;
553 }
192} 554}
193 555
556// ============================================================================================================
194public class BSShapeHull : BSShape 557public class BSShapeHull : BSShape
195{ 558{
196 private static string LogHeader = "[BULLETSIM SHAPE HULL]"; 559 private static string LogHeader = "[BULLETSIM SHAPE HULL]";
197 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>(); 560 public static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
198 561
199 public BSShapeHull() : base() 562 public BSShapeHull(BulletShape pShape) : base(pShape)
200 { 563 {
201 } 564 }
202 public static BSShape GetReference() { return new BSShapeNull(); } 565 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
203 public override void Dereference(BSScene physicsScene) { } 566 {
567 float lod;
568 System.UInt64 newHullKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
569
570 BSShapeHull retHull = null;
571 lock (Hulls)
572 {
573 if (Hulls.TryGetValue(newHullKey, out retHull))
574 {
575 // The mesh has already been created. Return a new reference to same.
576 retHull.IncrementReference();
577 }
578 else
579 {
580 retHull = new BSShapeHull(new BulletShape());
581 // An instance of this mesh has not been created. Build and remember same.
582 BulletShape newShape = retHull.CreatePhysicalHull(physicsScene, prim, newHullKey, prim.BaseShape, prim.Size, lod);
583
584 // Check to see if hull was created (might require an asset).
585 newShape = VerifyMeshCreated(physicsScene, newShape, prim);
586 if (!newShape.isNativeShape
587 || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedMeshing
588 || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedAssetFetch)
589 {
590 // If a mesh was what was created, remember the built shape for later sharing.
591 Hulls.Add(newHullKey, retHull);
592 }
593 retHull.physShapeInfo = newShape;
594 }
595 }
596 physicsScene.DetailLog("{0},BSShapeHull,getReference,hull={1},size={2},lod={3}", prim.LocalID, retHull, prim.Size, lod);
597 return retHull;
598 }
599 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
600 {
601 BSShape ret = null;
602 // If the underlying shape is native, the actual shape has not been build (waiting for asset)
603 // and we must create a copy of the native shape since they are never shared.
604 if (physShapeInfo.HasPhysicalShape && physShapeInfo.isNativeShape)
605 {
606 // TODO: decide when the native shapes should be freed. Check in Dereference?
607 ret = BSShapeNative.GetReference(pPhysicsScene, pPrim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
608 }
609 else
610 {
611 // Another reference to this shape is just counted.
612 IncrementReference();
613 ret = this;
614 }
615 return ret;
616 }
617 public override void Dereference(BSScene physicsScene)
618 {
619 lock (Hulls)
620 {
621 this.DecrementReference();
622 physicsScene.DetailLog("{0},BSShapeHull.Dereference,shape={1}", BSScene.DetailLogZero, this);
623 // TODO: schedule aging and destruction of unused meshes.
624 }
625 }
626 List<ConvexResult> m_hulls;
627 private BulletShape CreatePhysicalHull(BSScene physicsScene, BSPhysObject prim, System.UInt64 newHullKey,
628 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
629 {
630 BulletShape newShape = new BulletShape();
631
632 IMesh meshData = null;
633 List<List<OMV.Vector3>> allHulls = null;
634 lock (physicsScene.mesher)
635 {
636 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
637 meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */, false, false);
638
639 // If we should use the asset's hull info, fetch it out of the locked mesher
640 if (meshData != null && BSParam.ShouldUseAssetHulls)
641 {
642 Meshmerizer realMesher = physicsScene.mesher as Meshmerizer;
643 if (realMesher != null)
644 {
645 allHulls = realMesher.GetConvexHulls(size);
646 }
647 if (allHulls == null)
648 {
649 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,noAssetHull", prim.LocalID);
650 }
651 }
652 }
653
654 // If there is hull data in the mesh asset, build the hull from that
655 if (allHulls != null && BSParam.ShouldUseAssetHulls)
656 {
657 int hullCount = allHulls.Count;
658 int totalVertices = 1; // include one for the count of the hulls
659 // Using the structure described for HACD hulls, create the memory sturcture
660 // to pass the hull data to the creater.
661 foreach (List<OMV.Vector3> hullVerts in allHulls)
662 {
663 totalVertices += 4; // add four for the vertex count and centroid
664 totalVertices += hullVerts.Count * 3; // one vertex is three dimensions
665 }
666 float[] convHulls = new float[totalVertices];
667
668 convHulls[0] = (float)hullCount;
669 int jj = 1;
670 foreach (List<OMV.Vector3> hullVerts in allHulls)
671 {
672 convHulls[jj + 0] = hullVerts.Count;
673 convHulls[jj + 1] = 0f; // centroid x,y,z
674 convHulls[jj + 2] = 0f;
675 convHulls[jj + 3] = 0f;
676 jj += 4;
677 foreach (OMV.Vector3 oneVert in hullVerts)
678 {
679 convHulls[jj + 0] = oneVert.X;
680 convHulls[jj + 1] = oneVert.Y;
681 convHulls[jj + 2] = oneVert.Z;
682 jj += 3;
683 }
684 }
685
686 // create the hull data structure in Bullet
687 newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
688
689 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,hulls={1},totVert={2},shape={3}",
690 prim.LocalID, hullCount, totalVertices, newShape);
691 }
692
693 // If no hull specified in the asset and we should use Bullet's HACD approximation...
694 if (!newShape.HasPhysicalShape && BSParam.ShouldUseBulletHACD)
695 {
696 // Build the hull shape from an existing mesh shape.
697 // The mesh should have already been created in Bullet.
698 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,entry", prim.LocalID);
699 BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim);
700
701 if (meshShape.physShapeInfo.HasPhysicalShape)
702 {
703 HACDParams parms;
704 parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
705 parms.minClusters = BSParam.BHullMinClusters;
706 parms.compacityWeight = BSParam.BHullCompacityWeight;
707 parms.volumeWeight = BSParam.BHullVolumeWeight;
708 parms.concavity = BSParam.BHullConcavity;
709 parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
710 parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
711 parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
712 parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
713
714 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
715 newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
716 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,shape={1}", prim.LocalID, newShape);
717
718 // Now done with the mesh shape.
719 meshShape.Dereference(physicsScene);
720 }
721 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
722 }
723
724 // If no other hull specifications, use our HACD hull approximation.
725 if (!newShape.HasPhysicalShape && meshData != null)
726 {
727 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
728 {
729 // Release the fetched asset data once it has been used.
730 pbs.SculptData = new byte[0];
731 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
732 }
733
734 int[] indices = meshData.getIndexListAsInt();
735 List<OMV.Vector3> vertices = meshData.getVertexList();
736
737 //format conversion from IMesh format to DecompDesc format
738 List<int> convIndices = new List<int>();
739 List<float3> convVertices = new List<float3>();
740 for (int ii = 0; ii < indices.GetLength(0); ii++)
741 {
742 convIndices.Add(indices[ii]);
743 }
744 foreach (OMV.Vector3 vv in vertices)
745 {
746 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
747 }
748
749 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
750 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
751 {
752 // Simple primitive shapes we know are convex so they are better implemented with
753 // fewer hulls.
754 // Check for simple shape (prim without cuts) and reduce split parameter if so.
755 if (BSShapeCollection.PrimHasNoCuts(pbs))
756 {
757 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
758 }
759 }
760
761 // setup and do convex hull conversion
762 m_hulls = new List<ConvexResult>();
763 DecompDesc dcomp = new DecompDesc();
764 dcomp.mIndices = convIndices;
765 dcomp.mVertices = convVertices;
766 dcomp.mDepth = maxDepthSplit;
767 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
768 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
769 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
770 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
771 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
772 // create the hull into the _hulls variable
773 convexBuilder.process(dcomp);
774
775 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
776 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
777
778 // Convert the vertices and indices for passing to unmanaged.
779 // The hull information is passed as a large floating point array.
780 // The format is:
781 // convHulls[0] = number of hulls
782 // convHulls[1] = number of vertices in first hull
783 // convHulls[2] = hull centroid X coordinate
784 // convHulls[3] = hull centroid Y coordinate
785 // convHulls[4] = hull centroid Z coordinate
786 // convHulls[5] = first hull vertex X
787 // convHulls[6] = first hull vertex Y
788 // convHulls[7] = first hull vertex Z
789 // convHulls[8] = second hull vertex X
790 // ...
791 // convHulls[n] = number of vertices in second hull
792 // convHulls[n+1] = second hull centroid X coordinate
793 // ...
794 //
795 // TODO: is is very inefficient. Someday change the convex hull generator to return
796 // data structures that do not need to be converted in order to pass to Bullet.
797 // And maybe put the values directly into pinned memory rather than marshaling.
798 int hullCount = m_hulls.Count;
799 int totalVertices = 1; // include one for the count of the hulls
800 foreach (ConvexResult cr in m_hulls)
801 {
802 totalVertices += 4; // add four for the vertex count and centroid
803 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
804 }
805 float[] convHulls = new float[totalVertices];
806
807 convHulls[0] = (float)hullCount;
808 int jj = 1;
809 foreach (ConvexResult cr in m_hulls)
810 {
811 // copy vertices for index access
812 float3[] verts = new float3[cr.HullVertices.Count];
813 int kk = 0;
814 foreach (float3 ff in cr.HullVertices)
815 {
816 verts[kk++] = ff;
817 }
818
819 // add to the array one hull's worth of data
820 convHulls[jj++] = cr.HullIndices.Count;
821 convHulls[jj++] = 0f; // centroid x,y,z
822 convHulls[jj++] = 0f;
823 convHulls[jj++] = 0f;
824 foreach (int ind in cr.HullIndices)
825 {
826 convHulls[jj++] = verts[ind].x;
827 convHulls[jj++] = verts[ind].y;
828 convHulls[jj++] = verts[ind].z;
829 }
830 }
831 // create the hull data structure in Bullet
832 newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
833 }
834 newShape.shapeKey = newHullKey;
835 return newShape;
836 }
837 // Callback from convex hull creater with a newly created hull.
838 // Just add it to our collection of hulls for this shape.
839 private void HullReturn(ConvexResult result)
840 {
841 m_hulls.Add(result);
842 return;
843 }
844 // Loop through all the known hulls and return the description based on the physical address.
845 public static bool TryGetHullByPtr(BulletShape pShape, out BSShapeHull outHull)
846 {
847 bool ret = false;
848 BSShapeHull foundDesc = null;
849 lock (Hulls)
850 {
851 foreach (BSShapeHull sh in Hulls.Values)
852 {
853 if (sh.physShapeInfo.ReferenceSame(pShape))
854 {
855 foundDesc = sh;
856 ret = true;
857 break;
858 }
859
860 }
861 }
862 outHull = foundDesc;
863 return ret;
864 }
204} 865}
205 866
867// ============================================================================================================
206public class BSShapeCompound : BSShape 868public class BSShapeCompound : BSShape
207{ 869{
208 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; 870 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
209 public BSShapeCompound() : base() 871 public static Dictionary<string, BSShapeCompound> CompoundShapes = new Dictionary<string, BSShapeCompound>();
872
873 public BSShapeCompound(BulletShape pShape) : base(pShape)
210 { 874 {
211 } 875 }
212 public static BSShape GetReference(BSPhysObject prim) 876 public static BSShape GetReference(BSScene physicsScene)
213 { 877 {
214 return new BSShapeNull(); 878 // Base compound shapes are not shared so this returns a raw shape.
879 // A built compound shape can be reused in linksets.
880 BSShapeCompound ret = new BSShapeCompound(CreatePhysicalCompoundShape(physicsScene));
881 CompoundShapes.Add(ret.AddrString, ret);
882 return ret;
883 }
884 public override BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
885 {
886 // Calling this reference means we want another handle to an existing compound shape
887 // (usually linksets) so return this copy.
888 IncrementReference();
889 return this;
890 }
891 // Dereferencing a compound shape releases the hold on all the child shapes.
892 public override void Dereference(BSScene physicsScene)
893 {
894 lock (physShapeInfo)
895 {
896 this.DecrementReference();
897 physicsScene.DetailLog("{0},BSShapeCompound.Dereference,shape={1}", BSScene.DetailLogZero, this);
898 if (referenceCount <= 0)
899 {
900 if (!physicsScene.PE.IsCompound(physShapeInfo))
901 {
902 // Failed the sanity check!!
903 physicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
904 LogHeader, physShapeInfo.shapeType, physShapeInfo.AddrString);
905 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
906 BSScene.DetailLogZero, physShapeInfo.shapeType, physShapeInfo.AddrString);
907 return;
908 }
909
910 int numChildren = physicsScene.PE.GetNumberOfCompoundChildren(physShapeInfo);
911 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}",
912 BSScene.DetailLogZero, physShapeInfo, numChildren);
913
914 // Loop through all the children dereferencing each.
915 for (int ii = numChildren - 1; ii >= 0; ii--)
916 {
917 BulletShape childShape = physicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(physShapeInfo, ii);
918 DereferenceAnonCollisionShape(physicsScene, childShape);
919 }
920
921 lock (CompoundShapes)
922 CompoundShapes.Remove(physShapeInfo.AddrString);
923 physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
924 }
925 }
926 }
927 public static bool TryGetCompoundByPtr(BulletShape pShape, out BSShapeCompound outCompound)
928 {
929 lock (CompoundShapes)
930 {
931 string addr = pShape.AddrString;
932 return CompoundShapes.TryGetValue(addr, out outCompound);
933 }
934 }
935 private static BulletShape CreatePhysicalCompoundShape(BSScene physicsScene)
936 {
937 BulletShape cShape = physicsScene.PE.CreateCompoundShape(physicsScene.World, false);
938 return cShape;
939 }
940 // Sometimes we have a pointer to a collision shape but don't know what type it is.
941 // Figure out type and call the correct dereference routine.
942 // Called at taint-time.
943 private void DereferenceAnonCollisionShape(BSScene physicsScene, BulletShape pShape)
944 {
945 // TODO: figure a better way to go through all the shape types and find a possible instance.
946 physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,shape={1}",
947 BSScene.DetailLogZero, pShape);
948 BSShapeMesh meshDesc;
949 if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc))
950 {
951 meshDesc.Dereference(physicsScene);
952 // physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,foundMesh,shape={1}", BSScene.DetailLogZero, pShape);
953 }
954 else
955 {
956 BSShapeHull hullDesc;
957 if (BSShapeHull.TryGetHullByPtr(pShape, out hullDesc))
958 {
959 hullDesc.Dereference(physicsScene);
960 // physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,foundHull,shape={1}", BSScene.DetailLogZero, pShape);
961 }
962 else
963 {
964 BSShapeConvexHull chullDesc;
965 if (BSShapeConvexHull.TryGetConvexHullByPtr(pShape, out chullDesc))
966 {
967 chullDesc.Dereference(physicsScene);
968 // physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,foundConvexHull,shape={1}", BSScene.DetailLogZero, pShape);
969 }
970 else
971 {
972 BSShapeGImpact gImpactDesc;
973 if (BSShapeGImpact.TryGetGImpactByPtr(pShape, out gImpactDesc))
974 {
975 gImpactDesc.Dereference(physicsScene);
976 // physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,foundgImpact,shape={1}", BSScene.DetailLogZero, pShape);
977 }
978 else
979 {
980 // Didn't find it in the lists of specific types. It could be compound.
981 BSShapeCompound compoundDesc;
982 if (BSShapeCompound.TryGetCompoundByPtr(pShape, out compoundDesc))
983 {
984 compoundDesc.Dereference(physicsScene);
985 // physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,recursiveCompoundShape,shape={1}", BSScene.DetailLogZero, pShape);
986 }
987 else
988 {
989 // If none of the above, maybe it is a simple native shape.
990 if (physicsScene.PE.IsNativeShape(pShape))
991 {
992 // physicsScene.DetailLog("{0},BSShapeCompound.DereferenceAnonCollisionShape,assumingNative,shape={1}", BSScene.DetailLogZero, pShape);
993 BSShapeNative nativeShape = new BSShapeNative(pShape);
994 nativeShape.Dereference(physicsScene);
995 }
996 }
997 }
998 }
999 }
1000 }
1001 }
1002}
1003
1004// ============================================================================================================
1005public class BSShapeConvexHull : BSShape
1006{
1007 private static string LogHeader = "[BULLETSIM SHAPE CONVEX HULL]";
1008 public static Dictionary<System.UInt64, BSShapeConvexHull> ConvexHulls = new Dictionary<System.UInt64, BSShapeConvexHull>();
1009
1010 public BSShapeConvexHull(BulletShape pShape) : base(pShape)
1011 {
1012 }
1013 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
1014 {
1015 float lod;
1016 System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
1017
1018 physicsScene.DetailLog("{0},BSShapeConvexHull,getReference,newKey={1},size={2},lod={3}",
1019 prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);
1020
1021 BSShapeConvexHull retConvexHull = null;
1022 lock (ConvexHulls)
1023 {
1024 if (ConvexHulls.TryGetValue(newMeshKey, out retConvexHull))
1025 {
1026 // The mesh has already been created. Return a new reference to same.
1027 retConvexHull.IncrementReference();
1028 }
1029 else
1030 {
1031 retConvexHull = new BSShapeConvexHull(new BulletShape());
1032 BulletShape convexShape = null;
1033
1034 // Get a handle to a mesh to build the hull from
1035 BSShape baseMesh = BSShapeMesh.GetReference(physicsScene, false /* forceRebuild */, prim);
1036 if (baseMesh.physShapeInfo.isNativeShape)
1037 {
1038 // We get here if the mesh was not creatable. Could be waiting for an asset from the disk.
1039 // In the short term, we return the native shape and a later ForceBodyShapeRebuild should
1040 // get back to this code with a buildable mesh.
1041 // TODO: not sure the temp native shape is freed when the mesh is rebuilt. When does this get freed?
1042 convexShape = baseMesh.physShapeInfo;
1043 }
1044 else
1045 {
1046 convexShape = physicsScene.PE.BuildConvexHullShapeFromMesh(physicsScene.World, baseMesh.physShapeInfo);
1047 convexShape.shapeKey = newMeshKey;
1048 ConvexHulls.Add(convexShape.shapeKey, retConvexHull);
1049 physicsScene.DetailLog("{0},BSShapeConvexHull.GetReference,addingNewlyCreatedShape,shape={1}",
1050 BSScene.DetailLogZero, convexShape);
1051 }
1052
1053 // Done with the base mesh
1054 baseMesh.Dereference(physicsScene);
1055
1056 retConvexHull.physShapeInfo = convexShape;
1057 }
1058 }
1059 return retConvexHull;
1060 }
1061 public override BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
1062 {
1063 // Calling this reference means we want another handle to an existing shape
1064 // (usually linksets) so return this copy.
1065 IncrementReference();
1066 return this;
1067 }
1068 // Dereferencing a compound shape releases the hold on all the child shapes.
1069 public override void Dereference(BSScene physicsScene)
1070 {
1071 lock (ConvexHulls)
1072 {
1073 this.DecrementReference();
1074 physicsScene.DetailLog("{0},BSShapeConvexHull.Dereference,shape={1}", BSScene.DetailLogZero, this);
1075 // TODO: schedule aging and destruction of unused meshes.
1076 }
1077 }
1078 // Loop through all the known hulls and return the description based on the physical address.
1079 public static bool TryGetConvexHullByPtr(BulletShape pShape, out BSShapeConvexHull outHull)
1080 {
1081 bool ret = false;
1082 BSShapeConvexHull foundDesc = null;
1083 lock (ConvexHulls)
1084 {
1085 foreach (BSShapeConvexHull sh in ConvexHulls.Values)
1086 {
1087 if (sh.physShapeInfo.ReferenceSame(pShape))
1088 {
1089 foundDesc = sh;
1090 ret = true;
1091 break;
1092 }
1093
1094 }
1095 }
1096 outHull = foundDesc;
1097 return ret;
1098 }
1099}
1100// ============================================================================================================
1101public class BSShapeGImpact : BSShape
1102{
1103 private static string LogHeader = "[BULLETSIM SHAPE GIMPACT]";
1104 public static Dictionary<System.UInt64, BSShapeGImpact> GImpacts = new Dictionary<System.UInt64, BSShapeGImpact>();
1105
1106 public BSShapeGImpact(BulletShape pShape) : base(pShape)
1107 {
1108 }
1109 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
1110 {
1111 float lod;
1112 System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
1113
1114 physicsScene.DetailLog("{0},BSShapeGImpact,getReference,newKey={1},size={2},lod={3}",
1115 prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);
1116
1117 BSShapeGImpact retGImpact = null;
1118 lock (GImpacts)
1119 {
1120 if (GImpacts.TryGetValue(newMeshKey, out retGImpact))
1121 {
1122 // The mesh has already been created. Return a new reference to same.
1123 retGImpact.IncrementReference();
1124 }
1125 else
1126 {
1127 retGImpact = new BSShapeGImpact(new BulletShape());
1128 BulletShape newShape = retGImpact.CreatePhysicalGImpact(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
1129
1130 // Check to see if mesh was created (might require an asset).
1131 newShape = VerifyMeshCreated(physicsScene, newShape, prim);
1132 newShape.shapeKey = newMeshKey;
1133 if (!newShape.isNativeShape
1134 || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedMeshing
1135 || prim.PrimAssetState == BSPhysObject.PrimAssetCondition.FailedAssetFetch)
1136 {
1137 // If a mesh was what was created, remember the built shape for later sharing.
1138 // Also note that if meshing failed we put it in the mesh list as there is nothing
1139 // else to do about the mesh.
1140 GImpacts.Add(newMeshKey, retGImpact);
1141 }
1142
1143 retGImpact.physShapeInfo = newShape;
1144 }
1145 }
1146 return retGImpact;
1147 }
1148
1149 private BulletShape CreatePhysicalGImpact(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
1150 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
1151 {
1152 return BSShapeMesh.CreatePhysicalMeshShape(physicsScene, prim, newMeshKey, pbs, size, lod,
1153 (w, iC, i, vC, v) => physicsScene.PE.CreateGImpactShape(w, iC, i, vC, v) );
1154 }
1155
1156 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
1157 {
1158 BSShape ret = null;
1159 // If the underlying shape is native, the actual shape has not been build (waiting for asset)
1160 // and we must create a copy of the native shape since they are never shared.
1161 if (physShapeInfo.HasPhysicalShape && physShapeInfo.isNativeShape)
1162 {
1163 // TODO: decide when the native shapes should be freed. Check in Dereference?
1164 ret = BSShapeNative.GetReference(pPhysicsScene, pPrim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
1165 }
1166 else
1167 {
1168 // Another reference to this shape is just counted.
1169 IncrementReference();
1170 ret = this;
1171 }
1172 return ret;
1173 }
1174 // Dereferencing a compound shape releases the hold on all the child shapes.
1175 public override void Dereference(BSScene physicsScene)
1176 {
1177 lock (GImpacts)
1178 {
1179 this.DecrementReference();
1180 physicsScene.DetailLog("{0},BSShapeGImpact.Dereference,shape={1}", BSScene.DetailLogZero, this);
1181 // TODO: schedule aging and destruction of unused meshes.
1182 }
1183 }
1184 // Loop through all the known hulls and return the description based on the physical address.
1185 public static bool TryGetGImpactByPtr(BulletShape pShape, out BSShapeGImpact outHull)
1186 {
1187 bool ret = false;
1188 BSShapeGImpact foundDesc = null;
1189 lock (GImpacts)
1190 {
1191 foreach (BSShapeGImpact sh in GImpacts.Values)
1192 {
1193 if (sh.physShapeInfo.ReferenceSame(pShape))
1194 {
1195 foundDesc = sh;
1196 ret = true;
1197 break;
1198 }
1199
1200 }
1201 }
1202 outHull = foundDesc;
1203 return ret;
215 } 1204 }
216 public override void Dereference(BSScene physicsScene) { }
217} 1205}
218 1206
1207// ============================================================================================================
219public class BSShapeAvatar : BSShape 1208public class BSShapeAvatar : BSShape
220{ 1209{
221 private static string LogHeader = "[BULLETSIM SHAPE AVATAR]"; 1210 private static string LogHeader = "[BULLETSIM SHAPE AVATAR]";
222 public BSShapeAvatar() : base() 1211 public BSShapeAvatar() : base()
223 { 1212 {
224 } 1213 }
225 public static BSShape GetReference(BSPhysObject prim) 1214 public static BSShape GetReference(BSPhysObject prim)
226 { 1215 {
1216 return new BSShapeNull();
1217 }
1218 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
1219 {
227 return new BSShapeNull(); 1220 return new BSShapeNull();
228 } 1221 }
229 public override void Dereference(BSScene physicsScene) { } 1222 public override void Dereference(BSScene physicsScene) { }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
index e4fecc3..8888d6d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
@@ -68,7 +68,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
68 68
69 // This minCoords and maxCoords passed in give the size of the terrain (min and max Z 69 // This minCoords and maxCoords passed in give the size of the terrain (min and max Z
70 // are the high and low points of the heightmap). 70 // are the high and low points of the heightmap).
71 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, 71 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
72 Vector3 minCoords, Vector3 maxCoords) 72 Vector3 minCoords, Vector3 maxCoords)
73 : base(physicsScene, regionBase, id) 73 : base(physicsScene, regionBase, id)
74 { 74 {
@@ -92,7 +92,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
92 private void BuildHeightmapTerrain() 92 private void BuildHeightmapTerrain()
93 { 93 {
94 // Create the terrain shape from the mapInfo 94 // Create the terrain shape from the mapInfo
95 m_mapInfo.terrainShape = PhysicsScene.PE.CreateTerrainShape( m_mapInfo.ID, 95 m_mapInfo.terrainShape = m_physicsScene.PE.CreateTerrainShape( m_mapInfo.ID,
96 new Vector3(m_mapInfo.sizeX, m_mapInfo.sizeY, 0), m_mapInfo.minZ, m_mapInfo.maxZ, 96 new Vector3(m_mapInfo.sizeX, m_mapInfo.sizeY, 0), m_mapInfo.minZ, m_mapInfo.maxZ,
97 m_mapInfo.heightMap, 1f, BSParam.TerrainCollisionMargin); 97 m_mapInfo.heightMap, 1f, BSParam.TerrainCollisionMargin);
98 98
@@ -103,26 +103,25 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
103 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); 103 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f);
104 centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f); 104 centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f);
105 105
106 m_mapInfo.terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_mapInfo.terrainShape, 106 m_mapInfo.terrainBody = m_physicsScene.PE.CreateBodyWithDefaultMotionState(m_mapInfo.terrainShape,
107 m_mapInfo.ID, centerPos, Quaternion.Identity); 107 m_mapInfo.ID, centerPos, Quaternion.Identity);
108 108
109 // Set current terrain attributes 109 // Set current terrain attributes
110 PhysicsScene.PE.SetFriction(m_mapInfo.terrainBody, BSParam.TerrainFriction); 110 m_physicsScene.PE.SetFriction(m_mapInfo.terrainBody, BSParam.TerrainFriction);
111 PhysicsScene.PE.SetHitFraction(m_mapInfo.terrainBody, BSParam.TerrainHitFraction); 111 m_physicsScene.PE.SetHitFraction(m_mapInfo.terrainBody, BSParam.TerrainHitFraction);
112 PhysicsScene.PE.SetRestitution(m_mapInfo.terrainBody, BSParam.TerrainRestitution); 112 m_physicsScene.PE.SetRestitution(m_mapInfo.terrainBody, BSParam.TerrainRestitution);
113 PhysicsScene.PE.SetCollisionFlags(m_mapInfo.terrainBody, CollisionFlags.CF_STATIC_OBJECT); 113 m_physicsScene.PE.SetCollisionFlags(m_mapInfo.terrainBody, CollisionFlags.CF_STATIC_OBJECT);
114
115 m_mapInfo.terrainBody.collisionType = CollisionType.Terrain;
114 116
115 // Return the new terrain to the world of physical objects 117 // Return the new terrain to the world of physical objects
116 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_mapInfo.terrainBody); 118 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_mapInfo.terrainBody);
117 119
118 // redo its bounding box now that it is in the world 120 // redo its bounding box now that it is in the world
119 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_mapInfo.terrainBody); 121 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_mapInfo.terrainBody);
120
121 m_mapInfo.terrainBody.collisionType = CollisionType.Terrain;
122 m_mapInfo.terrainBody.ApplyCollisionMask(PhysicsScene);
123 122
124 // Make it so the terrain will not move or be considered for movement. 123 // Make it so the terrain will not move or be considered for movement.
125 PhysicsScene.PE.ForceActivationState(m_mapInfo.terrainBody, ActivationState.DISABLE_SIMULATION); 124 m_physicsScene.PE.ForceActivationState(m_mapInfo.terrainBody, ActivationState.DISABLE_SIMULATION);
126 125
127 return; 126 return;
128 } 127 }
@@ -134,9 +133,9 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
134 { 133 {
135 if (m_mapInfo.terrainBody.HasPhysicalBody) 134 if (m_mapInfo.terrainBody.HasPhysicalBody)
136 { 135 {
137 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_mapInfo.terrainBody); 136 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_mapInfo.terrainBody);
138 // Frees both the body and the shape. 137 // Frees both the body and the shape.
139 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_mapInfo.terrainBody); 138 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_mapInfo.terrainBody);
140 } 139 }
141 } 140 }
142 m_mapInfo = null; 141 m_mapInfo = null;
@@ -155,7 +154,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
155 catch 154 catch
156 { 155 {
157 // Sometimes they give us wonky values of X and Y. Give a warning and return something. 156 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
158 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", 157 m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
159 LogHeader, m_mapInfo.terrainRegionBase, pos); 158 LogHeader, m_mapInfo.terrainRegionBase, pos);
160 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; 159 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
161 } 160 }
@@ -165,7 +164,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
165 // The passed position is relative to the base of the region. 164 // The passed position is relative to the base of the region.
166 public override float GetWaterLevelAtXYZ(Vector3 pos) 165 public override float GetWaterLevelAtXYZ(Vector3 pos)
167 { 166 {
168 return PhysicsScene.SimpleWaterLevel; 167 return m_physicsScene.SimpleWaterLevel;
169 } 168 }
170} 169}
171} 170}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index cd15850..441d2d3 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -50,14 +50,14 @@ public abstract class BSTerrainPhys : IDisposable
50 Mesh = 1 50 Mesh = 1
51 } 51 }
52 52
53 public BSScene PhysicsScene { get; private set; } 53 protected BSScene m_physicsScene { get; private set; }
54 // Base of the region in world coordinates. Coordinates inside the region are relative to this. 54 // Base of the region in world coordinates. Coordinates inside the region are relative to this.
55 public Vector3 TerrainBase { get; private set; } 55 public Vector3 TerrainBase { get; private set; }
56 public uint ID { get; private set; } 56 public uint ID { get; private set; }
57 57
58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id) 58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id)
59 { 59 {
60 PhysicsScene = physicsScene; 60 m_physicsScene = physicsScene;
61 TerrainBase = regionBase; 61 TerrainBase = regionBase;
62 ID = id; 62 ID = id;
63 } 63 }
@@ -86,7 +86,7 @@ public sealed class BSTerrainManager : IDisposable
86 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 86 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
87 87
88 // The scene that I am part of 88 // The scene that I am part of
89 private BSScene PhysicsScene { get; set; } 89 private BSScene m_physicsScene { get; set; }
90 90
91 // The ground plane created to keep thing from falling to infinity. 91 // The ground plane created to keep thing from falling to infinity.
92 private BulletBody m_groundPlane; 92 private BulletBody m_groundPlane;
@@ -113,7 +113,7 @@ public sealed class BSTerrainManager : IDisposable
113 113
114 public BSTerrainManager(BSScene physicsScene) 114 public BSTerrainManager(BSScene physicsScene)
115 { 115 {
116 PhysicsScene = physicsScene; 116 m_physicsScene = physicsScene;
117 m_terrains = new Dictionary<Vector3,BSTerrainPhys>(); 117 m_terrains = new Dictionary<Vector3,BSTerrainPhys>();
118 118
119 // Assume one region of default size 119 // Assume one region of default size
@@ -132,21 +132,22 @@ public sealed class BSTerrainManager : IDisposable
132 // safe to call Bullet in real time. We hope no one is moving prims around yet. 132 // safe to call Bullet in real time. We hope no one is moving prims around yet.
133 public void CreateInitialGroundPlaneAndTerrain() 133 public void CreateInitialGroundPlaneAndTerrain()
134 { 134 {
135 DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName); 135 DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, m_physicsScene.RegionName);
136 // The ground plane is here to catch things that are trying to drop to negative infinity 136 // The ground plane is here to catch things that are trying to drop to negative infinity
137 BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin); 137 BulletShape groundPlaneShape = m_physicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin);
138 m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape, 138 m_groundPlane = m_physicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape,
139 BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity); 139 BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity);
140 140
141 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_groundPlane);
142 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_groundPlane);
143 // Ground plane does not move
144 PhysicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION);
145 // Everything collides with the ground plane. 141 // Everything collides with the ground plane.
146 m_groundPlane.collisionType = CollisionType.Groundplane; 142 m_groundPlane.collisionType = CollisionType.Groundplane;
147 m_groundPlane.ApplyCollisionMask(PhysicsScene);
148 143
149 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); 144 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_groundPlane);
145 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_groundPlane);
146
147 // Ground plane does not move
148 m_physicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION);
149
150 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(m_physicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
150 lock (m_terrains) 151 lock (m_terrains)
151 { 152 {
152 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. 153 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
@@ -157,12 +158,12 @@ public sealed class BSTerrainManager : IDisposable
157 // Release all the terrain structures we might have allocated 158 // Release all the terrain structures we might have allocated
158 public void ReleaseGroundPlaneAndTerrain() 159 public void ReleaseGroundPlaneAndTerrain()
159 { 160 {
160 DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName); 161 DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, m_physicsScene.RegionName);
161 if (m_groundPlane.HasPhysicalBody) 162 if (m_groundPlane.HasPhysicalBody)
162 { 163 {
163 if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane)) 164 if (m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_groundPlane))
164 { 165 {
165 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_groundPlane); 166 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_groundPlane);
166 } 167 }
167 m_groundPlane.Clear(); 168 m_groundPlane.Clear();
168 } 169 }
@@ -188,7 +189,7 @@ public sealed class BSTerrainManager : IDisposable
188 float[] localHeightMap = heightMap; 189 float[] localHeightMap = heightMap;
189 // If there are multiple requests for changes to the same terrain between ticks, 190 // If there are multiple requests for changes to the same terrain between ticks,
190 // only do that last one. 191 // only do that last one.
191 PhysicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate() 192 m_physicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate()
192 { 193 {
193 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) 194 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null)
194 { 195 {
@@ -213,13 +214,13 @@ public sealed class BSTerrainManager : IDisposable
213 }); 214 });
214 } 215 }
215 216
216 // Another region is calling this region passing a terrain. 217 // Another region is calling this region and passing a terrain.
217 // A region that is not the mega-region root will pass its terrain to the root region so the root region 218 // A region that is not the mega-region root will pass its terrain to the root region so the root region
218 // physics engine will have all the terrains. 219 // physics engine will have all the terrains.
219 private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) 220 private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
220 { 221 {
221 // Since we are called by another region's thread, the action must be rescheduled onto our processing thread. 222 // Since we are called by another region's thread, the action must be rescheduled onto our processing thread.
222 PhysicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + m_worldOffset.ToString(), 0, delegate() 223 m_physicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + minCoords.ToString(), id, delegate()
223 { 224 {
224 UpdateTerrain(id, heightMap, minCoords, maxCoords); 225 UpdateTerrain(id, heightMap, minCoords, maxCoords);
225 }); 226 });
@@ -306,7 +307,7 @@ public sealed class BSTerrainManager : IDisposable
306 newTerrainID = ++m_terrainCount; 307 newTerrainID = ++m_terrainCount;
307 308
308 DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}", 309 DetailLog("{0},BSTerrainManager.UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
309 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); 310 BSScene.DetailLogZero, newTerrainID, minCoords, maxCoords);
310 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords); 311 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
311 m_terrains.Add(terrainRegionBase, newTerrainPhys); 312 m_terrains.Add(terrainRegionBase, newTerrainPhys);
312 313
@@ -318,26 +319,26 @@ public sealed class BSTerrainManager : IDisposable
318 // TODO: redo terrain implementation selection to allow other base types than heightMap. 319 // TODO: redo terrain implementation selection to allow other base types than heightMap.
319 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) 320 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
320 { 321 {
321 PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", 322 m_physicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}",
322 LogHeader, PhysicsScene.RegionName, terrainRegionBase, 323 LogHeader, m_physicsScene.RegionName, terrainRegionBase,
323 (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation); 324 (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation);
324 BSTerrainPhys newTerrainPhys = null; 325 BSTerrainPhys newTerrainPhys = null;
325 switch ((int)BSParam.TerrainImplementation) 326 switch ((int)BSParam.TerrainImplementation)
326 { 327 {
327 case (int)BSTerrainPhys.TerrainImplementation.Heightmap: 328 case (int)BSTerrainPhys.TerrainImplementation.Heightmap:
328 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, 329 newTerrainPhys = new BSTerrainHeightmap(m_physicsScene, terrainRegionBase, id,
329 heightMap, minCoords, maxCoords); 330 heightMap, minCoords, maxCoords);
330 break; 331 break;
331 case (int)BSTerrainPhys.TerrainImplementation.Mesh: 332 case (int)BSTerrainPhys.TerrainImplementation.Mesh:
332 newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, 333 newTerrainPhys = new BSTerrainMesh(m_physicsScene, terrainRegionBase, id,
333 heightMap, minCoords, maxCoords); 334 heightMap, minCoords, maxCoords);
334 break; 335 break;
335 default: 336 default:
336 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", 337 m_physicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}",
337 LogHeader, 338 LogHeader,
338 (int)BSParam.TerrainImplementation, 339 (int)BSParam.TerrainImplementation,
339 BSParam.TerrainImplementation, 340 BSParam.TerrainImplementation,
340 PhysicsScene.RegionName, terrainRegionBase); 341 m_physicsScene.RegionName, terrainRegionBase);
341 break; 342 break;
342 } 343 }
343 return newTerrainPhys; 344 return newTerrainPhys;
@@ -354,6 +355,8 @@ public sealed class BSTerrainManager : IDisposable
354 // Return a new position that is over known terrain if the position is outside our terrain. 355 // Return a new position that is over known terrain if the position is outside our terrain.
355 public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos) 356 public Vector3 ClampPositionIntoKnownTerrain(Vector3 pPos)
356 { 357 {
358 float edgeEpsilon = 0.1f;
359
357 Vector3 ret = pPos; 360 Vector3 ret = pPos;
358 361
359 // First, base addresses are never negative so correct for that possible problem. 362 // First, base addresses are never negative so correct for that possible problem.
@@ -378,10 +381,19 @@ public sealed class BSTerrainManager : IDisposable
378 // NOTE that GetTerrainPhysicalAtXYZ will set 'terrainBaseXYZ' to the base of the unfound region. 381 // NOTE that GetTerrainPhysicalAtXYZ will set 'terrainBaseXYZ' to the base of the unfound region.
379 382
380 // Must be off the top of a region. Find an adjacent region to move into. 383 // Must be off the top of a region. Find an adjacent region to move into.
384 // The returned terrain is always 'lower'. That is, closer to <0,0>.
381 Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ); 385 Vector3 adjacentTerrainBase = FindAdjacentTerrainBase(terrainBaseXYZ);
382 386
383 ret.X = Math.Min(ret.X, adjacentTerrainBase.X + (ret.X % DefaultRegionSize.X)); 387 if (adjacentTerrainBase.X < terrainBaseXYZ.X)
384 ret.Y = Math.Min(ret.Y, adjacentTerrainBase.Y + (ret.X % DefaultRegionSize.Y)); 388 {
389 // moving down into a new region in the X dimension. New position will be the max in the new base.
390 ret.X = adjacentTerrainBase.X + DefaultRegionSize.X - edgeEpsilon;
391 }
392 if (adjacentTerrainBase.Y < terrainBaseXYZ.Y)
393 {
394 // moving down into a new region in the X dimension. New position will be the max in the new base.
395 ret.Y = adjacentTerrainBase.Y + DefaultRegionSize.Y - edgeEpsilon;
396 }
385 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}", 397 DetailLog("{0},BSTerrainManager.ClampPositionToKnownTerrain,findingAdjacentRegion,adjacentRegBase={1},oldPos={2},newPos={3}",
386 BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret); 398 BSScene.DetailLogZero, adjacentTerrainBase, pPos, ret);
387 399
@@ -429,8 +441,8 @@ public sealed class BSTerrainManager : IDisposable
429 } 441 }
430 else 442 else
431 { 443 {
432 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", 444 m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
433 LogHeader, PhysicsScene.RegionName, tX, tY); 445 LogHeader, m_physicsScene.RegionName, tX, tY);
434 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}", 446 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}",
435 BSScene.DetailLogZero, pos, terrainBaseXYZ); 447 BSScene.DetailLogZero, pos, terrainBaseXYZ);
436 } 448 }
@@ -451,8 +463,8 @@ public sealed class BSTerrainManager : IDisposable
451 } 463 }
452 else 464 else
453 { 465 {
454 PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}", 466 m_physicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}",
455 LogHeader, PhysicsScene.RegionName, pos, terrainBaseXYZ, ret); 467 LogHeader, m_physicsScene.RegionName, pos, terrainBaseXYZ, ret);
456 } 468 }
457 return ret; 469 return ret;
458 } 470 }
@@ -564,7 +576,7 @@ public sealed class BSTerrainManager : IDisposable
564 576
565 private void DetailLog(string msg, params Object[] args) 577 private void DetailLog(string msg, params Object[] args)
566 { 578 {
567 PhysicsScene.PhysicsLogging.Write(msg, args); 579 m_physicsScene.PhysicsLogging.Write(msg, args);
568 } 580 }
569} 581}
570} 582}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
index 2ce1513..e4ca098 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
@@ -51,7 +51,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
51 BulletShape m_terrainShape; 51 BulletShape m_terrainShape;
52 BulletBody m_terrainBody; 52 BulletBody m_terrainBody;
53 53
54 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) 54 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
55 : base(physicsScene, regionBase, id) 55 : base(physicsScene, regionBase, id)
56 { 56 {
57 } 57 }
@@ -62,7 +62,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
62 } 62 }
63 63
64 // Create terrain mesh from a heightmap. 64 // Create terrain mesh from a heightmap.
65 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, 65 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
66 Vector3 minCoords, Vector3 maxCoords) 66 Vector3 minCoords, Vector3 maxCoords)
67 : base(physicsScene, regionBase, id) 67 : base(physicsScene, regionBase, id)
68 { 68 {
@@ -80,7 +80,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
80 if (BSParam.TerrainMeshMagnification == 1) 80 if (BSParam.TerrainMeshMagnification == 1)
81 { 81 {
82 // If a magnification of one, use the old routine that is tried and true. 82 // If a magnification of one, use the old routine that is tried and true.
83 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, 83 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh(m_physicsScene,
84 initialMap, m_sizeX, m_sizeY, // input size 84 initialMap, m_sizeX, m_sizeY, // input size
85 Vector3.Zero, // base for mesh 85 Vector3.Zero, // base for mesh
86 out indicesCount, out indices, out verticesCount, out vertices); 86 out indicesCount, out indices, out verticesCount, out vertices);
@@ -88,7 +88,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
88 else 88 else
89 { 89 {
90 // Other magnifications use the newer routine 90 // Other magnifications use the newer routine
91 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh2(PhysicsScene, 91 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh2(m_physicsScene,
92 initialMap, m_sizeX, m_sizeY, // input size 92 initialMap, m_sizeX, m_sizeY, // input size
93 BSParam.TerrainMeshMagnification, 93 BSParam.TerrainMeshMagnification,
94 physicsScene.TerrainManager.DefaultRegionSize, 94 physicsScene.TerrainManager.DefaultRegionSize,
@@ -98,21 +98,21 @@ public sealed class BSTerrainMesh : BSTerrainPhys
98 if (!meshCreationSuccess) 98 if (!meshCreationSuccess)
99 { 99 {
100 // DISASTER!! 100 // DISASTER!!
101 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap,id={1}", BSScene.DetailLogZero, ID); 101 m_physicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap,id={1}", BSScene.DetailLogZero, ID);
102 PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase); 102 m_physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase);
103 // Something is very messed up and a crash is in our future. 103 // Something is very messed up and a crash is in our future.
104 return; 104 return;
105 } 105 }
106 106
107 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}", 107 m_physicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}",
108 BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length); 108 BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length);
109 109
110 m_terrainShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, indicesCount, indices, verticesCount, vertices); 110 m_terrainShape = m_physicsScene.PE.CreateMeshShape(m_physicsScene.World, indicesCount, indices, verticesCount, vertices);
111 if (!m_terrainShape.HasPhysicalShape) 111 if (!m_terrainShape.HasPhysicalShape)
112 { 112 {
113 // DISASTER!! 113 // DISASTER!!
114 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape,id={1}", BSScene.DetailLogZero, ID); 114 m_physicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape,id={1}", BSScene.DetailLogZero, ID);
115 PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); 115 m_physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
116 // Something is very messed up and a crash is in our future. 116 // Something is very messed up and a crash is in our future.
117 return; 117 return;
118 } 118 }
@@ -120,52 +120,52 @@ public sealed class BSTerrainMesh : BSTerrainPhys
120 Vector3 pos = regionBase; 120 Vector3 pos = regionBase;
121 Quaternion rot = Quaternion.Identity; 121 Quaternion rot = Quaternion.Identity;
122 122
123 m_terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot); 123 m_terrainBody = m_physicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot);
124 if (!m_terrainBody.HasPhysicalBody) 124 if (!m_terrainBody.HasPhysicalBody)
125 { 125 {
126 // DISASTER!! 126 // DISASTER!!
127 PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); 127 m_physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
128 // Something is very messed up and a crash is in our future. 128 // Something is very messed up and a crash is in our future.
129 return; 129 return;
130 } 130 }
131 physicsScene.PE.SetShapeCollisionMargin(m_terrainShape, BSParam.TerrainCollisionMargin); 131 physicsScene.PE.SetShapeCollisionMargin(m_terrainShape, BSParam.TerrainCollisionMargin);
132 132
133 // Set current terrain attributes 133 // Set current terrain attributes
134 PhysicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction); 134 m_physicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction);
135 PhysicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction); 135 m_physicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction);
136 PhysicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution); 136 m_physicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution);
137 PhysicsScene.PE.SetContactProcessingThreshold(m_terrainBody, BSParam.TerrainContactProcessingThreshold); 137 m_physicsScene.PE.SetContactProcessingThreshold(m_terrainBody, BSParam.TerrainContactProcessingThreshold);
138 PhysicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT); 138 m_physicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT);
139 139
140 // Static objects are not very massive. 140 // Static objects are not very massive.
141 PhysicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero); 141 m_physicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero);
142 142
143 // Put the new terrain to the world of physical objects 143 // Put the new terrain to the world of physical objects
144 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_terrainBody); 144 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_terrainBody);
145 145
146 // Redo its bounding box now that it is in the world 146 // Redo its bounding box now that it is in the world
147 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_terrainBody); 147 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_terrainBody);
148 148
149 m_terrainBody.collisionType = CollisionType.Terrain; 149 m_terrainBody.collisionType = CollisionType.Terrain;
150 m_terrainBody.ApplyCollisionMask(PhysicsScene); 150 m_terrainBody.ApplyCollisionMask(m_physicsScene);
151 151
152 if (BSParam.UseSingleSidedMeshes) 152 if (BSParam.UseSingleSidedMeshes)
153 { 153 {
154 PhysicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial,id={1}", BSScene.DetailLogZero, id); 154 m_physicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial,id={1}", BSScene.DetailLogZero, id);
155 PhysicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK); 155 m_physicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
156 } 156 }
157 157
158 // Make it so the terrain will not move or be considered for movement. 158 // Make it so the terrain will not move or be considered for movement.
159 PhysicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION); 159 m_physicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION);
160 } 160 }
161 161
162 public override void Dispose() 162 public override void Dispose()
163 { 163 {
164 if (m_terrainBody.HasPhysicalBody) 164 if (m_terrainBody.HasPhysicalBody)
165 { 165 {
166 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_terrainBody); 166 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_terrainBody);
167 // Frees both the body and the shape. 167 // Frees both the body and the shape.
168 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_terrainBody); 168 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_terrainBody);
169 m_terrainBody.Clear(); 169 m_terrainBody.Clear();
170 m_terrainShape.Clear(); 170 m_terrainShape.Clear();
171 } 171 }
@@ -185,7 +185,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
185 catch 185 catch
186 { 186 {
187 // Sometimes they give us wonky values of X and Y. Give a warning and return something. 187 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
188 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", 188 m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
189 LogHeader, TerrainBase, pos); 189 LogHeader, TerrainBase, pos);
190 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; 190 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
191 } 191 }
@@ -195,7 +195,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
195 // The passed position is relative to the base of the region. 195 // The passed position is relative to the base of the region.
196 public override float GetWaterLevelAtXYZ(Vector3 pos) 196 public override float GetWaterLevelAtXYZ(Vector3 pos)
197 { 197 {
198 return PhysicsScene.SimpleWaterLevel; 198 return m_physicsScene.SimpleWaterLevel;
199 } 199 }
200 200
201 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). 201 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
index 8012d91..971ff9f 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
@@ -104,11 +104,11 @@ public class BulletShape
104{ 104{
105 public BulletShape() 105 public BulletShape()
106 { 106 {
107 type = BSPhysicsShapeType.SHAPE_UNKNOWN; 107 shapeType = BSPhysicsShapeType.SHAPE_UNKNOWN;
108 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; 108 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
109 isNativeShape = false; 109 isNativeShape = false;
110 } 110 }
111 public BSPhysicsShapeType type; 111 public BSPhysicsShapeType shapeType;
112 public System.UInt64 shapeKey; 112 public System.UInt64 shapeKey;
113 public bool isNativeShape; 113 public bool isNativeShape;
114 114
@@ -133,7 +133,7 @@ public class BulletShape
133 buff.Append("<p="); 133 buff.Append("<p=");
134 buff.Append(AddrString); 134 buff.Append(AddrString);
135 buff.Append(",s="); 135 buff.Append(",s=");
136 buff.Append(type.ToString()); 136 buff.Append(shapeType.ToString());
137 buff.Append(",k="); 137 buff.Append(",k=");
138 buff.Append(shapeKey.ToString("X")); 138 buff.Append(shapeKey.ToString("X"));
139 buff.Append(",n="); 139 buff.Append(",n=");
@@ -224,42 +224,43 @@ public static class BulletSimData
224// As mentioned above, don't use the CollisionFilterGroups definitions directly in the code 224// As mentioned above, don't use the CollisionFilterGroups definitions directly in the code
225// but, instead, use references to this dictionary. Finding and debugging 225// but, instead, use references to this dictionary. Finding and debugging
226// collision flag problems will be made easier. 226// collision flag problems will be made easier.
227public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeMasks 227public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeMasks
228 = new Dictionary<CollisionType, CollisionTypeFilterGroup>() 228 = new Dictionary<CollisionType, CollisionTypeFilterGroup>()
229{ 229{
230 { CollisionType.Avatar, 230 { CollisionType.Avatar,
231 new CollisionTypeFilterGroup(CollisionType.Avatar, 231 new CollisionTypeFilterGroup(CollisionType.Avatar,
232 (uint)CollisionFilterGroups.BCharacterGroup, 232 (uint)CollisionFilterGroups.BCharacterGroup,
233 (uint)CollisionFilterGroups.BAllGroup) 233 (uint)CollisionFilterGroups.BAllGroup)
234 }, 234 },
235 { CollisionType.Groundplane, 235 { CollisionType.Groundplane,
236 new CollisionTypeFilterGroup(CollisionType.Groundplane, 236 new CollisionTypeFilterGroup(CollisionType.Groundplane,
237 (uint)CollisionFilterGroups.BGroundPlaneGroup, 237 (uint)CollisionFilterGroups.BGroundPlaneGroup,
238 (uint)CollisionFilterGroups.BAllGroup) 238 // (uint)CollisionFilterGroups.BAllGroup)
239 (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
239 }, 240 },
240 { CollisionType.Terrain, 241 { CollisionType.Terrain,
241 new CollisionTypeFilterGroup(CollisionType.Terrain, 242 new CollisionTypeFilterGroup(CollisionType.Terrain,
242 (uint)CollisionFilterGroups.BTerrainGroup, 243 (uint)CollisionFilterGroups.BTerrainGroup,
243 (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup)) 244 (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup))
244 }, 245 },
245 { CollisionType.Static, 246 { CollisionType.Static,
246 new CollisionTypeFilterGroup(CollisionType.Static, 247 new CollisionTypeFilterGroup(CollisionType.Static,
247 (uint)CollisionFilterGroups.BStaticGroup, 248 (uint)CollisionFilterGroups.BStaticGroup,
248 (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup)) 249 (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
249 }, 250 },
250 { CollisionType.Dynamic, 251 { CollisionType.Dynamic,
251 new CollisionTypeFilterGroup(CollisionType.Dynamic, 252 new CollisionTypeFilterGroup(CollisionType.Dynamic,
252 (uint)CollisionFilterGroups.BSolidGroup, 253 (uint)CollisionFilterGroups.BSolidGroup,
253 (uint)(CollisionFilterGroups.BAllGroup)) 254 (uint)(CollisionFilterGroups.BAllGroup))
254 }, 255 },
255 { CollisionType.VolumeDetect, 256 { CollisionType.VolumeDetect,
256 new CollisionTypeFilterGroup(CollisionType.VolumeDetect, 257 new CollisionTypeFilterGroup(CollisionType.VolumeDetect,
257 (uint)CollisionFilterGroups.BSensorTrigger, 258 (uint)CollisionFilterGroups.BSensorTrigger,
258 (uint)(~CollisionFilterGroups.BSensorTrigger)) 259 (uint)(~CollisionFilterGroups.BSensorTrigger))
259 }, 260 },
260 { CollisionType.LinksetChild, 261 { CollisionType.LinksetChild,
261 new CollisionTypeFilterGroup(CollisionType.LinksetChild, 262 new CollisionTypeFilterGroup(CollisionType.LinksetChild,
262 (uint)CollisionFilterGroups.BLinksetChildGroup, 263 (uint)CollisionFilterGroups.BLinksetChildGroup,
263 (uint)(CollisionFilterGroups.BNoneGroup)) 264 (uint)(CollisionFilterGroups.BNoneGroup))
264 // (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup)) 265 // (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
265 }, 266 },
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index 8a15abe..0453376 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -1,65 +1,61 @@
1CURRENT PRIORITIES 1CURRENT PROBLEMS TO FIX AND/OR LOOK AT
2================================================= 2=================================================
3Use the HACD convex hull routine in Bullet rather than the C# version. 3Vehicle buoyancy. Computed correctly? Possibly creating very large effective mass.
4 Speed up hullifying large meshes. 4 Interaction of llSetBuoyancy and vehicle buoyancy. Should be additive?
5 Negative buoyancy computed correctly
6Center-of-gravity
7Computation of mesh mass. How done? How should it be done?
5Enable vehicle border crossings (at least as poorly as ODE) 8Enable vehicle border crossings (at least as poorly as ODE)
6 Terrain skirts 9 Terrain skirts
7 Avatar created in previous region and not new region when crossing border 10 Avatar created in previous region and not new region when crossing border
8 Vehicle recreated in new sim at small Z value (offset from root value?) (DONE) 11 Vehicle recreated in new sim at small Z value (offset from root value?) (DONE)
9Lock axis 12User settable terrain mesh
13 Allow specifying as convex or concave and use different getHeight functions depending
14Boats, when turning nose down into the water
15 Acts like rotation around Z is also effecting rotation around X and Y
10Deleting a linkset while standing on the root will leave the physical shape of the root behind. 16Deleting a linkset while standing on the root will leave the physical shape of the root behind.
11 Not sure if it is because standing on it. Done with large prim linksets. 17 Not sure if it is because standing on it. Done with large prim linksets.
12Linkset child rotations. 18Linkset child rotations.
13 Nebadon spiral tube has middle sections which are rotated wrong. 19 Nebadon spiral tube has middle sections which are rotated wrong.
14 Select linked spiral tube. Delink and note where the middle section ends up. 20 Select linked spiral tube. Delink and note where the middle section ends up.
15Vehicle angular vertical attraction
16vehicle angular banking
17Center-of-gravity
18Vehicle angular deflection
19 Preferred orientation angular correction fix
20when should angular and linear motor targets be zeroed? when selected?
21 Need a vehicle.clear()? Or an 'else' in prestep if not physical.
22Teravus llMoveToTarget script debug 21Teravus llMoveToTarget script debug
23 Mixing of hover, buoyancy/gravity, moveToTarget, into one force 22 Mixing of hover, buoyancy/gravity, moveToTarget, into one force
24 Setting hover height to zero disables hover even if hover flags are on (from SL wiki) 23 Setting hover height to zero disables hover even if hover flags are on (from SL wiki)
25limitMotorUp calibration (more down?) 24limitMotorUp calibration (more down?)
26llRotLookAt 25llRotLookAt
27llLookAt 26llLookAt
28Avatars walking up stairs (HALF DONE) 27Convert to avatar mesh capsule. Include rotation of capsule.
29Avatar movement
30 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
31 walking up stairs is not calibrated correctly (stairs out of Kepler cabin)
32 avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution)
33Vehicle script tuning/debugging 28Vehicle script tuning/debugging
34 Avanti speed script 29 Avanti speed script
35 Weapon shooter script 30 Weapon shooter script
36Move material definitions (friction, ...) into simulator. 31Move material definitions (friction, ...) into simulator.
37Add material densities to the material types. 32osGetPhysicsEngineVerion() and create a version code for the C++ DLL
38Terrain detail: double terrain mesh detail
39One sided meshes? Should terrain be built into a closed shape? 33One sided meshes? Should terrain be built into a closed shape?
40 When meshes get partially wedged into the terrain, they cannot push themselves out. 34 When meshes get partially wedged into the terrain, they cannot push themselves out.
41 It is possible that Bullet processes collisions whether entering or leaving a mesh. 35 It is possible that Bullet processes collisions whether entering or leaving a mesh.
42 Ref: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4869 36 Ref: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4869
37Small physical objects do not interact correctly
38 Create chain of .5x.5x.1 torui and make all but top physical so to hang.
39 The chain will fall apart and pairs will dance around on ground
40 Chains of 1x1x.2 will stay connected but will dance.
41 Chains above 2x2x.4 are more stable and get stablier as torui get larger.
43 42
44VEHICLES TODO LIST: 43VEHICLES TODO LIST:
45================================================= 44=================================================
46Border crossing with linked vehicle causes crash 45LINEAR_MOTOR_DIRECTION values should be clamped to reasonable numbers.
47 20121129.1411: editting/moving phys object across region boundries causes crash 46 What are the limits in SL?
48 getPos-> btRigidBody::upcast -> getBodyType -> BOOM 47 Same for other velocity settings.
49Vehicles (Move smoothly) 48UBit improvements to remove rubber-banding of avatars sitting on vehicle child prims:
49 https://github.com/UbitUmarov/Ubit-opensim
50Some vehicles should not be able to turn if no speed or off ground. 50Some vehicles should not be able to turn if no speed or off ground.
51What to do if vehicle and prim buoyancy differ?
52Cannot edit/move a vehicle being ridden: it jumps back to the origional position. 51Cannot edit/move a vehicle being ridden: it jumps back to the origional position.
53Neb car jiggling left and right 52Neb car jiggling left and right
54 Happens on terrain and any other mesh object. Flat cubes are much smoother. 53 Happens on terrain and any other mesh object. Flat cubes are much smoother.
55 This has been reduced but not eliminated. 54 This has been reduced but not eliminated.
56Implement referenceFrame for all the motion routines. 55Implement referenceFrame for all the motion routines.
57For limitMotorUp, use raycast down to find if vehicle is in the air.
58Verify llGetVel() is returning a smooth and good value for vehicle movement. 56Verify llGetVel() is returning a smooth and good value for vehicle movement.
59llGetVel() should return the root's velocity if requested in a child prim. 57llGetVel() should return the root's velocity if requested in a child prim.
60Implement function efficiency for lineaar and angular motion. 58Implement function efficiency for lineaar and angular motion.
61After getting off a vehicle, the root prim is phantom (can be walked through)
62 Need to force a position update for the root prim after compound shape destruction
63Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint) 59Linkset explosion after three "rides" on Nebadon lite vehicle (LinksetConstraint)
64Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties(). 60Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties().
65 A kludge that isn't fixing the real problem of Bullet adding extra motion. 61 A kludge that isn't fixing the real problem of Bullet adding extra motion.
@@ -68,11 +64,10 @@ Incorporate inter-relationship of angular corrections. For instance, angularDefl
68 creates over-correction and over-shoot and wabbling. 64 creates over-correction and over-shoot and wabbling.
69Vehicle attributes are not restored when a vehicle is rezzed on region creation 65Vehicle attributes are not restored when a vehicle is rezzed on region creation
70 Create vehicle, setup vehicle properties, restart region, vehicle is not reinitialized. 66 Create vehicle, setup vehicle properties, restart region, vehicle is not reinitialized.
67What to do if vehicle and prim buoyancy differ?
71 68
72GENERAL TODO LIST: 69GENERAL TODO LIST:
73================================================= 70=================================================
74Explore btGImpactMeshShape as alternative to convex hulls for simplified physical objects.
75 Regular triangle meshes don't do physical collisions.
76Resitution of a prim works on another prim but not on terrain. 71Resitution of a prim works on another prim but not on terrain.
77 The dropped prim doesn't bounce properly on the terrain. 72 The dropped prim doesn't bounce properly on the terrain.
78Add a sanity check for PIDTarget location. 73Add a sanity check for PIDTarget location.
@@ -98,29 +93,15 @@ Revisit CollisionMargin. Builders notice the 0.04 spacing between prims.
98Duplicating a physical prim causes old prim to jump away 93Duplicating a physical prim causes old prim to jump away
99 Dup a phys prim and the original become unselected and thus interacts w/ selected prim. 94 Dup a phys prim and the original become unselected and thus interacts w/ selected prim.
100Scenes with hundred of thousands of static objects take a lot of physics CPU time. 95Scenes with hundred of thousands of static objects take a lot of physics CPU time.
101BSPrim.Force should set a continious force on the prim. The force should be
102 applied each tick. Some limits?
103Gun sending shooter flying. 96Gun sending shooter flying.
104Collision margin (gap between physical objects lying on each other) 97Collision margin (gap between physical objects lying on each other)
105Boundry checking (crashes related to crossing boundry) 98Boundry checking (crashes related to crossing boundry)
106 Add check for border edge position for avatars and objects. 99 Add check for border edge position for avatars and objects.
107 Verify the events are created for border crossings. 100 Verify the events are created for border crossings.
108Avatar rotation (check out changes to ScenePresence for physical rotation)
109Avatar running (what does phys engine need to do?)
110Small physical objects do not interact correctly
111 Create chain of .5x.5x.1 torui and make all but top physical so to hang.
112 The chain will fall apart and pairs will dance around on ground
113 Chains of 1x1x.2 will stay connected but will dance.
114 Chains above 2x2x.4 are more stable and get stablier as torui get larger.
115Add PID motor for avatar movement (slow to stop, ...)
116setForce should set a constant force. Different than AddImpulse.
117Implement raycast.
118Implement ShapeCollection.Dispose() 101Implement ShapeCollection.Dispose()
119Implement water as a plain so raycasting and collisions can happen with same. 102Implement water as a plain or mesh so raycasting and collisions can happen with same.
120Add collision penetration return 103Add collision penetration return
121 Add field passed back by BulletSim.dll and fill with info in ManifoldConstact.GetDistance() 104 Add field passed back by BulletSim.dll and fill with info in ManifoldConstact.GetDistance()
122Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE
123 Also osGetPhysicsEngineVerion() maybe.
124Linkset.Position and Linkset.Orientation requre rewrite to properly return 105Linkset.Position and Linkset.Orientation requre rewrite to properly return
125 child position. LinksetConstraint acts like it's at taint time!! 106 child position. LinksetConstraint acts like it's at taint time!!
126Implement LockAngularMotion -- implements llSetStatus(ROTATE_AXIS_*, T/F) 107Implement LockAngularMotion -- implements llSetStatus(ROTATE_AXIS_*, T/F)
@@ -132,9 +113,6 @@ Selecting and deselecting physical objects causes CPU processing time to jump
132Re-implement buoyancy as a separate force on the object rather than diddling gravity. 113Re-implement buoyancy as a separate force on the object rather than diddling gravity.
133 Register a pre-step event to add the force. 114 Register a pre-step event to add the force.
134More efficient memory usage when passing hull information from BSPrim to BulletSim 115More efficient memory usage when passing hull information from BSPrim to BulletSim
135Avatar movement motor check for zero or small movement. Somehow suppress small movements
136 when avatar has stopped and is just standing. Simple test for near zero has
137 the problem of preventing starting up (increase from zero) especially when falling.
138Physical and phantom will drop through the terrain 116Physical and phantom will drop through the terrain
139 117
140 118
@@ -168,6 +146,7 @@ Eliminate collisions between objects in a linkset. (LinksetConstraint)
168 146
169MORE 147MORE
170====================================================== 148======================================================
149Compute avatar size and scale correctly. Now it is a bit off from the capsule size.
171Create tests for different interface components 150Create tests for different interface components
172 Have test objects/scripts measure themselves and turn color if correct/bad 151 Have test objects/scripts measure themselves and turn color if correct/bad
173 Test functions in SL and calibrate correctness there 152 Test functions in SL and calibrate correctness there
@@ -176,7 +155,6 @@ Do we need to do convex hulls all the time? Can complex meshes be left meshes?
176 There is some problem with meshes and collisions 155 There is some problem with meshes and collisions
177 Hulls are not as detailed as meshes. Hulled vehicles insides are different shape. 156 Hulls are not as detailed as meshes. Hulled vehicles insides are different shape.
178Debounce avatar contact so legs don't keep folding up when standing. 157Debounce avatar contact so legs don't keep folding up when standing.
179Implement LSL physics controls. Like STATUS_ROTATE_X.
180Add border extensions to terrain to help region crossings and objects leaving region. 158Add border extensions to terrain to help region crossings and objects leaving region.
181Use a different capsule shape for avatar when sitting 159Use a different capsule shape for avatar when sitting
182 LL uses a pyrimidal shape scaled by the avatar's bounding box 160 LL uses a pyrimidal shape scaled by the avatar's bounding box
@@ -209,8 +187,6 @@ Keep avatar scaling correct. http://pennycow.blogspot.fr/2011/07/matter-of-scale
209 187
210INTERNAL IMPROVEMENT/CLEANUP 188INTERNAL IMPROVEMENT/CLEANUP
211================================================= 189=================================================
212Can the 'inTaintTime' flag be cleaned up and used? For instance, a call to
213 BSScene.TaintedObject() could immediately execute the callback if already in taint time.
214Create the physical wrapper classes (BulletBody, BulletShape) by methods on 190Create the physical wrapper classes (BulletBody, BulletShape) by methods on
215 BSAPITemplate and make their actual implementation Bullet engine specific. 191 BSAPITemplate and make their actual implementation Bullet engine specific.
216 For the short term, just call the existing functions in ShapeCollection. 192 For the short term, just call the existing functions in ShapeCollection.
@@ -344,3 +320,60 @@ Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
344 Verify that angular motion specified around Z moves in the vehicle coordinates. 320 Verify that angular motion specified around Z moves in the vehicle coordinates.
345 DONE 20130120: BulletSim properly applies force in vehicle relative coordinates. 321 DONE 20130120: BulletSim properly applies force in vehicle relative coordinates.
346Nebadon vehicles turning funny in arena (DONE) 322Nebadon vehicles turning funny in arena (DONE)
323Lock axis (DONE 20130401)
324Terrain detail: double terrain mesh detail (DONE)
325Use the HACD convex hull routine in Bullet rather than the C# version.
326 Speed up hullifying large meshes. (DONE)
327Vehicle ride, get up, ride again. Second time vehicle does not act correctly.
328 Have to rez new vehicle and delete the old to fix situation.
329 (DONE 20130520: normalize rotations)
330Hitting RESET on Nebadon's vehicle while riding causes vehicle to get into odd
331 position state where it will not settle onto ground properly, etc
332 (DONE 20130520: normalize rotations)
333Two of Nebadon vehicles in a sim max the CPU. This is new.
334 (DONE 20130520: two problems: if asset failed to mesh, constantly refetched
335 asset; vehicle was sending too many messages to all linkset members)
336Add material densities to the material types. (WILL NOT BE DONE: not how it is done)
337Avatars walking up stairs (DONE)
338Avatar movement
339 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
340 walking up stairs is not calibrated correctly (stairs out of Kepler cabin) (DONE)
341 avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution)
342After getting off a vehicle, the root prim is phantom (can be walked through)
343 Need to force a position update for the root prim after compound shape destruction
344 (DONE)
345Explore btGImpactMeshShape as alternative to convex hulls for simplified physical objects.
346 Regular triangle meshes don't do physical collisions.
347 (DONE: discovered GImpact is VERY CPU intensive)
348Script changing rotation of child prim while vehicle moving (eg turning wheel) causes
349 the wheel to appear to jump back. Looks like sending position from previous update.
350 (DONE: redo of compound linksets fixed problem)
351Refarb compound linkset creation to create a pseudo-root for center-of-mass
352 Let children change their shape to physical indendently and just add shapes to compound
353 (DONE: redo of compound linkset fixed problem)
354Vehicle angular vertical attraction (DONE: vegaslon code)
355vehicle angular banking (DONE: vegaslon code)
356Vehicle angular deflection (DONE: vegaslon code)
357 Preferred orientation angular correction fix
358Vehicles (Move smoothly)
359For limitMotorUp, use raycast down to find if vehicle is in the air.
360 (WILL NOT BE DONE: gravity does the job well enough)
361BSPrim.Force should set a continious force on the prim. The force should be
362 applied each tick. Some limits?
363 (DONE: added physical actors. Implemented SetForce, SetTorque, ...)
364Implement LSL physics controls. Like STATUS_ROTATE_X. (DONE)
365Add osGetPhysicsEngineName() so scripters can tell whether BulletSim or ODE
366Avatar rotation (check out changes to ScenePresence for physical rotation) (DONE)
367Avatar running (what does phys engine need to do?) (DONE: multiplies run factor by walking force)
368setForce should set a constant force. Different than AddImpulse. (DONE)
369Add PID motor for avatar movement (slow to stop, ...) (WNBD: current works ok)
370Avatar movement motor check for zero or small movement. Somehow suppress small movements
371 when avatar has stopped and is just standing. Simple test for near zero has
372 the problem of preventing starting up (increase from zero) especially when falling.
373 (DONE: avatar movement actor knows if standing on stationary object and zeros motion)
374Can the 'inTaintTime' flag be cleaned up and used? For instance, a call to
375 BSScene.TaintedObject() could immediately execute the callback if already in taint time.
376 (DONE)
377
378
379
diff --git a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
index 02b03a8..d069178 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs b/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs
index b040e21..48e74eb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/Tests/BasicVehicles.cs
@@ -57,6 +57,8 @@ public class BasicVehicles : OpenSimTestCase
57 public void Init() 57 public void Init()
58 { 58 {
59 Dictionary<string, string> engineParams = new Dictionary<string, string>(); 59 Dictionary<string, string> engineParams = new Dictionary<string, string>();
60 engineParams.Add("VehicleEnableAngularVerticalAttraction", "true");
61 engineParams.Add("VehicleAngularVerticalAttractionAlgorithm", "1");
60 PhysicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams); 62 PhysicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams);
61 63
62 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateSphere(); 64 PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateSphere();
@@ -114,21 +116,25 @@ public class BasicVehicles : OpenSimTestCase
114 // Instead the appropriate values are set and calls are made just the parts of the 116 // Instead the appropriate values are set and calls are made just the parts of the
115 // controller we want to exercise. Stepping the physics engine then applies 117 // controller we want to exercise. Stepping the physics engine then applies
116 // the actions of that one feature. 118 // the actions of that one feature.
117 TestVehicle.VehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, efficiency); 119 BSDynamics vehicleActor = TestVehicle.GetVehicleActor(true /* createIfNone */);
118 TestVehicle.VehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_TIMESCALE, timeScale); 120 if (vehicleActor != null)
119 TestVehicle.VehicleActor.enableAngularVerticalAttraction = true;
120
121 TestVehicle.IsPhysical = true;
122 PhysicsScene.ProcessTaints();
123
124 // Step the simulator a bunch of times and vertical attraction should orient the vehicle up
125 for (int ii = 0; ii < simSteps; ii++)
126 { 121 {
127 TestVehicle.VehicleActor.ForgetKnownVehicleProperties(); 122 vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, efficiency);
128 TestVehicle.VehicleActor.ComputeAngularVerticalAttraction(); 123 vehicleActor.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_TIMESCALE, timeScale);
129 TestVehicle.VehicleActor.PushKnownChanged(); 124 // vehicleActor.enableAngularVerticalAttraction = true;
130 125
131 PhysicsScene.Simulate(simulationTimeStep); 126 TestVehicle.IsPhysical = true;
127 PhysicsScene.ProcessTaints();
128
129 // Step the simulator a bunch of times and vertical attraction should orient the vehicle up
130 for (int ii = 0; ii < simSteps; ii++)
131 {
132 vehicleActor.ForgetKnownVehicleProperties();
133 vehicleActor.ComputeAngularVerticalAttraction();
134 vehicleActor.PushKnownChanged();
135
136 PhysicsScene.Simulate(simulationTimeStep);
137 }
132 } 138 }
133 139
134 TestVehicle.IsPhysical = false; 140 TestVehicle.IsPhysical = false;
diff --git a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
index f611b9a..b8cf624 100644
--- a/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/ConvexDecompositionDotNet/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
32// You can specify all the values or you can default the Build and Revision Numbers 32// You can specify all the values or you can default the Build and Revision Numbers
33// by using the '*' as shown below: 33// by using the '*' as shown below:
34// [assembly: AssemblyVersion("1.0.*")] 34// [assembly: AssemblyVersion("1.0.*")]
35[assembly: AssemblyVersion("0.7.6.*")] 35[assembly: AssemblyVersion("0.8.0.*")]
36 36
diff --git a/OpenSim/Region/Physics/Manager/AssemblyInfo.cs b/OpenSim/Region/Physics/Manager/AssemblyInfo.cs
index 5da3956..10e850e 100644
--- a/OpenSim/Region/Physics/Manager/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/Manager/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.7.6.*")] 58[assembly : AssemblyVersion("0.8.0.*")]
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index 7cd364b..44bfd42 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -415,6 +415,12 @@ namespace OpenSim.Region.Physics.Manager
415 public virtual PhysicsActor ParentActor { get { return this; } } 415 public virtual PhysicsActor ParentActor { get { return this; } }
416 416
417 417
418 // Extendable interface for new, physics engine specific operations
419 public virtual object Extension(string pFunct, params object[] pParams)
420 {
421 // A NOP of the physics engine does not implement this feature
422 return null;
423 }
418 } 424 }
419 425
420 public class NullPhysicsActor : PhysicsActor 426 public class NullPhysicsActor : PhysicsActor
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index 20a70b4..dd9bbc1 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -25,10 +25,13 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
28using System.Collections.Generic; 29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
31
30using log4net; 32using log4net;
31using Nini.Config; 33using Nini.Config;
34
32using OpenSim.Framework; 35using OpenSim.Framework;
33using OpenMetaverse; 36using OpenMetaverse;
34 37
@@ -386,5 +389,12 @@ namespace OpenSim.Region.Physics.Manager
386 { 389 {
387 return 0; 390 return 0;
388 } 391 }
392
393 // Extendable interface for new, physics engine specific operations
394 public virtual object Extension(string pFunct, params object[] pParams)
395 {
396 // A NOP if the extension thing is not implemented by the physics engine
397 return null;
398 }
389 } 399 }
390} 400}
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index d181b78..6938e55 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -40,7 +40,6 @@ using log4net;
40using Nini.Config; 40using Nini.Config;
41using System.Reflection; 41using System.Reflection;
42using System.IO; 42using System.IO;
43using ComponentAce.Compression.Libs.zlib;
44 43
45namespace OpenSim.Region.Physics.Meshing 44namespace OpenSim.Region.Physics.Meshing
46{ 45{
@@ -64,6 +63,7 @@ namespace OpenSim.Region.Physics.Meshing
64 public class Meshmerizer : IMesher 63 public class Meshmerizer : IMesher
65 { 64 {
66 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 65 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
66 private static string LogHeader = "[MESH]";
67 67
68 // Setting baseDir to a path will enable the dumping of raw files 68 // Setting baseDir to a path will enable the dumping of raw files
69 // raw files can be imported by blender so a visual inspection of the results can be done 69 // raw files can be imported by blender so a visual inspection of the results can be done
@@ -72,6 +72,8 @@ namespace OpenSim.Region.Physics.Meshing
72#else 72#else
73 private const string baseDir = null; //"rawFiles"; 73 private const string baseDir = null; //"rawFiles";
74#endif 74#endif
75 // If 'true', lots of DEBUG logging of asset parsing details
76 private bool debugDetail = false;
75 77
76 private bool cacheSculptMaps = true; 78 private bool cacheSculptMaps = true;
77 private string decodedSculptMapPath = null; 79 private string decodedSculptMapPath = null;
@@ -79,6 +81,9 @@ namespace OpenSim.Region.Physics.Meshing
79 81
80 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh 82 private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh
81 83
84 private List<List<Vector3>> mConvexHulls = null;
85 private List<Vector3> mBoundingHull = null;
86
82 private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>(); 87 private Dictionary<ulong, Mesh> m_uniqueMeshes = new Dictionary<ulong, Mesh>();
83 88
84 public Meshmerizer(IConfigSource config) 89 public Meshmerizer(IConfigSource config)
@@ -88,8 +93,11 @@ namespace OpenSim.Region.Physics.Meshing
88 93
89 decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); 94 decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache");
90 cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps); 95 cacheSculptMaps = start_config.GetBoolean("CacheSculptMaps", cacheSculptMaps);
91 if(mesh_config != null) 96 if (mesh_config != null)
97 {
92 useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); 98 useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh);
99 debugDetail = mesh_config.GetBoolean("LogMeshDetails", debugDetail);
100 }
93 101
94 try 102 try
95 { 103 {
@@ -319,6 +327,9 @@ namespace OpenSim.Region.Physics.Meshing
319 faces = new List<Face>(); 327 faces = new List<Face>();
320 OSD meshOsd = null; 328 OSD meshOsd = null;
321 329
330 mConvexHulls = null;
331 mBoundingHull = null;
332
322 if (primShape.SculptData.Length <= 0) 333 if (primShape.SculptData.Length <= 0)
323 { 334 {
324 // XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this 335 // XXX: At the moment we can not log here since ODEPrim, for instance, ends up triggering this
@@ -355,9 +366,139 @@ namespace OpenSim.Region.Physics.Meshing
355 OSDMap physicsParms = null; 366 OSDMap physicsParms = null;
356 OSDMap map = (OSDMap)meshOsd; 367 OSDMap map = (OSDMap)meshOsd;
357 if (map.ContainsKey("physics_shape")) 368 if (map.ContainsKey("physics_shape"))
369 {
358 physicsParms = (OSDMap)map["physics_shape"]; // old asset format 370 physicsParms = (OSDMap)map["physics_shape"]; // old asset format
371 if (debugDetail) m_log.DebugFormat("{0} prim='{1}': using 'physics_shape' mesh data", LogHeader, primName);
372 }
359 else if (map.ContainsKey("physics_mesh")) 373 else if (map.ContainsKey("physics_mesh"))
374 {
360 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format 375 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
376 if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'physics_mesh' mesh data", LogHeader, primName);
377 }
378 else if (map.ContainsKey("medium_lod"))
379 {
380 physicsParms = (OSDMap)map["medium_lod"]; // if no physics mesh, try to fall back to medium LOD display mesh
381 if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'medium_lod' mesh data", LogHeader, primName);
382 }
383 else if (map.ContainsKey("high_lod"))
384 {
385 physicsParms = (OSDMap)map["high_lod"]; // if all else fails, use highest LOD display mesh and hope it works :)
386 if (debugDetail) m_log.DebugFormat("{0} prim='{1}':using 'high_lod' mesh data", LogHeader, primName);
387 }
388
389 if (map.ContainsKey("physics_convex"))
390 { // pull this out also in case physics engine can use it
391 OSD convexBlockOsd = null;
392 try
393 {
394 OSDMap convexBlock = (OSDMap)map["physics_convex"];
395 {
396 int convexOffset = convexBlock["offset"].AsInteger() + (int)start;
397 int convexSize = convexBlock["size"].AsInteger();
398
399 byte[] convexBytes = new byte[convexSize];
400
401 System.Buffer.BlockCopy(primShape.SculptData, convexOffset, convexBytes, 0, convexSize);
402
403 try
404 {
405 convexBlockOsd = DecompressOsd(convexBytes);
406 }
407 catch (Exception e)
408 {
409 m_log.ErrorFormat("{0} prim='{1}': exception decoding convex block: {2}", LogHeader, primName, e);
410 //return false;
411 }
412 }
413
414 if (convexBlockOsd != null && convexBlockOsd is OSDMap)
415 {
416 convexBlock = convexBlockOsd as OSDMap;
417
418 if (debugDetail)
419 {
420 string keys = LogHeader + " keys found in convexBlock: ";
421 foreach (KeyValuePair<string, OSD> kvp in convexBlock)
422 keys += "'" + kvp.Key + "' ";
423 m_log.Debug(keys);
424 }
425
426 Vector3 min = new Vector3(-0.5f, -0.5f, -0.5f);
427 if (convexBlock.ContainsKey("Min")) min = convexBlock["Min"].AsVector3();
428 Vector3 max = new Vector3(0.5f, 0.5f, 0.5f);
429 if (convexBlock.ContainsKey("Max")) max = convexBlock["Max"].AsVector3();
430
431 List<Vector3> boundingHull = null;
432
433 if (convexBlock.ContainsKey("BoundingVerts"))
434 {
435 byte[] boundingVertsBytes = convexBlock["BoundingVerts"].AsBinary();
436 boundingHull = new List<Vector3>();
437 for (int i = 0; i < boundingVertsBytes.Length; )
438 {
439 ushort uX = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
440 ushort uY = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
441 ushort uZ = Utils.BytesToUInt16(boundingVertsBytes, i); i += 2;
442
443 Vector3 pos = new Vector3(
444 Utils.UInt16ToFloat(uX, min.X, max.X),
445 Utils.UInt16ToFloat(uY, min.Y, max.Y),
446 Utils.UInt16ToFloat(uZ, min.Z, max.Z)
447 );
448
449 boundingHull.Add(pos);
450 }
451
452 mBoundingHull = boundingHull;
453 if (debugDetail) m_log.DebugFormat("{0} prim='{1}': parsed bounding hull. nVerts={2}", LogHeader, primName, mBoundingHull.Count);
454 }
455
456 if (convexBlock.ContainsKey("HullList"))
457 {
458 byte[] hullList = convexBlock["HullList"].AsBinary();
459
460 byte[] posBytes = convexBlock["Positions"].AsBinary();
461
462 List<List<Vector3>> hulls = new List<List<Vector3>>();
463 int posNdx = 0;
464
465 foreach (byte cnt in hullList)
466 {
467 int count = cnt == 0 ? 256 : cnt;
468 List<Vector3> hull = new List<Vector3>();
469
470 for (int i = 0; i < count; i++)
471 {
472 ushort uX = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2;
473 ushort uY = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2;
474 ushort uZ = Utils.BytesToUInt16(posBytes, posNdx); posNdx += 2;
475
476 Vector3 pos = new Vector3(
477 Utils.UInt16ToFloat(uX, min.X, max.X),
478 Utils.UInt16ToFloat(uY, min.Y, max.Y),
479 Utils.UInt16ToFloat(uZ, min.Z, max.Z)
480 );
481
482 hull.Add(pos);
483 }
484
485 hulls.Add(hull);
486 }
487
488 mConvexHulls = hulls;
489 if (debugDetail) m_log.DebugFormat("{0} prim='{1}': parsed hulls. nHulls={2}", LogHeader, primName, mConvexHulls.Count);
490 }
491 else
492 {
493 if (debugDetail) m_log.DebugFormat("{0} prim='{1}' has physics_convex but no HullList", LogHeader, primName);
494 }
495 }
496 }
497 catch (Exception e)
498 {
499 m_log.WarnFormat("{0} exception decoding convex block: {1}", LogHeader, e);
500 }
501 }
361 502
362 if (physicsParms == null) 503 if (physicsParms == null)
363 { 504 {
@@ -374,34 +515,14 @@ namespace OpenSim.Region.Physics.Meshing
374 OSD decodedMeshOsd = new OSD(); 515 OSD decodedMeshOsd = new OSD();
375 byte[] meshBytes = new byte[physSize]; 516 byte[] meshBytes = new byte[physSize];
376 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); 517 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
377// byte[] decompressed = new byte[physSize * 5]; 518 // byte[] decompressed = new byte[physSize * 5];
378 try 519 try
379 { 520 {
380 using (MemoryStream inMs = new MemoryStream(meshBytes)) 521 decodedMeshOsd = DecompressOsd(meshBytes);
381 {
382 using (MemoryStream outMs = new MemoryStream())
383 {
384 using (ZOutputStream zOut = new ZOutputStream(outMs))
385 {
386 byte[] readBuffer = new byte[2048];
387 int readLen = 0;
388 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
389 {
390 zOut.Write(readBuffer, 0, readLen);
391 }
392 zOut.Flush();
393 outMs.Seek(0, SeekOrigin.Begin);
394
395 byte[] decompressedBuf = outMs.GetBuffer();
396
397 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
398 }
399 }
400 }
401 } 522 }
402 catch (Exception e) 523 catch (Exception e)
403 { 524 {
404 m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); 525 m_log.ErrorFormat("{0} prim='{1}': exception decoding physical mesh: {2}", LogHeader, primName, e);
405 return false; 526 return false;
406 } 527 }
407 528
@@ -410,7 +531,7 @@ namespace OpenSim.Region.Physics.Meshing
410 // physics_shape is an array of OSDMaps, one for each submesh 531 // physics_shape is an array of OSDMaps, one for each submesh
411 if (decodedMeshOsd is OSDArray) 532 if (decodedMeshOsd is OSDArray)
412 { 533 {
413// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); 534 // Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
414 535
415 decodedMeshOsdArray = (OSDArray)decodedMeshOsd; 536 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
416 foreach (OSD subMeshOsd in decodedMeshOsdArray) 537 foreach (OSD subMeshOsd in decodedMeshOsdArray)
@@ -418,6 +539,9 @@ namespace OpenSim.Region.Physics.Meshing
418 if (subMeshOsd is OSDMap) 539 if (subMeshOsd is OSDMap)
419 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); 540 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces);
420 } 541 }
542 if (debugDetail)
543 m_log.DebugFormat("{0} {1}: mesh decoded. offset={2}, size={3}, nCoords={4}, nFaces={5}",
544 LogHeader, primName, physOffset, physSize, coords.Count, faces.Count);
421 } 545 }
422 } 546 }
423 547
@@ -425,6 +549,42 @@ namespace OpenSim.Region.Physics.Meshing
425 } 549 }
426 550
427 /// <summary> 551 /// <summary>
552 /// decompresses a gzipped OSD object
553 /// </summary>
554 /// <param name="decodedOsd"></param> the OSD object
555 /// <param name="meshBytes"></param>
556 /// <returns></returns>
557 private static OSD DecompressOsd(byte[] meshBytes)
558 {
559 OSD decodedOsd = null;
560
561 using (MemoryStream inMs = new MemoryStream(meshBytes))
562 {
563 using (MemoryStream outMs = new MemoryStream())
564 {
565 using (DeflateStream decompressionStream = new DeflateStream(inMs, CompressionMode.Decompress))
566 {
567 byte[] readBuffer = new byte[2048];
568 inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header
569 int readLen = 0;
570
571 while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
572 outMs.Write(readBuffer, 0, readLen);
573
574 outMs.Flush();
575
576 outMs.Seek(0, SeekOrigin.Begin);
577
578 byte[] decompressedBuf = outMs.GetBuffer();
579
580 decodedOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
581 }
582 }
583 }
584 return decodedOsd;
585 }
586
587 /// <summary>
428 /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim. 588 /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim.
429 /// </summary> 589 /// </summary>
430 /// <param name="primName"></param> 590 /// <param name="primName"></param>
@@ -469,10 +629,11 @@ namespace OpenSim.Region.Physics.Meshing
469 629
470 try 630 try
471 { 631 {
472 OpenMetaverse.Imaging.ManagedImage unusedData; 632 OpenMetaverse.Imaging.ManagedImage managedImage;
473 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata); 633
634 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out managedImage);
474 635
475 if (idata == null) 636 if (managedImage == null)
476 { 637 {
477 // In some cases it seems that the decode can return a null bitmap without throwing 638 // In some cases it seems that the decode can return a null bitmap without throwing
478 // an exception 639 // an exception
@@ -481,9 +642,12 @@ namespace OpenSim.Region.Physics.Meshing
481 return false; 642 return false;
482 } 643 }
483 644
484 unusedData = null; 645 if ((managedImage.Channels & OpenMetaverse.Imaging.ManagedImage.ImageChannels.Alpha) != 0)
646 managedImage.ConvertChannels(managedImage.Channels & ~OpenMetaverse.Imaging.ManagedImage.ImageChannels.Alpha);
485 647
486 //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData); 648 Bitmap imgData = OpenMetaverse.Imaging.LoadTGAClass.LoadTGA(new MemoryStream(managedImage.ExportTGA()));
649 idata = (Image)imgData;
650 managedImage = null;
487 651
488 if (cacheSculptMaps) 652 if (cacheSculptMaps)
489 { 653 {
@@ -700,6 +864,45 @@ namespace OpenSim.Region.Physics.Meshing
700 return true; 864 return true;
701 } 865 }
702 866
867 /// <summary>
868 /// temporary prototype code - please do not use until the interface has been finalized!
869 /// </summary>
870 /// <param name="size">value to scale the hull points by</param>
871 /// <returns>a list of vertices in the bounding hull if it exists and has been successfully decoded, otherwise null</returns>
872 public List<Vector3> GetBoundingHull(Vector3 size)
873 {
874 if (mBoundingHull == null)
875 return null;
876
877 List<Vector3> verts = new List<Vector3>();
878 foreach (var vert in mBoundingHull)
879 verts.Add(vert * size);
880
881 return verts;
882 }
883
884 /// <summary>
885 /// temporary prototype code - please do not use until the interface has been finalized!
886 /// </summary>
887 /// <param name="size">value to scale the hull points by</param>
888 /// <returns>a list of hulls if they exist and have been successfully decoded, otherwise null</returns>
889 public List<List<Vector3>> GetConvexHulls(Vector3 size)
890 {
891 if (mConvexHulls == null)
892 return null;
893
894 List<List<Vector3>> hulls = new List<List<Vector3>>();
895 foreach (var hull in mConvexHulls)
896 {
897 List<Vector3> verts = new List<Vector3>();
898 foreach (var vert in hull)
899 verts.Add(vert * size);
900 hulls.Add(verts);
901 }
902
903 return hulls;
904 }
905
703 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 906 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
704 { 907 {
705 return CreateMesh(primName, primShape, size, lod, false, true); 908 return CreateMesh(primName, primShape, size, lod, false, true);
diff --git a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
index 3de061a..8542753 100644
--- a/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/Meshing/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs
index f477ed1..288cab5 100644
--- a/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/OdePlugin/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.7.6.*")] 58[assembly : AssemblyVersion("0.8.0.*")]
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index d09aa62..b4b7e7f 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -108,7 +108,6 @@ namespace OpenSim.Region.Physics.OdePlugin
108 private Vector3 m_taintAngularLock = Vector3.One; 108 private Vector3 m_taintAngularLock = Vector3.One;
109 private IntPtr Amotor = IntPtr.Zero; 109 private IntPtr Amotor = IntPtr.Zero;
110 110
111 private object m_assetsLock = new object();
112 private bool m_assetFailed = false; 111 private bool m_assetFailed = false;
113 112
114 private Vector3 m_PIDTarget; 113 private Vector3 m_PIDTarget;
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 07663b3..7e652fc 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -46,7 +46,7 @@ namespace OpenSim.Region.Physics.OdePlugin
46 /// </summary> 46 /// </summary>
47 public class OdePlugin : IPhysicsPlugin 47 public class OdePlugin : IPhysicsPlugin
48 { 48 {
49 private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 49// private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 private OdeScene m_scene; 51 private OdeScene m_scene;
52 52
diff --git a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs
index 4289863..83be103 100644
--- a/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs
+++ b/OpenSim/Region/Physics/POSPlugin/AssemblyInfo.cs
@@ -55,4 +55,4 @@ using System.Runtime.InteropServices;
55// You can specify all values by your own or you can build default build and revision 55// You can specify all values by your own or you can build default build and revision
56// numbers with the '*' character (the default): 56// numbers with the '*' character (the default):
57 57
58[assembly : AssemblyVersion("0.7.6.*")] 58[assembly : AssemblyVersion("0.8.0.*")]
diff --git a/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs b/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
index 86a3101..c341dfd 100644
--- a/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/RegionCombinerModule/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
index f424e7f..83732e2 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerIndividualEventForwarder.cs
@@ -51,7 +51,8 @@ namespace OpenSim.Region.RegionCombinerModule
51 m_virtScene.UnSubscribeToClientPrimEvents(client); 51 m_virtScene.UnSubscribeToClientPrimEvents(client);
52 m_virtScene.UnSubscribeToClientPrimRezEvents(client); 52 m_virtScene.UnSubscribeToClientPrimRezEvents(client);
53 m_virtScene.UnSubscribeToClientInventoryEvents(client); 53 m_virtScene.UnSubscribeToClientInventoryEvents(client);
54 ((AttachmentsModule)m_virtScene.AttachmentsModule).UnsubscribeFromClientEvents(client); 54 if(m_virtScene.AttachmentsModule != null)
55 ((AttachmentsModule)m_virtScene.AttachmentsModule).UnsubscribeFromClientEvents(client);
55 //m_virtScene.UnSubscribeToClientTeleportEvents(client); 56 //m_virtScene.UnSubscribeToClientTeleportEvents(client);
56 m_virtScene.UnSubscribeToClientScriptEvents(client); 57 m_virtScene.UnSubscribeToClientScriptEvents(client);
57 58
@@ -66,7 +67,8 @@ namespace OpenSim.Region.RegionCombinerModule
66 client.OnRezObject += LocalRezObject; 67 client.OnRezObject += LocalRezObject;
67 68
68 m_rootScene.SubscribeToClientInventoryEvents(client); 69 m_rootScene.SubscribeToClientInventoryEvents(client);
69 ((AttachmentsModule)m_rootScene.AttachmentsModule).SubscribeToClientEvents(client); 70 if (m_rootScene.AttachmentsModule != null)
71 ((AttachmentsModule)m_rootScene.AttachmentsModule).SubscribeToClientEvents(client);
70 //m_rootScene.SubscribeToClientTeleportEvents(client); 72 //m_rootScene.SubscribeToClientTeleportEvents(client);
71 m_rootScene.SubscribeToClientScriptEvents(client); 73 m_rootScene.SubscribeToClientScriptEvents(client);
72 74
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
index b4abc1d..4bf2a82 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
@@ -27,6 +27,8 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
30using OpenMetaverse; 32using OpenMetaverse;
31using OpenSim.Framework; 33using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
@@ -34,10 +36,10 @@ using OpenSim.Region.CoreModules.World.Land;
34 36
35namespace OpenSim.Region.RegionCombinerModule 37namespace OpenSim.Region.RegionCombinerModule
36{ 38{
37public class RegionCombinerLargeLandChannel : ILandChannel 39 public class RegionCombinerLargeLandChannel : ILandChannel
38 { 40 {
39 // private static readonly ILog m_log = 41// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42
41 private RegionData RegData; 43 private RegionData RegData;
42 private ILandChannel RootRegionLandChannel; 44 private ILandChannel RootRegionLandChannel;
43 private readonly List<RegionData> RegionConnections; 45 private readonly List<RegionData> RegionConnections;
@@ -75,40 +77,51 @@ public class RegionCombinerLargeLandChannel : ILandChannel
75 77
76 public ILandObject GetLandObject(int x, int y) 78 public ILandObject GetLandObject(int x, int y)
77 { 79 {
78 //m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y); 80 return GetLandObject((float)x, (float)y);
79 81
80 if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize) 82// m_log.DebugFormat("[BIGLANDTESTINT]: <{0},{1}>", x, y);
81 { 83//
82 return RootRegionLandChannel.GetLandObject(x, y); 84// if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
83 } 85// {
84 else 86// return RootRegionLandChannel.GetLandObject(x, y);
85 { 87// }
86 int offsetX = (x / (int)Constants.RegionSize); 88// else
87 int offsetY = (y / (int)Constants.RegionSize); 89// {
88 offsetX *= (int)Constants.RegionSize; 90// int offsetX = (x / (int)Constants.RegionSize);
89 offsetY *= (int)Constants.RegionSize; 91// int offsetY = (y / (int)Constants.RegionSize);
90 92// offsetX *= (int)Constants.RegionSize;
91 foreach (RegionData regionData in RegionConnections) 93// offsetY *= (int)Constants.RegionSize;
92 { 94//
93 if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY) 95// foreach (RegionData regionData in RegionConnections)
94 { 96// {
95 return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY); 97// if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
96 } 98// {
97 } 99// m_log.DebugFormat(
98 ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene); 100// "[REGION COMBINER LARGE LAND CHANNEL]: Found region {0} at offset {1},{2}",
99 obj.LandData.Name = "NO LAND"; 101// regionData.RegionScene.Name, offsetX, offsetY);
100 return obj; 102//
101 } 103// return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
104// }
105// }
106// //ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
107// //obj.LandData.Name = "NO LAND";
108// //return obj;
109// }
110//
111// m_log.DebugFormat("[REGION COMBINER LARGE LAND CHANNEL]: No region found at {0},{1}, returning null", x, y);
112//
113// return null;
102 } 114 }
103 115
104 public ILandObject GetLandObject(int localID) 116 public ILandObject GetLandObject(int localID)
105 { 117 {
118 // XXX: Possibly should be looking in every land channel, not just the root.
106 return RootRegionLandChannel.GetLandObject(localID); 119 return RootRegionLandChannel.GetLandObject(localID);
107 } 120 }
108 121
109 public ILandObject GetLandObject(float x, float y) 122 public ILandObject GetLandObject(float x, float y)
110 { 123 {
111 //m_log.DebugFormat("[BIGLANDTESTFLOAT]: <{0},{1}>", x, y); 124// m_log.DebugFormat("[BIGLANDTESTFLOAT]: <{0},{1}>", x, y);
112 125
113 if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize) 126 if (x > 0 && x <= (int)Constants.RegionSize && y > 0 && y <= (int)Constants.RegionSize)
114 { 127 {
@@ -125,14 +138,22 @@ public class RegionCombinerLargeLandChannel : ILandChannel
125 { 138 {
126 if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY) 139 if (regionData.Offset.X == offsetX && regionData.Offset.Y == offsetY)
127 { 140 {
141// m_log.DebugFormat(
142// "[REGION COMBINER LARGE LAND CHANNEL]: Found region {0} at offset {1},{2}",
143// regionData.RegionScene.Name, offsetX, offsetY);
144
128 return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY); 145 return regionData.RegionScene.LandChannel.GetLandObject(x - offsetX, y - offsetY);
129 } 146 }
130 } 147 }
131 148
132 ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene); 149// ILandObject obj = new LandObject(UUID.Zero, false, RegData.RegionScene);
133 obj.LandData.Name = "NO LAND"; 150// obj.LandData.Name = "NO LAND";
134 return obj; 151// return obj;
135 } 152 }
153
154// m_log.DebugFormat("[REGION COMBINER LARGE LAND CHANNEL]: No region found at {0},{1}, returning null", x, y);
155
156 return null;
136 } 157 }
137 158
138 public bool IsForcefulBansAllowed() 159 public bool IsForcefulBansAllowed()
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index 35ae44c..b9a217b 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
51 public interface IScriptWorkItem 51 public interface IScriptWorkItem
52 { 52 {
53 bool Cancel(); 53 bool Cancel();
54 void Abort(); 54 bool Abort();
55 55
56 /// <summary> 56 /// <summary>
57 /// Wait for the work item to complete. 57 /// Wait for the work item to complete.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index 6879ebb..1e19032 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -37,6 +37,8 @@ using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared; 37using OpenSim.Region.ScriptEngine.Shared;
38using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; 38using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
39using Timer=OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer; 39using Timer=OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer;
40using System.Reflection;
41using log4net;
40 42
41namespace OpenSim.Region.ScriptEngine.Shared.Api 43namespace OpenSim.Region.ScriptEngine.Shared.Api
42{ 44{
@@ -45,15 +47,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
45 /// </summary> 47 /// </summary>
46 public class AsyncCommandManager 48 public class AsyncCommandManager
47 { 49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
48 private static Thread cmdHandlerThread; 52 private static Thread cmdHandlerThread;
49 private static int cmdHandlerThreadCycleSleepms; 53 private static int cmdHandlerThreadCycleSleepms;
50 54
51 private static List<IScene> m_Scenes = new List<IScene>(); 55 /// <summary>
56 /// Lock for reading/writing static components of AsyncCommandManager.
57 /// </summary>
58 /// <remarks>
59 /// This lock exists so that multiple threads from different engines and/or different copies of the same engine
60 /// are prevented from running non-thread safe code (e.g. read/write of lists) concurrently.
61 /// </remarks>
62 private static object staticLock = new object();
63
52 private static List<IScriptEngine> m_ScriptEngines = 64 private static List<IScriptEngine> m_ScriptEngines =
53 new List<IScriptEngine>(); 65 new List<IScriptEngine>();
54 66
55 public IScriptEngine m_ScriptEngine; 67 public IScriptEngine m_ScriptEngine;
56 private IScene m_Scene;
57 68
58 private static Dictionary<IScriptEngine, Dataserver> m_Dataserver = 69 private static Dictionary<IScriptEngine, Dataserver> m_Dataserver =
59 new Dictionary<IScriptEngine, Dataserver>(); 70 new Dictionary<IScriptEngine, Dataserver>();
@@ -70,67 +81,99 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
70 81
71 public Dataserver DataserverPlugin 82 public Dataserver DataserverPlugin
72 { 83 {
73 get { return m_Dataserver[m_ScriptEngine]; } 84 get
85 {
86 lock (staticLock)
87 return m_Dataserver[m_ScriptEngine];
88 }
74 } 89 }
75 90
76 public Timer TimerPlugin 91 public Timer TimerPlugin
77 { 92 {
78 get { return m_Timer[m_ScriptEngine]; } 93 get
94 {
95 lock (staticLock)
96 return m_Timer[m_ScriptEngine];
97 }
79 } 98 }
80 99
81 public HttpRequest HttpRequestPlugin 100 public HttpRequest HttpRequestPlugin
82 { 101 {
83 get { return m_HttpRequest[m_ScriptEngine]; } 102 get
103 {
104 lock (staticLock)
105 return m_HttpRequest[m_ScriptEngine];
106 }
84 } 107 }
85 108
86 public Listener ListenerPlugin 109 public Listener ListenerPlugin
87 { 110 {
88 get { return m_Listener[m_ScriptEngine]; } 111 get
112 {
113 lock (staticLock)
114 return m_Listener[m_ScriptEngine];
115 }
89 } 116 }
90 117
91 public SensorRepeat SensorRepeatPlugin 118 public SensorRepeat SensorRepeatPlugin
92 { 119 {
93 get { return m_SensorRepeat[m_ScriptEngine]; } 120 get
121 {
122 lock (staticLock)
123 return m_SensorRepeat[m_ScriptEngine];
124 }
94 } 125 }
95 126
96 public XmlRequest XmlRequestPlugin 127 public XmlRequest XmlRequestPlugin
97 { 128 {
98 get { return m_XmlRequest[m_ScriptEngine]; } 129 get
130 {
131 lock (staticLock)
132 return m_XmlRequest[m_ScriptEngine];
133 }
99 } 134 }
100 135
101 public IScriptEngine[] ScriptEngines 136 public IScriptEngine[] ScriptEngines
102 { 137 {
103 get { return m_ScriptEngines.ToArray(); } 138 get
139 {
140 lock (staticLock)
141 return m_ScriptEngines.ToArray();
142 }
104 } 143 }
105 144
106 public AsyncCommandManager(IScriptEngine _ScriptEngine) 145 public AsyncCommandManager(IScriptEngine _ScriptEngine)
107 { 146 {
108 m_ScriptEngine = _ScriptEngine; 147 m_ScriptEngine = _ScriptEngine;
109 m_Scene = m_ScriptEngine.World; 148
110 149 // If there is more than one scene in the simulator or multiple script engines are used on the same region
111 if (m_Scenes.Count == 0) 150 // then more than one thread could arrive at this block of code simultaneously. However, it cannot be
112 ReadConfig(); 151 // executed concurrently both because concurrent list operations are not thread-safe and because of other
113 152 // race conditions such as the later check of cmdHandlerThread == null.
114 if (!m_Scenes.Contains(m_Scene)) 153 lock (staticLock)
115 m_Scenes.Add(m_Scene); 154 {
116 if (!m_ScriptEngines.Contains(m_ScriptEngine)) 155 if (m_ScriptEngines.Count == 0)
117 m_ScriptEngines.Add(m_ScriptEngine); 156 ReadConfig();
118 157
119 // Create instances of all plugins 158 if (!m_ScriptEngines.Contains(m_ScriptEngine))
120 if (!m_Dataserver.ContainsKey(m_ScriptEngine)) 159 m_ScriptEngines.Add(m_ScriptEngine);
121 m_Dataserver[m_ScriptEngine] = new Dataserver(this); 160
122 if (!m_Timer.ContainsKey(m_ScriptEngine)) 161 // Create instances of all plugins
123 m_Timer[m_ScriptEngine] = new Timer(this); 162 if (!m_Dataserver.ContainsKey(m_ScriptEngine))
124 if (!m_HttpRequest.ContainsKey(m_ScriptEngine)) 163 m_Dataserver[m_ScriptEngine] = new Dataserver(this);
125 m_HttpRequest[m_ScriptEngine] = new HttpRequest(this); 164 if (!m_Timer.ContainsKey(m_ScriptEngine))
126 if (!m_Listener.ContainsKey(m_ScriptEngine)) 165 m_Timer[m_ScriptEngine] = new Timer(this);
127 m_Listener[m_ScriptEngine] = new Listener(this); 166 if (!m_HttpRequest.ContainsKey(m_ScriptEngine))
128 if (!m_SensorRepeat.ContainsKey(m_ScriptEngine)) 167 m_HttpRequest[m_ScriptEngine] = new HttpRequest(this);
129 m_SensorRepeat[m_ScriptEngine] = new SensorRepeat(this); 168 if (!m_Listener.ContainsKey(m_ScriptEngine))
130 if (!m_XmlRequest.ContainsKey(m_ScriptEngine)) 169 m_Listener[m_ScriptEngine] = new Listener(this);
131 m_XmlRequest[m_ScriptEngine] = new XmlRequest(this); 170 if (!m_SensorRepeat.ContainsKey(m_ScriptEngine))
132 171 m_SensorRepeat[m_ScriptEngine] = new SensorRepeat(this);
133 StartThread(); 172 if (!m_XmlRequest.ContainsKey(m_ScriptEngine))
173 m_XmlRequest[m_ScriptEngine] = new XmlRequest(this);
174
175 StartThread();
176 }
134 } 177 }
135 178
136 private static void StartThread() 179 private static void StartThread()
@@ -179,42 +222,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
179 { 222 {
180 try 223 try
181 { 224 {
182 while (true) 225 Thread.Sleep(cmdHandlerThreadCycleSleepms);
183 {
184 Thread.Sleep(cmdHandlerThreadCycleSleepms);
185 226
186 DoOneCmdHandlerPass(); 227 DoOneCmdHandlerPass();
187 228
188 Watchdog.UpdateThread(); 229 Watchdog.UpdateThread();
189 }
190 } 230 }
191 catch 231 catch (Exception e)
192 { 232 {
233 m_log.Error("[ASYNC COMMAND MANAGER]: Exception in command handler pass: ", e);
193 } 234 }
194 } 235 }
195 } 236 }
196 237
197 private static void DoOneCmdHandlerPass() 238 private static void DoOneCmdHandlerPass()
198 { 239 {
199 // Check HttpRequests 240 lock (staticLock)
200 m_HttpRequest[m_ScriptEngines[0]].CheckHttpRequests(); 241 {
242 // Check HttpRequests
243 m_HttpRequest[m_ScriptEngines[0]].CheckHttpRequests();
201 244
202 // Check XMLRPCRequests 245 // Check XMLRPCRequests
203 m_XmlRequest[m_ScriptEngines[0]].CheckXMLRPCRequests(); 246 m_XmlRequest[m_ScriptEngines[0]].CheckXMLRPCRequests();
204 247
205 foreach (IScriptEngine s in m_ScriptEngines) 248 foreach (IScriptEngine s in m_ScriptEngines)
206 { 249 {
207 // Check Listeners 250 // Check Listeners
208 m_Listener[s].CheckListeners(); 251 m_Listener[s].CheckListeners();
209 252
210 // Check timers 253 // Check timers
211 m_Timer[s].CheckTimerEvents(); 254 m_Timer[s].CheckTimerEvents();
212 255
213 // Check Sensors 256 // Check Sensors
214 m_SensorRepeat[s].CheckSenseRepeaterEvents(); 257 m_SensorRepeat[s].CheckSenseRepeaterEvents();
215 258
216 // Check dataserver 259 // Check dataserver
217 m_Dataserver[s].ExpireRequests(); 260 m_Dataserver[s].ExpireRequests();
261 }
218 } 262 }
219 } 263 }
220 264
@@ -226,31 +270,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
226 public static void RemoveScript(IScriptEngine engine, uint localID, UUID itemID) 270 public static void RemoveScript(IScriptEngine engine, uint localID, UUID itemID)
227 { 271 {
228 // Remove a specific script 272 // Remove a specific script
273// m_log.DebugFormat("[ASYNC COMMAND MANAGER]: Removing facilities for script {0}", itemID);
229 274
230 // Remove dataserver events 275 lock (staticLock)
231 m_Dataserver[engine].RemoveEvents(localID, itemID); 276 {
277 // Remove dataserver events
278 m_Dataserver[engine].RemoveEvents(localID, itemID);
232 279
233 // Remove from: Timers 280 // Remove from: Timers
234 m_Timer[engine].UnSetTimerEvents(localID, itemID); 281 m_Timer[engine].UnSetTimerEvents(localID, itemID);
235 282
236 // Remove from: HttpRequest 283 // Remove from: HttpRequest
237 IHttpRequestModule iHttpReq = engine.World.RequestModuleInterface<IHttpRequestModule>(); 284 IHttpRequestModule iHttpReq = engine.World.RequestModuleInterface<IHttpRequestModule>();
238 if (iHttpReq != null) 285 if (iHttpReq != null)
239 iHttpReq.StopHttpRequest(localID, itemID); 286 iHttpReq.StopHttpRequest(localID, itemID);
240 287
241 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>(); 288 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>();
242 if (comms != null) 289 if (comms != null)
243 comms.DeleteListener(itemID); 290 comms.DeleteListener(itemID);
244 291
245 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>(); 292 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>();
246 if (xmlrpc != null) 293 if (xmlrpc != null)
247 { 294 {
248 xmlrpc.DeleteChannels(itemID); 295 xmlrpc.DeleteChannels(itemID);
249 xmlrpc.CancelSRDRequests(itemID); 296 xmlrpc.CancelSRDRequests(itemID);
250 } 297 }
251 298
252 // Remove Sensors 299 // Remove Sensors
253 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID); 300 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID);
301 }
254 } 302 }
255 303
256 /// <summary> 304 /// <summary>
@@ -260,10 +308,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
260 /// <returns></returns> 308 /// <returns></returns>
261 public static SensorRepeat GetSensorRepeatPlugin(IScriptEngine engine) 309 public static SensorRepeat GetSensorRepeatPlugin(IScriptEngine engine)
262 { 310 {
263 if (m_SensorRepeat.ContainsKey(engine)) 311 lock (staticLock)
264 return m_SensorRepeat[engine]; 312 {
265 else 313 if (m_SensorRepeat.ContainsKey(engine))
266 return null; 314 return m_SensorRepeat[engine];
315 else
316 return null;
317 }
267 } 318 }
268 319
269 /// <summary> 320 /// <summary>
@@ -273,10 +324,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
273 /// <returns></returns> 324 /// <returns></returns>
274 public static Dataserver GetDataserverPlugin(IScriptEngine engine) 325 public static Dataserver GetDataserverPlugin(IScriptEngine engine)
275 { 326 {
276 if (m_Dataserver.ContainsKey(engine)) 327 lock (staticLock)
277 return m_Dataserver[engine]; 328 {
278 else 329 if (m_Dataserver.ContainsKey(engine))
279 return null; 330 return m_Dataserver[engine];
331 else
332 return null;
333 }
280 } 334 }
281 335
282 /// <summary> 336 /// <summary>
@@ -286,10 +340,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
286 /// <returns></returns> 340 /// <returns></returns>
287 public static Timer GetTimerPlugin(IScriptEngine engine) 341 public static Timer GetTimerPlugin(IScriptEngine engine)
288 { 342 {
289 if (m_Timer.ContainsKey(engine)) 343 lock (staticLock)
290 return m_Timer[engine]; 344 {
291 else 345 if (m_Timer.ContainsKey(engine))
292 return null; 346 return m_Timer[engine];
347 else
348 return null;
349 }
293 } 350 }
294 351
295 /// <summary> 352 /// <summary>
@@ -299,10 +356,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
299 /// <returns></returns> 356 /// <returns></returns>
300 public static Listener GetListenerPlugin(IScriptEngine engine) 357 public static Listener GetListenerPlugin(IScriptEngine engine)
301 { 358 {
302 if (m_Listener.ContainsKey(engine)) 359 lock (staticLock)
303 return m_Listener[engine]; 360 {
304 else 361 if (m_Listener.ContainsKey(engine))
305 return null; 362 return m_Listener[engine];
363 else
364 return null;
365 }
306 } 366 }
307 367
308 public static void StateChange(IScriptEngine engine, uint localID, UUID itemID) 368 public static void StateChange(IScriptEngine engine, uint localID, UUID itemID)
@@ -332,28 +392,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
332 { 392 {
333 List<Object> data = new List<Object>(); 393 List<Object> data = new List<Object>();
334 394
335 Object[] listeners = m_Listener[engine].GetSerializationData(itemID); 395 lock (staticLock)
336 if (listeners.Length > 0)
337 { 396 {
338 data.Add("listener"); 397 Object[] listeners = m_Listener[engine].GetSerializationData(itemID);
339 data.Add(listeners.Length); 398 if (listeners.Length > 0)
340 data.AddRange(listeners); 399 {
341 } 400 data.Add("listener");
401 data.Add(listeners.Length);
402 data.AddRange(listeners);
403 }
342 404
343 Object[] timers=m_Timer[engine].GetSerializationData(itemID); 405 Object[] timers=m_Timer[engine].GetSerializationData(itemID);
344 if (timers.Length > 0) 406 if (timers.Length > 0)
345 { 407 {
346 data.Add("timer"); 408 data.Add("timer");
347 data.Add(timers.Length); 409 data.Add(timers.Length);
348 data.AddRange(timers); 410 data.AddRange(timers);
349 } 411 }
350 412
351 Object[] sensors = m_SensorRepeat[engine].GetSerializationData(itemID); 413 Object[] sensors = m_SensorRepeat[engine].GetSerializationData(itemID);
352 if (sensors.Length > 0) 414 if (sensors.Length > 0)
353 { 415 {
354 data.Add("sensor"); 416 data.Add("sensor");
355 data.Add(sensors.Length); 417 data.Add(sensors.Length);
356 data.AddRange(sensors); 418 data.AddRange(sensors);
419 }
357 } 420 }
358 421
359 return data.ToArray(); 422 return data.ToArray();
@@ -378,41 +441,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
378 441
379 idx+=len; 442 idx+=len;
380 443
444 lock (staticLock)
445 {
381 switch (type) 446 switch (type)
382 { 447 {
383 case "listener": 448 case "listener":
384 m_Listener[engine].CreateFromData(localID, itemID, 449 m_Listener[engine].CreateFromData(localID, itemID,
385 hostID, item); 450 hostID, item);
386 break; 451 break;
387 case "timer": 452 case "timer":
388 m_Timer[engine].CreateFromData(localID, itemID, 453 m_Timer[engine].CreateFromData(localID, itemID,
389 hostID, item); 454 hostID, item);
390 break; 455 break;
391 case "sensor": 456 case "sensor":
392 m_SensorRepeat[engine].CreateFromData(localID, 457 m_SensorRepeat[engine].CreateFromData(localID,
393 itemID, hostID, item); 458 itemID, hostID, item);
394 break; 459 break;
460 }
395 } 461 }
396 } 462 }
397 } 463 }
398 } 464 }
399
400 #region Check llRemoteData channels
401
402 #endregion
403
404 #region Check llListeners
405
406 #endregion
407
408 /// <summary>
409 /// If set to true then threads and stuff should try to make a graceful exit
410 /// </summary>
411 public bool PleaseShutdown
412 {
413 get { return _PleaseShutdown; }
414 set { _PleaseShutdown = value; }
415 }
416 private bool _PleaseShutdown = false;
417 } 465 }
418} 466}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 3f0af6d..916d841 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -1664,6 +1664,75 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1664 m_host.SetFaceColorAlpha(face, color, null); 1664 m_host.SetFaceColorAlpha(face, color, null);
1665 } 1665 }
1666 1666
1667 /*
1668 public void llSetContentType(LSL_Key id, LSL_Integer type)
1669 {
1670 m_host.AddScriptLPS(1);
1671
1672 if (m_UrlModule == null)
1673 return;
1674
1675 // Make sure the content type is text/plain to start with
1676 m_UrlModule.HttpContentType(new UUID(id), "text/plain");
1677
1678 // Is the object owner online and in the region
1679 ScenePresence agent = World.GetScenePresence(m_host.ParentGroup.OwnerID);
1680 if (agent == null || agent.IsChildAgent)
1681 return; // Fail if the owner is not in the same region
1682
1683 // Is it the embeded browser?
1684 string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent");
1685 if (userAgent.IndexOf("SecondLife") < 0)
1686 return; // Not the embedded browser. Is this check good enough?
1687
1688 // Use the IP address of the client and check against the request
1689 // seperate logins from the same IP will allow all of them to get non-text/plain as long
1690 // as the owner is in the region. Same as SL!
1691 string logonFromIPAddress = agent.ControllingClient.RemoteEndPoint.Address.ToString();
1692 string requestFromIPAddress = m_UrlModule.GetHttpHeader(new UUID(id), "remote_addr");
1693 //m_log.Debug("IP from header='" + requestFromIPAddress + "' IP from endpoint='" + logonFromIPAddress + "'");
1694 if (requestFromIPAddress == null || requestFromIPAddress.Trim() == "")
1695 return;
1696 if (logonFromIPAddress == null || logonFromIPAddress.Trim() == "")
1697 return;
1698
1699 // If the request isnt from the same IP address then the request cannot be from the owner
1700 if (!requestFromIPAddress.Trim().Equals(logonFromIPAddress.Trim()))
1701 return;
1702
1703 switch (type)
1704 {
1705 case ScriptBaseClass.CONTENT_TYPE_HTML:
1706 m_UrlModule.HttpContentType(new UUID(id), "text/html");
1707 break;
1708 case ScriptBaseClass.CONTENT_TYPE_XML:
1709 m_UrlModule.HttpContentType(new UUID(id), "application/xml");
1710 break;
1711 case ScriptBaseClass.CONTENT_TYPE_XHTML:
1712 m_UrlModule.HttpContentType(new UUID(id), "application/xhtml+xml");
1713 break;
1714 case ScriptBaseClass.CONTENT_TYPE_ATOM:
1715 m_UrlModule.HttpContentType(new UUID(id), "application/atom+xml");
1716 break;
1717 case ScriptBaseClass.CONTENT_TYPE_JSON:
1718 m_UrlModule.HttpContentType(new UUID(id), "application/json");
1719 break;
1720 case ScriptBaseClass.CONTENT_TYPE_LLSD:
1721 m_UrlModule.HttpContentType(new UUID(id), "application/llsd+xml");
1722 break;
1723 case ScriptBaseClass.CONTENT_TYPE_FORM:
1724 m_UrlModule.HttpContentType(new UUID(id), "application/x-www-form-urlencoded");
1725 break;
1726 case ScriptBaseClass.CONTENT_TYPE_RSS:
1727 m_UrlModule.HttpContentType(new UUID(id), "application/rss+xml");
1728 break;
1729 default:
1730 m_UrlModule.HttpContentType(new UUID(id), "text/plain");
1731 break;
1732 }
1733 }
1734 */
1735
1667 public void SetTexGen(SceneObjectPart part, int face,int style) 1736 public void SetTexGen(SceneObjectPart part, int face,int style)
1668 { 1737 {
1669 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 1738 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
@@ -2772,9 +2841,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2772 // send the sound, once, to all clients in range 2841 // send the sound, once, to all clients in range
2773 if (m_SoundModule != null) 2842 if (m_SoundModule != null)
2774 { 2843 {
2775 m_SoundModule.SendSound(m_host.UUID, 2844 m_SoundModule.SendSound(
2776 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0, 2845 m_host.UUID,
2777 0, false, false); 2846 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound),
2847 volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None,
2848 0, false, false);
2778 } 2849 }
2779 } 2850 }
2780 2851
@@ -3176,46 +3247,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3176 // need the magnitude later 3247 // need the magnitude later
3177 // float velmag = (float)Util.GetMagnitude(llvel); 3248 // float velmag = (float)Util.GetMagnitude(llvel);
3178 3249
3179 SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); 3250 List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param);
3180 3251
3181 // If either of these are null, then there was an unknown error. 3252 // If either of these are null, then there was an unknown error.
3182 if (new_group == null) 3253 if (new_groups == null)
3183 return; 3254 return;
3184 3255
3185 // objects rezzed with this method are die_at_edge by default. 3256 foreach (SceneObjectGroup group in new_groups)
3186 new_group.RootPart.SetDieAtEdge(true); 3257 {
3187 3258 // objects rezzed with this method are die_at_edge by default.
3188 new_group.ResumeScripts(); 3259 group.RootPart.SetDieAtEdge(true);
3189 3260
3190 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( 3261 group.ResumeScripts();
3191 "object_rez", new Object[] {
3192 new LSL_String(
3193 new_group.RootPart.UUID.ToString()) },
3194 new DetectParams[0]));
3195 3262
3196 // do recoil 3263 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
3197 SceneObjectGroup hostgrp = m_host.ParentGroup; 3264 "object_rez", new Object[] {
3198 if (hostgrp == null) 3265 new LSL_String(
3199 return; 3266 group.RootPart.UUID.ToString()) },
3267 new DetectParams[0]));
3200 3268
3201 if (hostgrp.IsAttachment) // don't recoil avatars 3269 float groupmass = group.GetMass();
3202 return;
3203 3270
3204 PhysicsActor pa = new_group.RootPart.PhysActor; 3271 PhysicsActor pa = group.RootPart.PhysActor;
3205 3272
3206 //Recoil. 3273 //Recoil.
3207 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3274 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3208 {
3209 float groupmass = new_group.GetMass();
3210 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3211 if (recoil != Vector3.Zero)
3212 { 3275 {
3213 llApplyImpulse(recoil, 0); 3276 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3277 if (recoil != Vector3.Zero)
3278 {
3279 llApplyImpulse(recoil, 0);
3280 }
3214 } 3281 }
3282 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3215 } 3283 }
3216 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3217 return; 3284 return;
3218
3219 }); 3285 });
3220 3286
3221 //ScriptSleep((int)((groupmass * velmag) / 10)); 3287 //ScriptSleep((int)((groupmass * velmag) / 10));
@@ -4746,6 +4812,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4746 UUID av = new UUID(); 4812 UUID av = new UUID();
4747 if (!UUID.TryParse(agent,out av)) 4813 if (!UUID.TryParse(agent,out av))
4748 { 4814 {
4815 LSLError("First parameter to llTextBox needs to be a key");
4749 return; 4816 return;
4750 } 4817 }
4751 4818
@@ -5108,6 +5175,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5108 5175
5109 s = Math.Cos(angle * 0.5); 5176 s = Math.Cos(angle * 0.5);
5110 t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs 5177 t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs
5178 axis = LSL_Vector.Norm(axis);
5111 x = axis.x * t; 5179 x = axis.x * t;
5112 y = axis.y * t; 5180 y = axis.y * t;
5113 z = axis.z * t; 5181 z = axis.z * t;
@@ -5115,41 +5183,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5115 return new LSL_Rotation(x,y,z,s); 5183 return new LSL_Rotation(x,y,z,s);
5116 } 5184 }
5117 5185
5118 5186 /// <summary>
5119 // Xantor 29/apr/2008 5187 /// Returns the axis of rotation for a quaternion
5120 // converts a Quaternion to X,Y,Z axis rotations 5188 /// </summary>
5189 /// <returns></returns>
5190 /// <param name='rot'></param>
5121 public LSL_Vector llRot2Axis(LSL_Rotation rot) 5191 public LSL_Vector llRot2Axis(LSL_Rotation rot)
5122 { 5192 {
5123 m_host.AddScriptLPS(1); 5193 m_host.AddScriptLPS(1);
5124 double x,y,z;
5125 5194
5126 if (rot.s > 1) // normalization needed 5195 if (Math.Abs(rot.s) > 1) // normalization needed
5127 { 5196 rot.Normalize();
5128 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
5129 rot.z * rot.z + rot.s * rot.s);
5130
5131 rot.x /= length;
5132 rot.y /= length;
5133 rot.z /= length;
5134 rot.s /= length;
5135
5136 }
5137 5197
5138 // double angle = 2 * Math.Acos(rot.s);
5139 double s = Math.Sqrt(1 - rot.s * rot.s); 5198 double s = Math.Sqrt(1 - rot.s * rot.s);
5140 if (s < 0.001) 5199 if (s < 0.001)
5141 { 5200 {
5142 x = 1; 5201 return new LSL_Vector(1, 0, 0);
5143 y = z = 0;
5144 } 5202 }
5145 else 5203 else
5146 { 5204 {
5147 x = rot.x / s; // normalise axis 5205 double invS = 1.0 / s;
5148 y = rot.y / s; 5206 if (rot.s < 0) invS = -invS;
5149 z = rot.z / s; 5207 return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS);
5150 } 5208 }
5151
5152 return new LSL_Vector(x,y,z);
5153 } 5209 }
5154 5210
5155 5211
@@ -5158,18 +5214,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5158 { 5214 {
5159 m_host.AddScriptLPS(1); 5215 m_host.AddScriptLPS(1);
5160 5216
5161 if (rot.s > 1) // normalization needed 5217 if (Math.Abs(rot.s) > 1) // normalization needed
5162 { 5218 rot.Normalize();
5163 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
5164 rot.z * rot.z + rot.s * rot.s);
5165
5166 rot.x /= length;
5167 rot.y /= length;
5168 rot.z /= length;
5169 rot.s /= length;
5170 }
5171 5219
5172 double angle = 2 * Math.Acos(rot.s); 5220 double angle = 2 * Math.Acos(rot.s);
5221 if (angle > Math.PI)
5222 angle = 2 * Math.PI - angle;
5173 5223
5174 return angle; 5224 return angle;
5175 } 5225 }
@@ -6687,7 +6737,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6687 PSYS_SRC_TARGET_KEY = 20, 6737 PSYS_SRC_TARGET_KEY = 20,
6688 PSYS_SRC_OMEGA = 21, 6738 PSYS_SRC_OMEGA = 21,
6689 PSYS_SRC_ANGLE_BEGIN = 22, 6739 PSYS_SRC_ANGLE_BEGIN = 22,
6690 PSYS_SRC_ANGLE_END = 23 6740 PSYS_SRC_ANGLE_END = 23,
6741 PSYS_PART_BLEND_FUNC_SOURCE = 24,
6742 PSYS_PART_BLEND_FUNC_DEST = 25,
6743 PSYS_PART_START_GLOW = 26,
6744 PSYS_PART_END_GLOW = 27
6691 } 6745 }
6692 6746
6693 internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags) 6747 internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags)
@@ -6713,6 +6767,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6713 ps.BurstRate = 0.1f; 6767 ps.BurstRate = 0.1f;
6714 ps.PartMaxAge = 10.0f; 6768 ps.PartMaxAge = 10.0f;
6715 ps.BurstPartCount = 1; 6769 ps.BurstPartCount = 1;
6770 ps.BlendFuncSource = ScriptBaseClass.PSYS_PART_BF_SOURCE_ALPHA;
6771 ps.BlendFuncDest = ScriptBaseClass.PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA;
6772 ps.PartStartGlow = 0.0f;
6773 ps.PartEndGlow = 0.0f;
6774
6716 return ps; 6775 return ps;
6717 } 6776 }
6718 6777
@@ -6747,6 +6806,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6747 LSL_Vector tempv = new LSL_Vector(); 6806 LSL_Vector tempv = new LSL_Vector();
6748 6807
6749 float tempf = 0; 6808 float tempf = 0;
6809 int tmpi = 0;
6750 6810
6751 for (int i = 0; i < rules.Length; i += 2) 6811 for (int i = 0; i < rules.Length; i += 2)
6752 { 6812 {
@@ -6805,7 +6865,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6805 break; 6865 break;
6806 6866
6807 case (int)ScriptBaseClass.PSYS_SRC_PATTERN: 6867 case (int)ScriptBaseClass.PSYS_SRC_PATTERN:
6808 int tmpi = (int)rules.GetLSLIntegerItem(i + 1); 6868 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
6809 prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; 6869 prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi;
6810 break; 6870 break;
6811 6871
@@ -6825,6 +6885,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6825 prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. 6885 prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
6826 break; 6886 break;
6827 6887
6888 case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_SOURCE:
6889 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
6890 prules.BlendFuncSource = (byte)tmpi;
6891 break;
6892
6893 case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_DEST:
6894 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
6895 prules.BlendFuncDest = (byte)tmpi;
6896 break;
6897
6898 case (int)ScriptBaseClass.PSYS_PART_START_GLOW:
6899 tempf = (float)rules.GetLSLFloatItem(i + 1);
6900 prules.PartStartGlow = (float)tempf;
6901 break;
6902
6903 case (int)ScriptBaseClass.PSYS_PART_END_GLOW:
6904 tempf = (float)rules.GetLSLFloatItem(i + 1);
6905 prules.PartEndGlow = (float)tempf;
6906 break;
6907
6828 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE: 6908 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE:
6829 prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1)); 6909 prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1));
6830 break; 6910 break;
@@ -8255,7 +8335,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8255 return null; 8335 return null;
8256 8336
8257 string ph = rules.Data[idx++].ToString(); 8337 string ph = rules.Data[idx++].ToString();
8258 parentgrp.ScriptSetPhantomStatus(ph.Equals("1")); 8338 part.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1"));
8259 8339
8260 break; 8340 break;
8261 8341
@@ -8308,7 +8388,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8308 return null; 8388 return null;
8309 string temp = rules.Data[idx++].ToString(); 8389 string temp = rules.Data[idx++].ToString();
8310 8390
8311 parentgrp.ScriptSetTemporaryStatus(temp.Equals("1")); 8391 part.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1"));
8312 8392
8313 break; 8393 break;
8314 8394
@@ -8846,8 +8926,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8846 int idx=0; 8926 int idx=0;
8847 while (idx < rules.Length) 8927 while (idx < rules.Length)
8848 { 8928 {
8849 int code=(int)rules.GetLSLIntegerItem(idx++); 8929 int code = (int)rules.GetLSLIntegerItem(idx++);
8850 int remain=rules.Length-idx; 8930 int remain = rules.Length - idx;
8851 8931
8852 switch (code) 8932 switch (code)
8853 { 8933 {
@@ -8920,7 +9000,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8920 break; 9000 break;
8921 9001
8922 case ScriptBaseClass.PRIM_TYPE_SCULPT: 9002 case ScriptBaseClass.PRIM_TYPE_SCULPT:
8923 res.Add(Shape.SculptTexture.ToString()); 9003 res.Add(new LSL_String(Shape.SculptTexture.ToString()));
8924 res.Add(new LSL_Integer(Shape.SculptType)); 9004 res.Add(new LSL_Integer(Shape.SculptType));
8925 break; 9005 break;
8926 9006
@@ -9262,7 +9342,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9262 )); 9342 ));
9263 break; 9343 break;
9264 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 9344 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
9265 if(remain < 3) 9345
9346 // TODO: Should be issuing a runtime script warning in this case.
9347 if (remain < 2)
9266 return null; 9348 return null;
9267 9349
9268 return rules.GetSublist(idx, -1); 9350 return rules.GetSublist(idx, -1);
@@ -12673,6 +12755,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12673 public void llSetSoundQueueing(int queue) 12755 public void llSetSoundQueueing(int queue)
12674 { 12756 {
12675 m_host.AddScriptLPS(1); 12757 m_host.AddScriptLPS(1);
12758
12759 if (m_SoundModule != null)
12760 m_SoundModule.SetSoundQueueing(m_host.UUID, queue == ScriptBaseClass.TRUE.value);
12676 } 12761 }
12677 12762
12678 public void llCollisionSprite(string impact_sprite) 12763 public void llCollisionSprite(string impact_sprite)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
index 1d6cb6d..b13a5ae 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
@@ -434,6 +434,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
434 } 434 }
435 return wl; 435 return wl;
436 } 436 }
437
437 /// <summary> 438 /// <summary>
438 /// Set the current Windlight scene 439 /// Set the current Windlight scene
439 /// </summary> 440 /// </summary>
@@ -446,13 +447,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
446 LSShoutError("LightShare functions are not enabled."); 447 LSShoutError("LightShare functions are not enabled.");
447 return 0; 448 return 0;
448 } 449 }
449 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 450
451 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID))
450 { 452 {
451 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); 453 ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
452 return 0; 454
455 if (sp == null || sp.GodLevel < 200)
456 {
457 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners.");
458 return 0;
459 }
453 } 460 }
461
454 int success = 0; 462 int success = 0;
455 m_host.AddScriptLPS(1); 463 m_host.AddScriptLPS(1);
464
456 if (LightShareModule.EnableWindlight) 465 if (LightShareModule.EnableWindlight)
457 { 466 {
458 RegionLightShareData wl = getWindlightProfileFromRules(rules); 467 RegionLightShareData wl = getWindlightProfileFromRules(rules);
@@ -465,8 +474,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
465 LSShoutError("Windlight module is disabled"); 474 LSShoutError("Windlight module is disabled");
466 return 0; 475 return 0;
467 } 476 }
477
468 return success; 478 return success;
469 } 479 }
480
470 public void lsClearWindlightScene() 481 public void lsClearWindlightScene()
471 { 482 {
472 if (!m_LSFunctionsEnabled) 483 if (!m_LSFunctionsEnabled)
@@ -474,17 +485,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
474 LSShoutError("LightShare functions are not enabled."); 485 LSShoutError("LightShare functions are not enabled.");
475 return; 486 return;
476 } 487 }
477 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 488
489 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID))
478 { 490 {
479 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); 491 ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
480 return; 492
493 if (sp == null || sp.GodLevel < 200)
494 {
495 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners.");
496 return;
497 }
481 } 498 }
482 499
483 m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.valid = false; 500 m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.valid = false;
484 if (m_host.ParentGroup.Scene.SimulationDataService != null) 501 if (m_host.ParentGroup.Scene.SimulationDataService != null)
485 m_host.ParentGroup.Scene.SimulationDataService.RemoveRegionWindlightSettings(m_host.ParentGroup.Scene.RegionInfo.RegionID); 502 m_host.ParentGroup.Scene.SimulationDataService.RemoveRegionWindlightSettings(m_host.ParentGroup.Scene.RegionInfo.RegionID);
503
486 m_host.ParentGroup.Scene.EventManager.TriggerOnSaveNewWindlightProfile(); 504 m_host.ParentGroup.Scene.EventManager.TriggerOnSaveNewWindlightProfile();
487 } 505 }
506
488 /// <summary> 507 /// <summary>
489 /// Set the current Windlight scene to a target avatar 508 /// Set the current Windlight scene to a target avatar
490 /// </summary> 509 /// </summary>
@@ -497,13 +516,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
497 LSShoutError("LightShare functions are not enabled."); 516 LSShoutError("LightShare functions are not enabled.");
498 return 0; 517 return 0;
499 } 518 }
500 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 519
520 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID))
501 { 521 {
502 LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); 522 ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
503 return 0; 523
524 if (sp == null || sp.GodLevel < 200)
525 {
526 LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners.");
527 return 0;
528 }
504 } 529 }
530
505 int success = 0; 531 int success = 0;
506 m_host.AddScriptLPS(1); 532 m_host.AddScriptLPS(1);
533
507 if (LightShareModule.EnableWindlight) 534 if (LightShareModule.EnableWindlight)
508 { 535 {
509 RegionLightShareData wl = getWindlightProfileFromRules(rules); 536 RegionLightShareData wl = getWindlightProfileFromRules(rules);
@@ -515,8 +542,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
515 LSShoutError("Windlight module is disabled"); 542 LSShoutError("Windlight module is disabled");
516 return 0; 543 return 0;
517 } 544 }
545
518 return success; 546 return success;
519 } 547 }
520
521 } 548 }
522} 549} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index bd776b6..edcdfbc 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -319,7 +319,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
319 319
320 object[] convertedParms = new object[parms.Length]; 320 object[] convertedParms = new object[parms.Length];
321 for (int i = 0; i < parms.Length; i++) 321 for (int i = 0; i < parms.Length; i++)
322 convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname); 322 convertedParms[i] = ConvertFromLSL(parms[i], signature[i], fname);
323 323
324 // now call the function, the contract with the function is that it will always return 324 // now call the function, the contract with the function is that it will always return
325 // non-null but don't trust it completely 325 // non-null but don't trust it completely
@@ -448,7 +448,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
448 } 448 }
449 } 449 }
450 450
451 MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname)); 451 MODError(String.Format("{0}: parameter type mismatch; expecting {1}, type(parm)={2}", fname, type.Name, lslparm.GetType()));
452 return null; 452 return null;
453 } 453 }
454 454
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 9c148d1..7081416 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -3005,6 +3005,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3005 return ret; 3005 return ret;
3006 } 3006 }
3007 3007
3008 public LSL_Vector osGetRegionSize()
3009 {
3010 CheckThreatLevel(ThreatLevel.None, "osGetRegionSize");
3011 m_host.AddScriptLPS(1);
3012
3013 bool isMegaregion;
3014 IRegionCombinerModule rcMod = World.RequestModuleInterface<IRegionCombinerModule>();
3015 if (rcMod != null)
3016 isMegaregion = rcMod.IsRootForMegaregion(World.RegionInfo.RegionID);
3017 else
3018 isMegaregion = false;
3019
3020 if (isMegaregion)
3021 {
3022 Vector2 size = rcMod.GetSizeOfMegaregion(World.RegionInfo.RegionID);
3023 return new LSL_Vector(size.X, size.Y, Constants.RegionHeight);
3024 }
3025 else
3026 {
3027 return new LSL_Vector((float)Constants.RegionSize, (float)Constants.RegionSize, Constants.RegionHeight);
3028 }
3029 }
3030
3008 public int osGetSimulatorMemory() 3031 public int osGetSimulatorMemory()
3009 { 3032 {
3010 CheckThreatLevel(ThreatLevel.Moderate, "osGetSimulatorMemory"); 3033 CheckThreatLevel(ThreatLevel.Moderate, "osGetSimulatorMemory");
@@ -3043,7 +3066,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3043 sp.ControllingClient.Kick(alert); 3066 sp.ControllingClient.Kick(alert);
3044 3067
3045 // ...and close on our side 3068 // ...and close on our side
3046 sp.Scene.IncomingCloseAgent(sp.UUID, false); 3069 sp.Scene.CloseAgent(sp.UUID, false);
3047 } 3070 }
3048 }); 3071 });
3049 } 3072 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index a47e452..181399d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -353,6 +353,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
353 // Position of a sensor in a child prim attached to an avatar 353 // Position of a sensor in a child prim attached to an avatar
354 // will be still wrong. 354 // will be still wrong.
355 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 355 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
356
357 // Don't proceed if the avatar for this attachment has since been removed from the scene.
358 if (avatar == null)
359 return sensedEntities;
360
356 fromRegionPos = avatar.AbsolutePosition; 361 fromRegionPos = avatar.AbsolutePosition;
357 q = avatar.Rotation; 362 q = avatar.Rotation;
358 } 363 }
@@ -363,7 +368,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
363 368
364 Vector3 ZeroVector = new Vector3(0, 0, 0); 369 Vector3 ZeroVector = new Vector3(0, 0, 0);
365 370
366 bool nameSearch = (ts.name != null && ts.name != ""); 371 bool nameSearch = !string.IsNullOrEmpty(ts.name);
367 372
368 foreach (EntityBase ent in Entities) 373 foreach (EntityBase ent in Entities)
369 { 374 {
@@ -483,6 +488,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
483 // Position of a sensor in a child prim attached to an avatar 488 // Position of a sensor in a child prim attached to an avatar
484 // will be still wrong. 489 // will be still wrong.
485 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 490 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
491
492 // Don't proceed if the avatar for this attachment has since been removed from the scene.
486 if (avatar == null) 493 if (avatar == null)
487 return sensedEntities; 494 return sensedEntities;
488 fromRegionPos = avatar.AbsolutePosition; 495 fromRegionPos = avatar.AbsolutePosition;
@@ -601,7 +608,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
601 return sensedEntities; 608 return sensedEntities;
602 senseEntity(sp); 609 senseEntity(sp);
603 } 610 }
604 else if (ts.name != null && ts.name != "") 611 else if (!string.IsNullOrEmpty(ts.name))
605 { 612 {
606 ScenePresence sp; 613 ScenePresence sp;
607 // Try lookup by name will return if/when found 614 // Try lookup by name will return if/when found
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
index 6d218a6..9137c69 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index daf89e5..d211a2b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -332,7 +332,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
332 void llSensorRemove(); 332 void llSensorRemove();
333 void llSensorRepeat(string name, string id, int type, double range, double arc, double rate); 333 void llSensorRepeat(string name, string id, int type, double range, double arc, double rate);
334 void llSetAlpha(double alpha, int face); 334 void llSetAlpha(double alpha, int face);
335 void llSetAngularVelocity(LSL_Vector angvelocity, int local);
336 void llSetBuoyancy(double buoyancy); 335 void llSetBuoyancy(double buoyancy);
337 void llSetCameraAtOffset(LSL_Vector offset); 336 void llSetCameraAtOffset(LSL_Vector offset);
338 void llSetCameraEyeOffset(LSL_Vector offset); 337 void llSetCameraEyeOffset(LSL_Vector offset);
@@ -340,9 +339,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
340 void llSetCameraParams(LSL_List rules); 339 void llSetCameraParams(LSL_List rules);
341 void llSetClickAction(int action); 340 void llSetClickAction(int action);
342 void llSetColor(LSL_Vector color, int face); 341 void llSetColor(LSL_Vector color, int face);
342 void llSetContentType(LSL_Key id, LSL_Integer type);
343 void llSetDamage(double damage); 343 void llSetDamage(double damage);
344 void llSetForce(LSL_Vector force, int local); 344 void llSetForce(LSL_Vector force, int local);
345 void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local); 345 void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local);
346 void llSetAngularVelocity(LSL_Vector angularVelocity, int local);
346 void llSetHoverHeight(double height, int water, double tau); 347 void llSetHoverHeight(double height, int water, double tau);
347 void llSetInventoryPermMask(string item, int mask, int value); 348 void llSetInventoryPermMask(string item, int mask, int value);
348 void llSetLinkAlpha(int linknumber, double alpha, int face); 349 void llSetLinkAlpha(int linknumber, double alpha, int face);
@@ -383,7 +384,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
383 void llSetVehicleRotationParam(int param, LSL_Rotation rot); 384 void llSetVehicleRotationParam(int param, LSL_Rotation rot);
384 void llSetVehicleType(int type); 385 void llSetVehicleType(int type);
385 void llSetVehicleVectorParam(int param, LSL_Vector vec); 386 void llSetVehicleVectorParam(int param, LSL_Vector vec);
386 void llSetVelocity(LSL_Vector velocity, int local);
387 void llShout(int channelID, string text); 387 void llShout(int channelID, string text);
388 LSL_Float llSin(double f); 388 LSL_Float llSin(double f);
389 void llSitTarget(LSL_Vector offset, LSL_Rotation rot); 389 void llSitTarget(LSL_Vector offset, LSL_Rotation rot);
@@ -434,6 +434,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
434 void llSetKeyframedMotion(LSL_List frames, LSL_List options); 434 void llSetKeyframedMotion(LSL_List frames, LSL_List options);
435 LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); 435 LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
436 LSL_List llGetPhysicsMaterial(); 436 LSL_List llGetPhysicsMaterial();
437 void llSetContentType(LSL_Key id, LSL_Integer content_type);
438 } 437 }
439} 438}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index a652cb8..d80d389 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -336,6 +336,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
336 key osGetMapTexture(); 336 key osGetMapTexture();
337 key osGetRegionMapTexture(string regionName); 337 key osGetRegionMapTexture(string regionName);
338 LSL_List osGetRegionStats(); 338 LSL_List osGetRegionStats();
339 vector osGetRegionSize();
339 340
340 int osGetSimulatorMemory(); 341 int osGetSimulatorMemory();
341 void osKickAvatar(string FirstName,string SurName,string alert); 342 void osKickAvatar(string FirstName,string SurName,string alert);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 6efa73f..e59c0be 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -107,6 +107,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
107 public const int PSYS_PART_TARGET_POS_MASK = 64; 107 public const int PSYS_PART_TARGET_POS_MASK = 64;
108 public const int PSYS_PART_TARGET_LINEAR_MASK = 128; 108 public const int PSYS_PART_TARGET_LINEAR_MASK = 128;
109 public const int PSYS_PART_EMISSIVE_MASK = 256; 109 public const int PSYS_PART_EMISSIVE_MASK = 256;
110 public const int PSYS_PART_RIBBON_MASK = 1024;
110 public const int PSYS_PART_FLAGS = 0; 111 public const int PSYS_PART_FLAGS = 0;
111 public const int PSYS_PART_START_COLOR = 1; 112 public const int PSYS_PART_START_COLOR = 1;
112 public const int PSYS_PART_START_ALPHA = 2; 113 public const int PSYS_PART_START_ALPHA = 2;
@@ -130,6 +131,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
130 public const int PSYS_SRC_OMEGA = 21; 131 public const int PSYS_SRC_OMEGA = 21;
131 public const int PSYS_SRC_ANGLE_BEGIN = 22; 132 public const int PSYS_SRC_ANGLE_BEGIN = 22;
132 public const int PSYS_SRC_ANGLE_END = 23; 133 public const int PSYS_SRC_ANGLE_END = 23;
134 public const int PSYS_PART_BLEND_FUNC_SOURCE = 24;
135 public const int PSYS_PART_BLEND_FUNC_DEST = 25;
136 public const int PSYS_PART_START_GLOW = 26;
137 public const int PSYS_PART_END_GLOW = 27;
138 public const int PSYS_PART_BF_ONE = 0;
139 public const int PSYS_PART_BF_ZERO = 1;
140 public const int PSYS_PART_BF_DEST_COLOR = 2;
141 public const int PSYS_PART_BF_SOURCE_COLOR = 3;
142 public const int PSYS_PART_BF_ONE_MINUS_DEST_COLOR = 4;
143 public const int PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR = 5;
144 public const int PSYS_PART_BF_SOURCE_ALPHA = 7;
145 public const int PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA = 9;
133 public const int PSYS_SRC_PATTERN_DROP = 1; 146 public const int PSYS_SRC_PATTERN_DROP = 1;
134 public const int PSYS_SRC_PATTERN_EXPLODE = 2; 147 public const int PSYS_SRC_PATTERN_EXPLODE = 2;
135 public const int PSYS_SRC_PATTERN_ANGLE = 4; 148 public const int PSYS_SRC_PATTERN_ANGLE = 4;
@@ -361,6 +374,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
361 public const int HTTP_CUSTOM_HEADER = 5; 374 public const int HTTP_CUSTOM_HEADER = 5;
362 public const int HTTP_PRAGMA_NO_CACHE = 6; 375 public const int HTTP_PRAGMA_NO_CACHE = 6;
363 376
377 // llSetContentType
378 public const int CONTENT_TYPE_TEXT = 0; //text/plain
379 public const int CONTENT_TYPE_HTML = 1; //text/html
380 public const int CONTENT_TYPE_XML = 2; //application/xml
381 public const int CONTENT_TYPE_XHTML = 3; //application/xhtml+xml
382 public const int CONTENT_TYPE_ATOM = 4; //application/atom+xml
383 public const int CONTENT_TYPE_JSON = 5; //application/json
384 public const int CONTENT_TYPE_LLSD = 6; //application/llsd+xml
385 public const int CONTENT_TYPE_FORM = 7; //application/x-www-form-urlencoded
386 public const int CONTENT_TYPE_RSS = 8; //application/rss+xml
387
364 public const int PRIM_MATERIAL = 2; 388 public const int PRIM_MATERIAL = 2;
365 public const int PRIM_PHYSICS = 3; 389 public const int PRIM_PHYSICS = 3;
366 public const int PRIM_TEMP_ON_REZ = 4; 390 public const int PRIM_TEMP_ON_REZ = 4;
@@ -772,8 +796,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
772 /// process message parameter as regex 796 /// process message parameter as regex
773 /// </summary> 797 /// </summary>
774 public const int OS_LISTEN_REGEX_MESSAGE = 0x2; 798 public const int OS_LISTEN_REGEX_MESSAGE = 0x2;
775
776 public const int CONTENT_TYPE_TEXT = 0;
777 public const int CONTENT_TYPE_HTML = 1;
778 } 799 }
779} 800}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
index 6f3677c..4fc8d65 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs
@@ -1495,11 +1495,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1495 m_LSL_Functions.llSetAlpha(alpha, face); 1495 m_LSL_Functions.llSetAlpha(alpha, face);
1496 } 1496 }
1497 1497
1498 public void llSetAngularVelocity(LSL_Vector angvelocity, int local)
1499 {
1500 m_LSL_Functions.llSetAngularVelocity(angvelocity, local);
1501 }
1502
1503 public void llSetBuoyancy(double buoyancy) 1498 public void llSetBuoyancy(double buoyancy)
1504 { 1499 {
1505 m_LSL_Functions.llSetBuoyancy(buoyancy); 1500 m_LSL_Functions.llSetBuoyancy(buoyancy);
@@ -1535,6 +1530,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1535 m_LSL_Functions.llSetColor(color, face); 1530 m_LSL_Functions.llSetColor(color, face);
1536 } 1531 }
1537 1532
1533 public void llSetContentType(LSL_Key id, LSL_Integer type)
1534 {
1535 m_LSL_Functions.llSetContentType(id, type);
1536 }
1537
1538 public void llSetDamage(double damage) 1538 public void llSetDamage(double damage)
1539 { 1539 {
1540 m_LSL_Functions.llSetDamage(damage); 1540 m_LSL_Functions.llSetDamage(damage);
@@ -1550,6 +1550,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1550 m_LSL_Functions.llSetForceAndTorque(force, torque, local); 1550 m_LSL_Functions.llSetForceAndTorque(force, torque, local);
1551 } 1551 }
1552 1552
1553 public void llSetAngularVelocity(LSL_Vector force, int local)
1554 {
1555 m_LSL_Functions.llSetAngularVelocity(force, local);
1556 }
1557
1553 public void llSetHoverHeight(double height, int water, double tau) 1558 public void llSetHoverHeight(double height, int water, double tau)
1554 { 1559 {
1555 m_LSL_Functions.llSetHoverHeight(height, water, tau); 1560 m_LSL_Functions.llSetHoverHeight(height, water, tau);
@@ -1740,11 +1745,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
1740 m_LSL_Functions.llSetVehicleVectorParam(param, vec); 1745 m_LSL_Functions.llSetVehicleVectorParam(param, vec);
1741 } 1746 }
1742 1747
1743 public void llSetVelocity(LSL_Vector velocity, int local)
1744 {
1745 m_LSL_Functions.llSetVelocity(velocity, local);
1746 }
1747
1748 public void llShout(int channelID, string text) 1748 public void llShout(int channelID, string text)
1749 { 1749 {
1750 m_LSL_Functions.llShout(channelID, text); 1750 m_LSL_Functions.llShout(channelID, text);
@@ -2014,10 +2014,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
2014 { 2014 {
2015 return m_LSL_Functions.llGetPhysicsMaterial(); 2015 return m_LSL_Functions.llGetPhysicsMaterial();
2016 } 2016 }
2017
2018 public void llSetContentType(LSL_Key id, LSL_Integer content_type)
2019 {
2020 m_LSL_Functions.llSetContentType(id, content_type);
2021 }
2022 } 2017 }
2023} 2018}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index b63773b..9cf7b35 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -858,6 +858,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
858 return m_OSSL_Functions.osGetRegionStats(); 858 return m_OSSL_Functions.osGetRegionStats();
859 } 859 }
860 860
861 public vector osGetRegionSize()
862 {
863 return m_OSSL_Functions.osGetRegionSize();
864 }
865
861 /// <summary> 866 /// <summary>
862 /// Returns the amount of memory in use by the Simulator Daemon. 867 /// Returns the amount of memory in use by the Simulator Daemon.
863 /// Amount in bytes - if >= 4GB, returns 4GB. (LSL is not 64-bit aware) 868 /// Amount in bytes - if >= 4GB, returns 4GB. (LSL is not 64-bit aware)
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
index 9e32f40..6aa717d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
@@ -937,7 +937,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
937 { 937 {
938 string retval = null; 938 string retval = null;
939 if (value is int) 939 if (value is int)
940 retval = ((int)value).ToString(); 940 retval = String.Format("new LSL_Types.LSLInteger({0})",((int)value).ToString());
941 else if (value is float) 941 else if (value is float)
942 retval = String.Format("new LSL_Types.LSLFloat({0})",((float)value).ToString()); 942 retval = String.Format("new LSL_Types.LSLFloat({0})",((float)value).ToString());
943 else if (value is string) 943 else if (value is string)
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index b71afe3..a1b8d85 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -610,6 +610,7 @@ namespace SecondLife
610 results = CScodeProvider.CompileAssemblyFromSource( 610 results = CScodeProvider.CompileAssemblyFromSource(
611 parameters, Script); 611 parameters, Script);
612 } 612 }
613
613 // Deal with an occasional segv in the compiler. 614 // Deal with an occasional segv in the compiler.
614 // Rarely, if ever, occurs twice in succession. 615 // Rarely, if ever, occurs twice in succession.
615 // Line # == 0 and no file name are indications that 616 // Line # == 0 and no file name are indications that
@@ -617,7 +618,7 @@ namespace SecondLife
617 // error log. 618 // error log.
618 if (results.Errors.Count > 0) 619 if (results.Errors.Count > 0)
619 { 620 {
620 if (!retried && (results.Errors[0].FileName == null || results.Errors[0].FileName == String.Empty) && 621 if (!retried && string.IsNullOrEmpty(results.Errors[0].FileName) &&
621 results.Errors[0].Line == 0) 622 results.Errors[0].Line == 0)
622 { 623 {
623 // System.Console.WriteLine("retrying failed compilation"); 624 // System.Console.WriteLine("retrying failed compilation");
@@ -647,15 +648,19 @@ namespace SecondLife
647 "language type \"" + lang.ToString() + "\""); 648 "language type \"" + lang.ToString() + "\"");
648 } 649 }
649 650
650 // Check result 651// foreach (Type type in results.CompiledAssembly.GetTypes())
651 // Go through errors 652// {
653// foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static))
654// {
655// m_log.DebugFormat("[COMPILER]: {0}.{1}", type.FullName, method.Name);
656// }
657// }
652 658
653 // 659 //
654 // WARNINGS AND ERRORS 660 // WARNINGS AND ERRORS
655 // 661 //
656 bool hadErrors = false; 662 bool hadErrors = false;
657 string errtext = String.Empty; 663 string errtext = String.Empty;
658
659 if (results.Errors.Count > 0) 664 if (results.Errors.Count > 0)
660 { 665 {
661 foreach (CompilerError CompErr in results.Errors) 666 foreach (CompilerError CompErr in results.Errors)
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/LSL2CSCodeTransformer.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/LSL2CSCodeTransformer.cs
index e77b3d2..0fb3574 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/LSL2CSCodeTransformer.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/LSL2CSCodeTransformer.cs
@@ -27,12 +27,16 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
30using Tools; 32using Tools;
31 33
32namespace OpenSim.Region.ScriptEngine.Shared.CodeTools 34namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
33{ 35{
34 public class LSL2CSCodeTransformer 36 public class LSL2CSCodeTransformer
35 { 37 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39
36 private SYMBOL m_astRoot = null; 40 private SYMBOL m_astRoot = null;
37 private static Dictionary<string, string> m_datatypeLSL2OpenSim = null; 41 private static Dictionary<string, string> m_datatypeLSL2OpenSim = null;
38 42
@@ -78,6 +82,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
78 /// <param name="s">The current node to transform.</param> 82 /// <param name="s">The current node to transform.</param>
79 private void TransformNode(SYMBOL s) 83 private void TransformNode(SYMBOL s)
80 { 84 {
85// m_log.DebugFormat("[LSL2CSCODETRANSFORMER]: Tranforming node {0}", s);
86
81 // make sure to put type lower in the inheritance hierarchy first 87 // make sure to put type lower in the inheritance hierarchy first
82 // ie: since IdentConstant and StringConstant inherit from Constant, 88 // ie: since IdentConstant and StringConstant inherit from Constant,
83 // put IdentConstant and StringConstant before Constant 89 // put IdentConstant and StringConstant before Constant
@@ -103,10 +109,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
103 // We need to check for that here. 109 // We need to check for that here.
104 if (null != s.kids[i]) 110 if (null != s.kids[i])
105 { 111 {
112// m_log.Debug("[LSL2CSCODETRANSFORMER]: Moving down level");
113
106 if (!(s is Assignment || s is ArgumentDeclarationList) && s.kids[i] is Declaration) 114 if (!(s is Assignment || s is ArgumentDeclarationList) && s.kids[i] is Declaration)
107 AddImplicitInitialization(s, i); 115 AddImplicitInitialization(s, i);
108 116
109 TransformNode((SYMBOL) s.kids[i]); 117 TransformNode((SYMBOL) s.kids[i]);
118
119// m_log.Debug("[LSL2CSCODETRANSFORMER]: Moving up level");
110 } 120 }
111 } 121 }
112 } 122 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
index 5b5c4fd..d163438 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
index 77e087c..b92f3a3 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
@@ -762,6 +762,7 @@ default
762 public void TestIfStatement() 762 public void TestIfStatement()
763 { 763 {
764 TestHelpers.InMethod(); 764 TestHelpers.InMethod();
765// TestHelpers.EnableLogging();
765 766
766 string input = @"// let's test if statements 767 string input = @"// let's test if statements
767 768
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/LSL_EventTests.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/LSL_EventTests.cs
new file mode 100644
index 0000000..67ce10a
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/LSL_EventTests.cs
@@ -0,0 +1,359 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Text.RegularExpressions;
31using NUnit.Framework;
32using OpenSim.Region.ScriptEngine.Shared.CodeTools;
33using OpenSim.Tests.Common;
34
35namespace OpenSim.Region.ScriptEngine.Shared.Tests
36{
37 public class LSL_EventTests : OpenSimTestCase
38 {
39 CSCodeGenerator m_cg = new CSCodeGenerator();
40
41 [Test]
42 public void TestBadEvent()
43 {
44 TestHelpers.InMethod();
45// TestHelpers.EnableLogging();
46
47 TestCompile("default { bad() {} }", true);
48 }
49
50 [Test]
51 public void TestAttachEvent()
52 {
53 TestHelpers.InMethod();
54// TestHelpers.EnableLogging();
55
56 TestKeyArgEvent("attach");
57 }
58
59 [Test]
60 public void TestObjectRezEvent()
61 {
62 TestHelpers.InMethod();
63// TestHelpers.EnableLogging();
64
65 TestKeyArgEvent("object_rez");
66 }
67
68 [Test]
69 public void TestMovingEndEvent()
70 {
71 TestHelpers.InMethod();
72// TestHelpers.EnableLogging();
73
74 TestVoidArgEvent("moving_end");
75 }
76
77 [Test]
78 public void TestMovingStartEvent()
79 {
80 TestHelpers.InMethod();
81// TestHelpers.EnableLogging();
82
83 TestVoidArgEvent("moving_start");
84 }
85
86 [Test]
87 public void TestNoSensorEvent()
88 {
89 TestHelpers.InMethod();
90// TestHelpers.EnableLogging();
91
92 TestVoidArgEvent("no_sensor");
93 }
94
95 [Test]
96 public void TestNotAtRotTargetEvent()
97 {
98 TestHelpers.InMethod();
99// TestHelpers.EnableLogging();
100
101 TestVoidArgEvent("not_at_rot_target");
102 }
103
104 [Test]
105 public void TestNotAtTargetEvent()
106 {
107 TestHelpers.InMethod();
108// TestHelpers.EnableLogging();
109
110 TestVoidArgEvent("not_at_target");
111 }
112
113 [Test]
114 public void TestStateEntryEvent()
115 {
116 TestHelpers.InMethod();
117// TestHelpers.EnableLogging();
118
119 TestVoidArgEvent("state_entry");
120 }
121
122 [Test]
123 public void TestStateExitEvent()
124 {
125 TestHelpers.InMethod();
126// TestHelpers.EnableLogging();
127
128 TestVoidArgEvent("state_exit");
129 }
130
131 [Test]
132 public void TestTimerEvent()
133 {
134 TestHelpers.InMethod();
135// TestHelpers.EnableLogging();
136
137 TestVoidArgEvent("timer");
138 }
139
140 private void TestVoidArgEvent(string eventName)
141 {
142 TestCompile("default { " + eventName + "() {} }", false);
143 TestCompile("default { " + eventName + "(integer n) {} }", true);
144 }
145
146 [Test]
147 public void TestChangedEvent()
148 {
149 TestHelpers.InMethod();
150// TestHelpers.EnableLogging();
151
152 TestIntArgEvent("changed");
153 }
154
155 [Test]
156 public void TestCollisionEvent()
157 {
158 TestHelpers.InMethod();
159// TestHelpers.EnableLogging();
160
161 TestIntArgEvent("collision");
162 }
163
164 [Test]
165 public void TestCollisionStartEvent()
166 {
167 TestHelpers.InMethod();
168// TestHelpers.EnableLogging();
169
170 TestIntArgEvent("collision_start");
171 }
172
173 [Test]
174 public void TestCollisionEndEvent()
175 {
176 TestHelpers.InMethod();
177// TestHelpers.EnableLogging();
178
179 TestIntArgEvent("collision_end");
180 }
181
182 [Test]
183 public void TestOnRezEvent()
184 {
185 TestHelpers.InMethod();
186// TestHelpers.EnableLogging();
187
188 TestIntArgEvent("on_rez");
189 }
190
191 [Test]
192 public void TestRunTimePermissionsEvent()
193 {
194 TestHelpers.InMethod();
195// TestHelpers.EnableLogging();
196
197 TestIntArgEvent("run_time_permissions");
198 }
199
200 [Test]
201 public void TestSensorEvent()
202 {
203 TestHelpers.InMethod();
204// TestHelpers.EnableLogging();
205
206 TestIntArgEvent("sensor");
207 }
208
209 [Test]
210 public void TestTouchEvent()
211 {
212 TestHelpers.InMethod();
213// TestHelpers.EnableLogging();
214
215 TestIntArgEvent("touch");
216 }
217
218 [Test]
219 public void TestTouchStartEvent()
220 {
221 TestHelpers.InMethod();
222// TestHelpers.EnableLogging();
223
224 TestIntArgEvent("touch_start");
225 }
226
227 [Test]
228 public void TestTouchEndEvent()
229 {
230 TestHelpers.InMethod();
231// TestHelpers.EnableLogging();
232
233 TestIntArgEvent("touch_end");
234 }
235
236 [Test]
237 public void TestLandCollisionEvent()
238 {
239 TestHelpers.InMethod();
240// TestHelpers.EnableLogging();
241
242 TestVectorArgEvent("land_collision");
243 }
244
245 [Test]
246 public void TestLandCollisionStartEvent()
247 {
248 TestHelpers.InMethod();
249// TestHelpers.EnableLogging();
250
251 TestVectorArgEvent("land_collision_start");
252 }
253
254 [Test]
255 public void TestLandCollisionEndEvent()
256 {
257 TestHelpers.InMethod();
258// TestHelpers.EnableLogging();
259
260 TestVectorArgEvent("land_collision_end");
261 }
262
263 [Test]
264 public void TestAtRotTargetEvent()
265 {
266 TestHelpers.InMethod();
267// TestHelpers.EnableLogging();
268
269 TestIntRotRotArgEvent("at_rot_target");
270 }
271
272 [Test]
273 public void TestAtTargetEvent()
274 {
275 TestHelpers.InMethod();
276// TestHelpers.EnableLogging();
277
278 TestIntVecVecArgEvent("at_target");
279 }
280
281 [Test]
282 public void TestControlEvent()
283 {
284 TestHelpers.InMethod();
285// TestHelpers.EnableLogging();
286
287 TestKeyIntIntArgEvent("control");
288 }
289
290 private void TestIntArgEvent(string eventName)
291 {
292 TestCompile("default { " + eventName + "(integer n) {} }", false);
293 TestCompile("default { " + eventName + "{{}} }", true);
294 TestCompile("default { " + eventName + "(string s) {{}} }", true);
295 TestCompile("default { " + eventName + "(integer n, integer o) {{}} }", true);
296 }
297
298 private void TestKeyArgEvent(string eventName)
299 {
300 TestCompile("default { " + eventName + "(key k) {} }", false);
301 TestCompile("default { " + eventName + "{{}} }", true);
302 TestCompile("default { " + eventName + "(string s) {{}} }", true);
303 TestCompile("default { " + eventName + "(key k, key l) {{}} }", true);
304 }
305
306 private void TestVectorArgEvent(string eventName)
307 {
308 TestCompile("default { " + eventName + "(vector v) {} }", false);
309 TestCompile("default { " + eventName + "{{}} }", true);
310 TestCompile("default { " + eventName + "(string s) {{}} }", true);
311 TestCompile("default { " + eventName + "(vector v, vector w) {{}} }", true);
312 }
313
314 private void TestIntRotRotArgEvent(string eventName)
315 {
316 TestCompile("default { " + eventName + "(integer n, rotation r, rotation s) {} }", false);
317 TestCompile("default { " + eventName + "{{}} }", true);
318 TestCompile("default { " + eventName + "(string s) {{}} }", true);
319 TestCompile("default { " + eventName + "(integer n, rotation r, rotation s, rotation t) {{}} }", true);
320 }
321
322 private void TestIntVecVecArgEvent(string eventName)
323 {
324 TestCompile("default { " + eventName + "(integer n, vector v, vector w) {} }", false);
325 TestCompile("default { " + eventName + "{{}} }", true);
326 TestCompile("default { " + eventName + "(string s) {{}} }", true);
327 TestCompile("default { " + eventName + "(integer n, vector v, vector w, vector x) {{}} }", true);
328 }
329
330 private void TestKeyIntIntArgEvent(string eventName)
331 {
332 TestCompile("default { " + eventName + "(key k, integer n, integer o) {} }", false);
333 TestCompile("default { " + eventName + "{{}} }", true);
334 TestCompile("default { " + eventName + "(string s) {{}} }", true);
335 TestCompile("default { " + eventName + "(key k, integer n, integer o, integer p) {{}} }", true);
336 }
337
338 private void TestCompile(string script, bool expectException)
339 {
340 bool gotException = false;
341 Exception ge = null;
342
343 try
344 {
345 m_cg.Convert(script);
346 }
347 catch (Exception e)
348 {
349 gotException = true;
350 ge = e;
351 }
352
353 Assert.That(
354 gotException,
355 Is.EqualTo(expectException),
356 "Failed on {0}, exception {1}", script, ge != null ? ge.ToString() : "n/a");
357 }
358 }
359} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/lsl.parser.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/lsl.parser.cs
index ca56cd6..44957bd 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/lsl.parser.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/lsl.parser.cs
@@ -116,9 +116,9 @@ public class StateEvent : SYMBOL{
116)yyp)){ m_name = name ; 116)yyp)){ m_name = name ;
117 kids . Add ( cs ); 117 kids . Add ( cs );
118} 118}
119 public StateEvent (Parser yyp, string name , ArgumentDeclarationList dal , CompoundStatement cs ):base(((LSLSyntax 119 public StateEvent (Parser yyp, string name , ArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
120)yyp)){ m_name = name ; 120)yyp)){ m_name = name ;
121 if (0< dal . kids . Count ) kids . Add ( dal ); 121 if (0< adl . kids . Count ) kids . Add ( adl );
122 kids . Add ( cs ); 122 kids . Add ( cs );
123} 123}
124 public override string ToString (){ return "EVENT<"+ m_name +">"; 124 public override string ToString (){ return "EVENT<"+ m_name +">";
@@ -130,20 +130,133 @@ public class StateEvent : SYMBOL{
130public override string yyname { get { return "StateEvent"; }} 130public override string yyname { get { return "StateEvent"; }}
131public override int yynum { get { return 103; }} 131public override int yynum { get { return 103; }}
132public StateEvent(Parser yyp):base(yyp){}} 132public StateEvent(Parser yyp):base(yyp){}}
133//%+ArgumentDeclarationList+104 133//%+VoidArgStateEvent+104
134public class VoidArgStateEvent : StateEvent{
135 public VoidArgStateEvent (Parser yyp, string name , CompoundStatement cs ):base(((LSLSyntax
136)yyp), name , cs ){}
137
138public override string yyname { get { return "VoidArgStateEvent"; }}
139public override int yynum { get { return 104; }}
140public VoidArgStateEvent(Parser yyp):base(yyp){}}
141//%+KeyArgStateEvent+105
142public class KeyArgStateEvent : StateEvent{
143 public KeyArgStateEvent (Parser yyp, string name , KeyArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
144)yyp), name , adl , cs ){}
145
146public override string yyname { get { return "KeyArgStateEvent"; }}
147public override int yynum { get { return 105; }}
148public KeyArgStateEvent(Parser yyp):base(yyp){}}
149//%+IntArgStateEvent+106
150public class IntArgStateEvent : StateEvent{
151 public IntArgStateEvent (Parser yyp, string name , IntArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
152)yyp), name , adl , cs ){}
153
154public override string yyname { get { return "IntArgStateEvent"; }}
155public override int yynum { get { return 106; }}
156public IntArgStateEvent(Parser yyp):base(yyp){}}
157//%+VectorArgStateEvent+107
158public class VectorArgStateEvent : StateEvent{
159 public VectorArgStateEvent (Parser yyp, string name , VectorArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
160)yyp), name , adl , cs ){}
161
162public override string yyname { get { return "VectorArgStateEvent"; }}
163public override int yynum { get { return 107; }}
164public VectorArgStateEvent(Parser yyp):base(yyp){}}
165//%+IntRotRotArgStateEvent+108
166public class IntRotRotArgStateEvent : StateEvent{
167 public IntRotRotArgStateEvent (Parser yyp, string name , IntRotRotArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
168)yyp), name , adl , cs ){}
169
170public override string yyname { get { return "IntRotRotArgStateEvent"; }}
171public override int yynum { get { return 108; }}
172public IntRotRotArgStateEvent(Parser yyp):base(yyp){}}
173//%+IntVecVecArgStateEvent+109
174public class IntVecVecArgStateEvent : StateEvent{
175 public IntVecVecArgStateEvent (Parser yyp, string name , IntVecVecArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
176)yyp), name , adl , cs ){}
177
178public override string yyname { get { return "IntVecVecArgStateEvent"; }}
179public override int yynum { get { return 109; }}
180public IntVecVecArgStateEvent(Parser yyp):base(yyp){}}
181//%+KeyIntIntArgStateEvent+110
182public class KeyIntIntArgStateEvent : StateEvent{
183 public KeyIntIntArgStateEvent (Parser yyp, string name , KeyIntIntArgumentDeclarationList adl , CompoundStatement cs ):base(((LSLSyntax
184)yyp), name , adl , cs ){}
185
186public override string yyname { get { return "KeyIntIntArgStateEvent"; }}
187public override int yynum { get { return 110; }}
188public KeyIntIntArgStateEvent(Parser yyp):base(yyp){}}
189//%+ArgumentDeclarationList+111
134public class ArgumentDeclarationList : SYMBOL{ 190public class ArgumentDeclarationList : SYMBOL{
135 public ArgumentDeclarationList (Parser yyp, Declaration d ):base(((LSLSyntax 191 public ArgumentDeclarationList (Parser yyp, Declaration d ):base(((LSLSyntax
136)yyp)){ kids . Add ( d ); 192)yyp)){ kids . Add ( d );
137} 193}
194 public ArgumentDeclarationList (Parser yyp, Declaration d , Declaration d2 ):base(((LSLSyntax
195)yyp)){ kids . Add ( d );
196 kids . Add ( d2 );
197}
198 public ArgumentDeclarationList (Parser yyp, Declaration d , Declaration d2 , Declaration d3 ):base(((LSLSyntax
199)yyp)){ kids . Add ( d );
200 kids . Add ( d2 );
201 kids . Add ( d3 );
202}
138 public ArgumentDeclarationList (Parser yyp, ArgumentDeclarationList adl , Declaration d ):base(((LSLSyntax 203 public ArgumentDeclarationList (Parser yyp, ArgumentDeclarationList adl , Declaration d ):base(((LSLSyntax
139)yyp)){ while (0< adl . kids . Count ) kids . Add ( adl . kids . Pop ()); 204)yyp)){ while (0< adl . kids . Count ) kids . Add ( adl . kids . Pop ());
140 kids . Add ( d ); 205 kids . Add ( d );
141} 206}
142 207
143public override string yyname { get { return "ArgumentDeclarationList"; }} 208public override string yyname { get { return "ArgumentDeclarationList"; }}
144public override int yynum { get { return 104; }} 209public override int yynum { get { return 111; }}
145public ArgumentDeclarationList(Parser yyp):base(yyp){}} 210public ArgumentDeclarationList(Parser yyp):base(yyp){}}
146//%+Declaration+105 211//%+KeyArgumentDeclarationList+112
212public class KeyArgumentDeclarationList : ArgumentDeclarationList{
213 public KeyArgumentDeclarationList (Parser yyp, KeyDeclaration d ):base(((LSLSyntax
214)yyp), d ){}
215
216public override string yyname { get { return "KeyArgumentDeclarationList"; }}
217public override int yynum { get { return 112; }}
218public KeyArgumentDeclarationList(Parser yyp):base(yyp){}}
219//%+IntArgumentDeclarationList+113
220public class IntArgumentDeclarationList : ArgumentDeclarationList{
221 public IntArgumentDeclarationList (Parser yyp, IntDeclaration d ):base(((LSLSyntax
222)yyp), d ){}
223
224public override string yyname { get { return "IntArgumentDeclarationList"; }}
225public override int yynum { get { return 113; }}
226public IntArgumentDeclarationList(Parser yyp):base(yyp){}}
227//%+VectorArgumentDeclarationList+114
228public class VectorArgumentDeclarationList : ArgumentDeclarationList{
229 public VectorArgumentDeclarationList (Parser yyp, VecDeclaration d ):base(((LSLSyntax
230)yyp), d ){}
231
232public override string yyname { get { return "VectorArgumentDeclarationList"; }}
233public override int yynum { get { return 114; }}
234public VectorArgumentDeclarationList(Parser yyp):base(yyp){}}
235//%+IntRotRotArgumentDeclarationList+115
236public class IntRotRotArgumentDeclarationList : ArgumentDeclarationList{
237 public IntRotRotArgumentDeclarationList (Parser yyp, Declaration d1 , Declaration d2 , Declaration d3 ):base(((LSLSyntax
238)yyp), d1 , d2 , d3 ){}
239
240public override string yyname { get { return "IntRotRotArgumentDeclarationList"; }}
241public override int yynum { get { return 115; }}
242public IntRotRotArgumentDeclarationList(Parser yyp):base(yyp){}}
243//%+IntVecVecArgumentDeclarationList+116
244public class IntVecVecArgumentDeclarationList : ArgumentDeclarationList{
245 public IntVecVecArgumentDeclarationList (Parser yyp, Declaration d1 , Declaration d2 , Declaration d3 ):base(((LSLSyntax
246)yyp), d1 , d2 , d3 ){}
247
248public override string yyname { get { return "IntVecVecArgumentDeclarationList"; }}
249public override int yynum { get { return 116; }}
250public IntVecVecArgumentDeclarationList(Parser yyp):base(yyp){}}
251//%+KeyIntIntArgumentDeclarationList+117
252public class KeyIntIntArgumentDeclarationList : ArgumentDeclarationList{
253 public KeyIntIntArgumentDeclarationList (Parser yyp, Declaration d1 , Declaration d2 , Declaration d3 ):base(((LSLSyntax
254)yyp), d1 , d2 , d3 ){}
255
256public override string yyname { get { return "KeyIntIntArgumentDeclarationList"; }}
257public override int yynum { get { return 117; }}
258public KeyIntIntArgumentDeclarationList(Parser yyp):base(yyp){}}
259//%+Declaration+118
147public class Declaration : SYMBOL{ 260public class Declaration : SYMBOL{
148 private string m_datatype ; 261 private string m_datatype ;
149 private string m_id ; 262 private string m_id ;
@@ -163,9 +276,41 @@ public class Declaration : SYMBOL{
163} 276}
164 277
165public override string yyname { get { return "Declaration"; }} 278public override string yyname { get { return "Declaration"; }}
166public override int yynum { get { return 105; }} 279public override int yynum { get { return 118; }}
167public Declaration(Parser yyp):base(yyp){}} 280public Declaration(Parser yyp):base(yyp){}}
168//%+Typename+106 281//%+KeyDeclaration+119
282public class KeyDeclaration : Declaration{
283 public KeyDeclaration (Parser yyp, string type , string id ):base(((LSLSyntax
284)yyp), type , id ){}
285
286public override string yyname { get { return "KeyDeclaration"; }}
287public override int yynum { get { return 119; }}
288public KeyDeclaration(Parser yyp):base(yyp){}}
289//%+IntDeclaration+120
290public class IntDeclaration : Declaration{
291 public IntDeclaration (Parser yyp, string type , string id ):base(((LSLSyntax
292)yyp), type , id ){}
293
294public override string yyname { get { return "IntDeclaration"; }}
295public override int yynum { get { return 120; }}
296public IntDeclaration(Parser yyp):base(yyp){}}
297//%+VecDeclaration+121
298public class VecDeclaration : Declaration{
299 public VecDeclaration (Parser yyp, string type , string id ):base(((LSLSyntax
300)yyp), type , id ){}
301
302public override string yyname { get { return "VecDeclaration"; }}
303public override int yynum { get { return 121; }}
304public VecDeclaration(Parser yyp):base(yyp){}}
305//%+RotDeclaration+122
306public class RotDeclaration : Declaration{
307 public RotDeclaration (Parser yyp, string type , string id ):base(((LSLSyntax
308)yyp), type , id ){}
309
310public override string yyname { get { return "RotDeclaration"; }}
311public override int yynum { get { return 122; }}
312public RotDeclaration(Parser yyp):base(yyp){}}
313//%+Typename+123
169public class Typename : SYMBOL{ 314public class Typename : SYMBOL{
170 public string yytext ; 315 public string yytext ;
171 public Typename (Parser yyp, string text ):base(((LSLSyntax 316 public Typename (Parser yyp, string text ):base(((LSLSyntax
@@ -173,9 +318,9 @@ public class Typename : SYMBOL{
173} 318}
174 319
175public override string yyname { get { return "Typename"; }} 320public override string yyname { get { return "Typename"; }}
176public override int yynum { get { return 106; }} 321public override int yynum { get { return 123; }}
177public Typename(Parser yyp):base(yyp){}} 322public Typename(Parser yyp):base(yyp){}}
178//%+Event+107 323//%+Event+124
179public class Event : SYMBOL{ 324public class Event : SYMBOL{
180 public string yytext ; 325 public string yytext ;
181 public Event (Parser yyp, string text ):base(((LSLSyntax 326 public Event (Parser yyp, string text ):base(((LSLSyntax
@@ -183,9 +328,65 @@ public class Event : SYMBOL{
183} 328}
184 329
185public override string yyname { get { return "Event"; }} 330public override string yyname { get { return "Event"; }}
186public override int yynum { get { return 107; }} 331public override int yynum { get { return 124; }}
187public Event(Parser yyp):base(yyp){}} 332public Event(Parser yyp):base(yyp){}}
188//%+CompoundStatement+108 333//%+VoidArgEvent+125
334public class VoidArgEvent : Event{
335 public VoidArgEvent (Parser yyp, string text ):base(((LSLSyntax
336)yyp), text ){}
337
338public override string yyname { get { return "VoidArgEvent"; }}
339public override int yynum { get { return 125; }}
340public VoidArgEvent(Parser yyp):base(yyp){}}
341//%+KeyArgEvent+126
342public class KeyArgEvent : Event{
343 public KeyArgEvent (Parser yyp, string text ):base(((LSLSyntax
344)yyp), text ){}
345
346public override string yyname { get { return "KeyArgEvent"; }}
347public override int yynum { get { return 126; }}
348public KeyArgEvent(Parser yyp):base(yyp){}}
349//%+IntArgEvent+127
350public class IntArgEvent : Event{
351 public IntArgEvent (Parser yyp, string text ):base(((LSLSyntax
352)yyp), text ){}
353
354public override string yyname { get { return "IntArgEvent"; }}
355public override int yynum { get { return 127; }}
356public IntArgEvent(Parser yyp):base(yyp){}}
357//%+VectorArgEvent+128
358public class VectorArgEvent : Event{
359 public VectorArgEvent (Parser yyp, string text ):base(((LSLSyntax
360)yyp), text ){}
361
362public override string yyname { get { return "VectorArgEvent"; }}
363public override int yynum { get { return 128; }}
364public VectorArgEvent(Parser yyp):base(yyp){}}
365//%+IntRotRotArgEvent+129
366public class IntRotRotArgEvent : Event{
367 public IntRotRotArgEvent (Parser yyp, string text ):base(((LSLSyntax
368)yyp), text ){}
369
370public override string yyname { get { return "IntRotRotArgEvent"; }}
371public override int yynum { get { return 129; }}
372public IntRotRotArgEvent(Parser yyp):base(yyp){}}
373//%+IntVecVecArgEvent+130
374public class IntVecVecArgEvent : Event{
375 public IntVecVecArgEvent (Parser yyp, string text ):base(((LSLSyntax
376)yyp), text ){}
377
378public override string yyname { get { return "IntVecVecArgEvent"; }}
379public override int yynum { get { return 130; }}
380public IntVecVecArgEvent(Parser yyp):base(yyp){}}
381//%+KeyIntIntArgEvent+131
382public class KeyIntIntArgEvent : Event{
383 public KeyIntIntArgEvent (Parser yyp, string text ):base(((LSLSyntax
384)yyp), text ){}
385
386public override string yyname { get { return "KeyIntIntArgEvent"; }}
387public override int yynum { get { return 131; }}
388public KeyIntIntArgEvent(Parser yyp):base(yyp){}}
389//%+CompoundStatement+132
189public class CompoundStatement : SYMBOL{ 390public class CompoundStatement : SYMBOL{
190 public CompoundStatement (Parser yyp):base(((LSLSyntax 391 public CompoundStatement (Parser yyp):base(((LSLSyntax
191)yyp)){} 392)yyp)){}
@@ -194,9 +395,9 @@ public class CompoundStatement : SYMBOL{
194} 395}
195 396
196public override string yyname { get { return "CompoundStatement"; }} 397public override string yyname { get { return "CompoundStatement"; }}
197public override int yynum { get { return 108; }} 398public override int yynum { get { return 132; }}
198} 399}
199//%+StatementList+109 400//%+StatementList+133
200public class StatementList : SYMBOL{ 401public class StatementList : SYMBOL{
201 private void AddStatement ( Statement s ){ if ( s . kids . Top is IfStatement || s . kids . Top is WhileStatement || s . kids . Top is DoWhileStatement || s . kids . Top is ForLoop ) kids . Add ( s . kids . Pop ()); 402 private void AddStatement ( Statement s ){ if ( s . kids . Top is IfStatement || s . kids . Top is WhileStatement || s . kids . Top is DoWhileStatement || s . kids . Top is ForLoop ) kids . Add ( s . kids . Pop ());
202 else kids . Add ( s ); 403 else kids . Add ( s );
@@ -210,9 +411,9 @@ public class StatementList : SYMBOL{
210} 411}
211 412
212public override string yyname { get { return "StatementList"; }} 413public override string yyname { get { return "StatementList"; }}
213public override int yynum { get { return 109; }} 414public override int yynum { get { return 133; }}
214public StatementList(Parser yyp):base(yyp){}} 415public StatementList(Parser yyp):base(yyp){}}
215//%+Statement+110 416//%+Statement+134
216public class Statement : SYMBOL{ 417public class Statement : SYMBOL{
217 public Statement (Parser yyp, Declaration d ):base(((LSLSyntax 418 public Statement (Parser yyp, Declaration d ):base(((LSLSyntax
218)yyp)){ kids . Add ( d ); 419)yyp)){ kids . Add ( d );
@@ -258,9 +459,9 @@ public class Statement : SYMBOL{
258} 459}
259 460
260public override string yyname { get { return "Statement"; }} 461public override string yyname { get { return "Statement"; }}
261public override int yynum { get { return 110; }} 462public override int yynum { get { return 134; }}
262public Statement(Parser yyp):base(yyp){}} 463public Statement(Parser yyp):base(yyp){}}
263//%+EmptyStatement+111 464//%+EmptyStatement+135
264public class EmptyStatement : SYMBOL{ 465public class EmptyStatement : SYMBOL{
265 public EmptyStatement (Parser yyp):base(((LSLSyntax 466 public EmptyStatement (Parser yyp):base(((LSLSyntax
266)yyp)){} 467)yyp)){}
@@ -268,9 +469,9 @@ public class EmptyStatement : SYMBOL{
268} 469}
269 470
270public override string yyname { get { return "EmptyStatement"; }} 471public override string yyname { get { return "EmptyStatement"; }}
271public override int yynum { get { return 111; }} 472public override int yynum { get { return 135; }}
272} 473}
273//%+Assignment+112 474//%+Assignment+136
274public class Assignment : SYMBOL{ 475public class Assignment : SYMBOL{
275 protected string m_assignmentType ; 476 protected string m_assignmentType ;
276 public Assignment (Parser yyp, SYMBOL lhs , SYMBOL rhs , string assignmentType ):base(((LSLSyntax 477 public Assignment (Parser yyp, SYMBOL lhs , SYMBOL rhs , string assignmentType ):base(((LSLSyntax
@@ -290,9 +491,9 @@ public class Assignment : SYMBOL{
290} 491}
291 492
292public override string yyname { get { return "Assignment"; }} 493public override string yyname { get { return "Assignment"; }}
293public override int yynum { get { return 112; }} 494public override int yynum { get { return 136; }}
294public Assignment(Parser yyp):base(yyp){}} 495public Assignment(Parser yyp):base(yyp){}}
295//%+SimpleAssignment+113 496//%+SimpleAssignment+137
296public class SimpleAssignment : Assignment{ 497public class SimpleAssignment : Assignment{
297 public SimpleAssignment (Parser yyp, SYMBOL lhs , SYMBOL rhs , string assignmentType ):base(((LSLSyntax 498 public SimpleAssignment (Parser yyp, SYMBOL lhs , SYMBOL rhs , string assignmentType ):base(((LSLSyntax
298)yyp)){ m_assignmentType = assignmentType ; 499)yyp)){ m_assignmentType = assignmentType ;
@@ -302,9 +503,9 @@ public class SimpleAssignment : Assignment{
302} 503}
303 504
304public override string yyname { get { return "SimpleAssignment"; }} 505public override string yyname { get { return "SimpleAssignment"; }}
305public override int yynum { get { return 113; }} 506public override int yynum { get { return 137; }}
306public SimpleAssignment(Parser yyp):base(yyp){}} 507public SimpleAssignment(Parser yyp):base(yyp){}}
307//%+ReturnStatement+114 508//%+ReturnStatement+138
308public class ReturnStatement : SYMBOL{ 509public class ReturnStatement : SYMBOL{
309 public ReturnStatement (Parser yyp):base(((LSLSyntax 510 public ReturnStatement (Parser yyp):base(((LSLSyntax
310)yyp)){} 511)yyp)){}
@@ -314,9 +515,9 @@ public class ReturnStatement : SYMBOL{
314} 515}
315 516
316public override string yyname { get { return "ReturnStatement"; }} 517public override string yyname { get { return "ReturnStatement"; }}
317public override int yynum { get { return 114; }} 518public override int yynum { get { return 138; }}
318} 519}
319//%+JumpLabel+115 520//%+JumpLabel+139
320public class JumpLabel : SYMBOL{ 521public class JumpLabel : SYMBOL{
321 private string m_labelName ; 522 private string m_labelName ;
322 public JumpLabel (Parser yyp, string labelName ):base(((LSLSyntax 523 public JumpLabel (Parser yyp, string labelName ):base(((LSLSyntax
@@ -329,9 +530,9 @@ public class JumpLabel : SYMBOL{
329} 530}
330 531
331public override string yyname { get { return "JumpLabel"; }} 532public override string yyname { get { return "JumpLabel"; }}
332public override int yynum { get { return 115; }} 533public override int yynum { get { return 139; }}
333public JumpLabel(Parser yyp):base(yyp){}} 534public JumpLabel(Parser yyp):base(yyp){}}
334//%+JumpStatement+116 535//%+JumpStatement+140
335public class JumpStatement : SYMBOL{ 536public class JumpStatement : SYMBOL{
336 private string m_targetName ; 537 private string m_targetName ;
337 public JumpStatement (Parser yyp, string targetName ):base(((LSLSyntax 538 public JumpStatement (Parser yyp, string targetName ):base(((LSLSyntax
@@ -344,9 +545,9 @@ public class JumpStatement : SYMBOL{
344} 545}
345 546
346public override string yyname { get { return "JumpStatement"; }} 547public override string yyname { get { return "JumpStatement"; }}
347public override int yynum { get { return 116; }} 548public override int yynum { get { return 140; }}
348public JumpStatement(Parser yyp):base(yyp){}} 549public JumpStatement(Parser yyp):base(yyp){}}
349//%+StateChange+117 550//%+StateChange+141
350public class StateChange : SYMBOL{ 551public class StateChange : SYMBOL{
351 private string m_newState ; 552 private string m_newState ;
352 public StateChange (Parser yyp, string newState ):base(((LSLSyntax 553 public StateChange (Parser yyp, string newState ):base(((LSLSyntax
@@ -357,9 +558,9 @@ public class StateChange : SYMBOL{
357} 558}
358 559
359public override string yyname { get { return "StateChange"; }} 560public override string yyname { get { return "StateChange"; }}
360public override int yynum { get { return 117; }} 561public override int yynum { get { return 141; }}
361public StateChange(Parser yyp):base(yyp){}} 562public StateChange(Parser yyp):base(yyp){}}
362//%+IfStatement+118 563//%+IfStatement+142
363public class IfStatement : SYMBOL{ 564public class IfStatement : SYMBOL{
364 private void AddStatement ( Statement s ){ if (0< s . kids . Count && s . kids . Top is CompoundStatement ) kids . Add ( s . kids . Pop ()); 565 private void AddStatement ( Statement s ){ if (0< s . kids . Count && s . kids . Top is CompoundStatement ) kids . Add ( s . kids . Pop ());
365 else kids . Add ( s ); 566 else kids . Add ( s );
@@ -376,9 +577,9 @@ public class IfStatement : SYMBOL{
376} 577}
377 578
378public override string yyname { get { return "IfStatement"; }} 579public override string yyname { get { return "IfStatement"; }}
379public override int yynum { get { return 118; }} 580public override int yynum { get { return 142; }}
380public IfStatement(Parser yyp):base(yyp){}} 581public IfStatement(Parser yyp):base(yyp){}}
381//%+WhileStatement+119 582//%+WhileStatement+143
382public class WhileStatement : SYMBOL{ 583public class WhileStatement : SYMBOL{
383 public WhileStatement (Parser yyp, SYMBOL s , Statement st ):base(((LSLSyntax 584 public WhileStatement (Parser yyp, SYMBOL s , Statement st ):base(((LSLSyntax
384)yyp)){ kids . Add ( s ); 585)yyp)){ kids . Add ( s );
@@ -387,9 +588,9 @@ public class WhileStatement : SYMBOL{
387} 588}
388 589
389public override string yyname { get { return "WhileStatement"; }} 590public override string yyname { get { return "WhileStatement"; }}
390public override int yynum { get { return 119; }} 591public override int yynum { get { return 143; }}
391public WhileStatement(Parser yyp):base(yyp){}} 592public WhileStatement(Parser yyp):base(yyp){}}
392//%+DoWhileStatement+120 593//%+DoWhileStatement+144
393public class DoWhileStatement : SYMBOL{ 594public class DoWhileStatement : SYMBOL{
394 public DoWhileStatement (Parser yyp, SYMBOL s , Statement st ):base(((LSLSyntax 595 public DoWhileStatement (Parser yyp, SYMBOL s , Statement st ):base(((LSLSyntax
395)yyp)){ if (0< st . kids . Count && st . kids . Top is CompoundStatement ) kids . Add ( st . kids . Pop ()); 596)yyp)){ if (0< st . kids . Count && st . kids . Top is CompoundStatement ) kids . Add ( st . kids . Pop ());
@@ -398,9 +599,9 @@ public class DoWhileStatement : SYMBOL{
398} 599}
399 600
400public override string yyname { get { return "DoWhileStatement"; }} 601public override string yyname { get { return "DoWhileStatement"; }}
401public override int yynum { get { return 120; }} 602public override int yynum { get { return 144; }}
402public DoWhileStatement(Parser yyp):base(yyp){}} 603public DoWhileStatement(Parser yyp):base(yyp){}}
403//%+ForLoop+121 604//%+ForLoop+145
404public class ForLoop : SYMBOL{ 605public class ForLoop : SYMBOL{
405 public ForLoop (Parser yyp, ForLoopStatement flsa , Expression e , ForLoopStatement flsb , Statement s ):base(((LSLSyntax 606 public ForLoop (Parser yyp, ForLoopStatement flsa , Expression e , ForLoopStatement flsb , Statement s ):base(((LSLSyntax
406)yyp)){ kids . Add ( flsa ); 607)yyp)){ kids . Add ( flsa );
@@ -411,9 +612,9 @@ public class ForLoop : SYMBOL{
411} 612}
412 613
413public override string yyname { get { return "ForLoop"; }} 614public override string yyname { get { return "ForLoop"; }}
414public override int yynum { get { return 121; }} 615public override int yynum { get { return 145; }}
415public ForLoop(Parser yyp):base(yyp){}} 616public ForLoop(Parser yyp):base(yyp){}}
416//%+ForLoopStatement+122 617//%+ForLoopStatement+146
417public class ForLoopStatement : SYMBOL{ 618public class ForLoopStatement : SYMBOL{
418 public ForLoopStatement (Parser yyp, Expression e ):base(((LSLSyntax 619 public ForLoopStatement (Parser yyp, Expression e ):base(((LSLSyntax
419)yyp)){ kids . Add ( e ); 620)yyp)){ kids . Add ( e );
@@ -431,9 +632,9 @@ public class ForLoopStatement : SYMBOL{
431} 632}
432 633
433public override string yyname { get { return "ForLoopStatement"; }} 634public override string yyname { get { return "ForLoopStatement"; }}
434public override int yynum { get { return 122; }} 635public override int yynum { get { return 146; }}
435public ForLoopStatement(Parser yyp):base(yyp){}} 636public ForLoopStatement(Parser yyp):base(yyp){}}
436//%+FunctionCall+123 637//%+FunctionCall+147
437public class FunctionCall : SYMBOL{ 638public class FunctionCall : SYMBOL{
438 private string m_id ; 639 private string m_id ;
439 public FunctionCall (Parser yyp, string id , ArgumentList al ):base(((LSLSyntax 640 public FunctionCall (Parser yyp, string id , ArgumentList al ):base(((LSLSyntax
@@ -447,9 +648,9 @@ public class FunctionCall : SYMBOL{
447} 648}
448 649
449public override string yyname { get { return "FunctionCall"; }} 650public override string yyname { get { return "FunctionCall"; }}
450public override int yynum { get { return 123; }} 651public override int yynum { get { return 147; }}
451public FunctionCall(Parser yyp):base(yyp){}} 652public FunctionCall(Parser yyp):base(yyp){}}
452//%+ArgumentList+124 653//%+ArgumentList+148
453public class ArgumentList : SYMBOL{ 654public class ArgumentList : SYMBOL{
454 public ArgumentList (Parser yyp, Argument a ):base(((LSLSyntax 655 public ArgumentList (Parser yyp, Argument a ):base(((LSLSyntax
455)yyp)){ AddArgument ( a ); 656)yyp)){ AddArgument ( a );
@@ -463,14 +664,14 @@ public class ArgumentList : SYMBOL{
463} 664}
464 665
465public override string yyname { get { return "ArgumentList"; }} 666public override string yyname { get { return "ArgumentList"; }}
466public override int yynum { get { return 124; }} 667public override int yynum { get { return 148; }}
467public ArgumentList(Parser yyp):base(yyp){}} 668public ArgumentList(Parser yyp):base(yyp){}}
468//%+Argument+125 669//%+Argument+149
469public class Argument : SYMBOL{ 670public class Argument : SYMBOL{
470public override string yyname { get { return "Argument"; }} 671public override string yyname { get { return "Argument"; }}
471public override int yynum { get { return 125; }} 672public override int yynum { get { return 149; }}
472public Argument(Parser yyp):base(yyp){}} 673public Argument(Parser yyp):base(yyp){}}
473//%+ExpressionArgument+126 674//%+ExpressionArgument+150
474public class ExpressionArgument : Argument{ 675public class ExpressionArgument : Argument{
475 public ExpressionArgument (Parser yyp, Expression e ):base(((LSLSyntax 676 public ExpressionArgument (Parser yyp, Expression e ):base(((LSLSyntax
476)yyp)){ if ( e is ConstantExpression ) while (0< e . kids . Count ) kids . Add ( e . kids . Pop ()); 677)yyp)){ if ( e is ConstantExpression ) while (0< e . kids . Count ) kids . Add ( e . kids . Pop ());
@@ -478,9 +679,9 @@ public class ExpressionArgument : Argument{
478} 679}
479 680
480public override string yyname { get { return "ExpressionArgument"; }} 681public override string yyname { get { return "ExpressionArgument"; }}
481public override int yynum { get { return 126; }} 682public override int yynum { get { return 150; }}
482public ExpressionArgument(Parser yyp):base(yyp){}} 683public ExpressionArgument(Parser yyp):base(yyp){}}
483//%+Constant+127 684//%+Constant+151
484public class Constant : SYMBOL{ 685public class Constant : SYMBOL{
485 private string m_type ; 686 private string m_type ;
486 private string m_val ; 687 private string m_val ;
@@ -502,9 +703,9 @@ public class Constant : SYMBOL{
502} 703}
503 704
504public override string yyname { get { return "Constant"; }} 705public override string yyname { get { return "Constant"; }}
505public override int yynum { get { return 127; }} 706public override int yynum { get { return 151; }}
506public Constant(Parser yyp):base(yyp){}} 707public Constant(Parser yyp):base(yyp){}}
507//%+VectorConstant+128 708//%+VectorConstant+152
508public class VectorConstant : Constant{ 709public class VectorConstant : Constant{
509 public VectorConstant (Parser yyp, Expression valX , Expression valY , Expression valZ ):base(((LSLSyntax 710 public VectorConstant (Parser yyp, Expression valX , Expression valY , Expression valZ ):base(((LSLSyntax
510)yyp),"vector", null ){ kids . Add ( valX ); 711)yyp),"vector", null ){ kids . Add ( valX );
@@ -513,9 +714,9 @@ public class VectorConstant : Constant{
513} 714}
514 715
515public override string yyname { get { return "VectorConstant"; }} 716public override string yyname { get { return "VectorConstant"; }}
516public override int yynum { get { return 128; }} 717public override int yynum { get { return 152; }}
517public VectorConstant(Parser yyp):base(yyp){}} 718public VectorConstant(Parser yyp):base(yyp){}}
518//%+RotationConstant+129 719//%+RotationConstant+153
519public class RotationConstant : Constant{ 720public class RotationConstant : Constant{
520 public RotationConstant (Parser yyp, Expression valX , Expression valY , Expression valZ , Expression valS ):base(((LSLSyntax 721 public RotationConstant (Parser yyp, Expression valX , Expression valY , Expression valZ , Expression valS ):base(((LSLSyntax
521)yyp),"rotation", null ){ kids . Add ( valX ); 722)yyp),"rotation", null ){ kids . Add ( valX );
@@ -525,36 +726,36 @@ public class RotationConstant : Constant{
525} 726}
526 727
527public override string yyname { get { return "RotationConstant"; }} 728public override string yyname { get { return "RotationConstant"; }}
528public override int yynum { get { return 129; }} 729public override int yynum { get { return 153; }}
529public RotationConstant(Parser yyp):base(yyp){}} 730public RotationConstant(Parser yyp):base(yyp){}}
530//%+ListConstant+130 731//%+ListConstant+154
531public class ListConstant : Constant{ 732public class ListConstant : Constant{
532 public ListConstant (Parser yyp, ArgumentList al ):base(((LSLSyntax 733 public ListConstant (Parser yyp, ArgumentList al ):base(((LSLSyntax
533)yyp),"list", null ){ kids . Add ( al ); 734)yyp),"list", null ){ kids . Add ( al );
534} 735}
535 736
536public override string yyname { get { return "ListConstant"; }} 737public override string yyname { get { return "ListConstant"; }}
537public override int yynum { get { return 130; }} 738public override int yynum { get { return 154; }}
538public ListConstant(Parser yyp):base(yyp){}} 739public ListConstant(Parser yyp):base(yyp){}}
539//%+Expression+131 740//%+Expression+155
540public class Expression : SYMBOL{ 741public class Expression : SYMBOL{
541 protected void AddExpression ( Expression e ){ if ( e is ConstantExpression ) while (0< e . kids . Count ) kids . Add ( e . kids . Pop ()); 742 protected void AddExpression ( Expression e ){ if ( e is ConstantExpression ) while (0< e . kids . Count ) kids . Add ( e . kids . Pop ());
542 else kids . Add ( e ); 743 else kids . Add ( e );
543} 744}
544 745
545public override string yyname { get { return "Expression"; }} 746public override string yyname { get { return "Expression"; }}
546public override int yynum { get { return 131; }} 747public override int yynum { get { return 155; }}
547public Expression(Parser yyp):base(yyp){}} 748public Expression(Parser yyp):base(yyp){}}
548//%+ConstantExpression+132 749//%+ConstantExpression+156
549public class ConstantExpression : Expression{ 750public class ConstantExpression : Expression{
550 public ConstantExpression (Parser yyp, Constant c ):base(((LSLSyntax 751 public ConstantExpression (Parser yyp, Constant c ):base(((LSLSyntax
551)yyp)){ kids . Add ( c ); 752)yyp)){ kids . Add ( c );
552} 753}
553 754
554public override string yyname { get { return "ConstantExpression"; }} 755public override string yyname { get { return "ConstantExpression"; }}
555public override int yynum { get { return 132; }} 756public override int yynum { get { return 156; }}
556public ConstantExpression(Parser yyp):base(yyp){}} 757public ConstantExpression(Parser yyp):base(yyp){}}
557//%+IdentExpression+133 758//%+IdentExpression+157
558public class IdentExpression : Expression{ 759public class IdentExpression : Expression{
559 protected string m_name ; 760 protected string m_name ;
560 public IdentExpression (Parser yyp, string name ):base(((LSLSyntax 761 public IdentExpression (Parser yyp, string name ):base(((LSLSyntax
@@ -567,9 +768,9 @@ public class IdentExpression : Expression{
567} 768}
568 769
569public override string yyname { get { return "IdentExpression"; }} 770public override string yyname { get { return "IdentExpression"; }}
570public override int yynum { get { return 133; }} 771public override int yynum { get { return 157; }}
571public IdentExpression(Parser yyp):base(yyp){}} 772public IdentExpression(Parser yyp):base(yyp){}}
572//%+IdentDotExpression+134 773//%+IdentDotExpression+158
573public class IdentDotExpression : IdentExpression{ 774public class IdentDotExpression : IdentExpression{
574 private string m_member ; 775 private string m_member ;
575 public IdentDotExpression (Parser yyp, string name , string member ):base(((LSLSyntax 776 public IdentDotExpression (Parser yyp, string name , string member ):base(((LSLSyntax
@@ -583,18 +784,18 @@ public class IdentDotExpression : IdentExpression{
583} 784}
584 785
585public override string yyname { get { return "IdentDotExpression"; }} 786public override string yyname { get { return "IdentDotExpression"; }}
586public override int yynum { get { return 134; }} 787public override int yynum { get { return 158; }}
587public IdentDotExpression(Parser yyp):base(yyp){}} 788public IdentDotExpression(Parser yyp):base(yyp){}}
588//%+FunctionCallExpression+135 789//%+FunctionCallExpression+159
589public class FunctionCallExpression : Expression{ 790public class FunctionCallExpression : Expression{
590 public FunctionCallExpression (Parser yyp, FunctionCall fc ):base(((LSLSyntax 791 public FunctionCallExpression (Parser yyp, FunctionCall fc ):base(((LSLSyntax
591)yyp)){ kids . Add ( fc ); 792)yyp)){ kids . Add ( fc );
592} 793}
593 794
594public override string yyname { get { return "FunctionCallExpression"; }} 795public override string yyname { get { return "FunctionCallExpression"; }}
595public override int yynum { get { return 135; }} 796public override int yynum { get { return 159; }}
596public FunctionCallExpression(Parser yyp):base(yyp){}} 797public FunctionCallExpression(Parser yyp):base(yyp){}}
597//%+BinaryExpression+136 798//%+BinaryExpression+160
598public class BinaryExpression : Expression{ 799public class BinaryExpression : Expression{
599 private string m_expressionSymbol ; 800 private string m_expressionSymbol ;
600 public BinaryExpression (Parser yyp, Expression lhs , Expression rhs , string expressionSymbol ):base(((LSLSyntax 801 public BinaryExpression (Parser yyp, Expression lhs , Expression rhs , string expressionSymbol ):base(((LSLSyntax
@@ -609,9 +810,9 @@ public class BinaryExpression : Expression{
609} 810}
610 811
611public override string yyname { get { return "BinaryExpression"; }} 812public override string yyname { get { return "BinaryExpression"; }}
612public override int yynum { get { return 136; }} 813public override int yynum { get { return 160; }}
613public BinaryExpression(Parser yyp):base(yyp){}} 814public BinaryExpression(Parser yyp):base(yyp){}}
614//%+UnaryExpression+137 815//%+UnaryExpression+161
615public class UnaryExpression : Expression{ 816public class UnaryExpression : Expression{
616 private string m_unarySymbol ; 817 private string m_unarySymbol ;
617 public UnaryExpression (Parser yyp, string unarySymbol , Expression e ):base(((LSLSyntax 818 public UnaryExpression (Parser yyp, string unarySymbol , Expression e ):base(((LSLSyntax
@@ -625,9 +826,9 @@ public class UnaryExpression : Expression{
625} 826}
626 827
627public override string yyname { get { return "UnaryExpression"; }} 828public override string yyname { get { return "UnaryExpression"; }}
628public override int yynum { get { return 137; }} 829public override int yynum { get { return 161; }}
629public UnaryExpression(Parser yyp):base(yyp){}} 830public UnaryExpression(Parser yyp):base(yyp){}}
630//%+TypecastExpression+138 831//%+TypecastExpression+162
631public class TypecastExpression : Expression{ 832public class TypecastExpression : Expression{
632 private string m_typecastType ; 833 private string m_typecastType ;
633 public TypecastExpression (Parser yyp, string typecastType , SYMBOL rhs ):base(((LSLSyntax 834 public TypecastExpression (Parser yyp, string typecastType , SYMBOL rhs ):base(((LSLSyntax
@@ -641,18 +842,18 @@ public class TypecastExpression : Expression{
641} 842}
642 843
643public override string yyname { get { return "TypecastExpression"; }} 844public override string yyname { get { return "TypecastExpression"; }}
644public override int yynum { get { return 138; }} 845public override int yynum { get { return 162; }}
645public TypecastExpression(Parser yyp):base(yyp){}} 846public TypecastExpression(Parser yyp):base(yyp){}}
646//%+ParenthesisExpression+139 847//%+ParenthesisExpression+163
647public class ParenthesisExpression : Expression{ 848public class ParenthesisExpression : Expression{
648 public ParenthesisExpression (Parser yyp, SYMBOL s ):base(((LSLSyntax 849 public ParenthesisExpression (Parser yyp, SYMBOL s ):base(((LSLSyntax
649)yyp)){ kids . Add ( s ); 850)yyp)){ kids . Add ( s );
650} 851}
651 852
652public override string yyname { get { return "ParenthesisExpression"; }} 853public override string yyname { get { return "ParenthesisExpression"; }}
653public override int yynum { get { return 139; }} 854public override int yynum { get { return 163; }}
654public ParenthesisExpression(Parser yyp):base(yyp){}} 855public ParenthesisExpression(Parser yyp):base(yyp){}}
655//%+IncrementDecrementExpression+140 856//%+IncrementDecrementExpression+164
656public class IncrementDecrementExpression : Expression{ 857public class IncrementDecrementExpression : Expression{
657 private string m_name ; 858 private string m_name ;
658 private string m_operation ; 859 private string m_operation ;
@@ -680,7 +881,7 @@ public class IncrementDecrementExpression : Expression{
680} 881}
681 882
682public override string yyname { get { return "IncrementDecrementExpression"; }} 883public override string yyname { get { return "IncrementDecrementExpression"; }}
683public override int yynum { get { return 140; }} 884public override int yynum { get { return 164; }}
684public IncrementDecrementExpression(Parser yyp):base(yyp){}} 885public IncrementDecrementExpression(Parser yyp):base(yyp){}}
685 886
686public class LSLProgramRoot_1 : LSLProgramRoot { 887public class LSLProgramRoot_1 : LSLProgramRoot {
@@ -792,6 +993,90 @@ public class StateBody_2 : StateBody {
792 ((StateEvent)(yyq.StackAt(0).m_value)) 993 ((StateEvent)(yyq.StackAt(0).m_value))
793 ){}} 994 ){}}
794 995
996public class StateBody_3 : StateBody {
997 public StateBody_3(Parser yyq):base(yyq,
998 ((VoidArgStateEvent)(yyq.StackAt(0).m_value))
999 ){}}
1000
1001public class StateBody_4 : StateBody {
1002 public StateBody_4(Parser yyq):base(yyq,
1003 ((StateBody)(yyq.StackAt(1).m_value))
1004 ,
1005 ((VoidArgStateEvent)(yyq.StackAt(0).m_value))
1006 ){}}
1007
1008public class StateBody_5 : StateBody {
1009 public StateBody_5(Parser yyq):base(yyq,
1010 ((KeyArgStateEvent)(yyq.StackAt(0).m_value))
1011 ){}}
1012
1013public class StateBody_6 : StateBody {
1014 public StateBody_6(Parser yyq):base(yyq,
1015 ((StateBody)(yyq.StackAt(1).m_value))
1016 ,
1017 ((KeyArgStateEvent)(yyq.StackAt(0).m_value))
1018 ){}}
1019
1020public class StateBody_7 : StateBody {
1021 public StateBody_7(Parser yyq):base(yyq,
1022 ((IntArgStateEvent)(yyq.StackAt(0).m_value))
1023 ){}}
1024
1025public class StateBody_8 : StateBody {
1026 public StateBody_8(Parser yyq):base(yyq,
1027 ((StateBody)(yyq.StackAt(1).m_value))
1028 ,
1029 ((IntArgStateEvent)(yyq.StackAt(0).m_value))
1030 ){}}
1031
1032public class StateBody_9 : StateBody {
1033 public StateBody_9(Parser yyq):base(yyq,
1034 ((VectorArgStateEvent)(yyq.StackAt(0).m_value))
1035 ){}}
1036
1037public class StateBody_10 : StateBody {
1038 public StateBody_10(Parser yyq):base(yyq,
1039 ((StateBody)(yyq.StackAt(1).m_value))
1040 ,
1041 ((VectorArgStateEvent)(yyq.StackAt(0).m_value))
1042 ){}}
1043
1044public class StateBody_11 : StateBody {
1045 public StateBody_11(Parser yyq):base(yyq,
1046 ((IntRotRotArgStateEvent)(yyq.StackAt(0).m_value))
1047 ){}}
1048
1049public class StateBody_12 : StateBody {
1050 public StateBody_12(Parser yyq):base(yyq,
1051 ((StateBody)(yyq.StackAt(1).m_value))
1052 ,
1053 ((IntRotRotArgStateEvent)(yyq.StackAt(0).m_value))
1054 ){}}
1055
1056public class StateBody_13 : StateBody {
1057 public StateBody_13(Parser yyq):base(yyq,
1058 ((IntVecVecArgStateEvent)(yyq.StackAt(0).m_value))
1059 ){}}
1060
1061public class StateBody_14 : StateBody {
1062 public StateBody_14(Parser yyq):base(yyq,
1063 ((StateBody)(yyq.StackAt(1).m_value))
1064 ,
1065 ((IntVecVecArgStateEvent)(yyq.StackAt(0).m_value))
1066 ){}}
1067
1068public class StateBody_15 : StateBody {
1069 public StateBody_15(Parser yyq):base(yyq,
1070 ((KeyIntIntArgStateEvent)(yyq.StackAt(0).m_value))
1071 ){}}
1072
1073public class StateBody_16 : StateBody {
1074 public StateBody_16(Parser yyq):base(yyq,
1075 ((StateBody)(yyq.StackAt(1).m_value))
1076 ,
1077 ((KeyIntIntArgStateEvent)(yyq.StackAt(0).m_value))
1078 ){}}
1079
795public class StateEvent_1 : StateEvent { 1080public class StateEvent_1 : StateEvent {
796 public StateEvent_1(Parser yyq):base(yyq, 1081 public StateEvent_1(Parser yyq):base(yyq,
797 ((Event)(yyq.StackAt(4).m_value)) 1082 ((Event)(yyq.StackAt(4).m_value))
@@ -801,6 +1086,67 @@ public class StateEvent_1 : StateEvent {
801 ((CompoundStatement)(yyq.StackAt(0).m_value)) 1086 ((CompoundStatement)(yyq.StackAt(0).m_value))
802 ){}} 1087 ){}}
803 1088
1089public class VoidArgStateEvent_1 : VoidArgStateEvent {
1090 public VoidArgStateEvent_1(Parser yyq):base(yyq,
1091 ((VoidArgEvent)(yyq.StackAt(3).m_value))
1092 .yytext,
1093 ((CompoundStatement)(yyq.StackAt(0).m_value))
1094 ){}}
1095
1096public class KeyArgStateEvent_1 : KeyArgStateEvent {
1097 public KeyArgStateEvent_1(Parser yyq):base(yyq,
1098 ((KeyArgEvent)(yyq.StackAt(4).m_value))
1099 .yytext,
1100 ((KeyArgumentDeclarationList)(yyq.StackAt(2).m_value))
1101 ,
1102 ((CompoundStatement)(yyq.StackAt(0).m_value))
1103 ){}}
1104
1105public class IntArgStateEvent_1 : IntArgStateEvent {
1106 public IntArgStateEvent_1(Parser yyq):base(yyq,
1107 ((IntArgEvent)(yyq.StackAt(4).m_value))
1108 .yytext,
1109 ((IntArgumentDeclarationList)(yyq.StackAt(2).m_value))
1110 ,
1111 ((CompoundStatement)(yyq.StackAt(0).m_value))
1112 ){}}
1113
1114public class VectorArgStateEvent_1 : VectorArgStateEvent {
1115 public VectorArgStateEvent_1(Parser yyq):base(yyq,
1116 ((VectorArgEvent)(yyq.StackAt(4).m_value))
1117 .yytext,
1118 ((VectorArgumentDeclarationList)(yyq.StackAt(2).m_value))
1119 ,
1120 ((CompoundStatement)(yyq.StackAt(0).m_value))
1121 ){}}
1122
1123public class IntRotRotArgStateEvent_1 : IntRotRotArgStateEvent {
1124 public IntRotRotArgStateEvent_1(Parser yyq):base(yyq,
1125 ((IntRotRotArgEvent)(yyq.StackAt(4).m_value))
1126 .yytext,
1127 ((IntRotRotArgumentDeclarationList)(yyq.StackAt(2).m_value))
1128 ,
1129 ((CompoundStatement)(yyq.StackAt(0).m_value))
1130 ){}}
1131
1132public class IntVecVecArgStateEvent_1 : IntVecVecArgStateEvent {
1133 public IntVecVecArgStateEvent_1(Parser yyq):base(yyq,
1134 ((IntVecVecArgEvent)(yyq.StackAt(4).m_value))
1135 .yytext,
1136 ((IntVecVecArgumentDeclarationList)(yyq.StackAt(2).m_value))
1137 ,
1138 ((CompoundStatement)(yyq.StackAt(0).m_value))
1139 ){}}
1140
1141public class KeyIntIntArgStateEvent_1 : KeyIntIntArgStateEvent {
1142 public KeyIntIntArgStateEvent_1(Parser yyq):base(yyq,
1143 ((KeyIntIntArgEvent)(yyq.StackAt(4).m_value))
1144 .yytext,
1145 ((KeyIntIntArgumentDeclarationList)(yyq.StackAt(2).m_value))
1146 ,
1147 ((CompoundStatement)(yyq.StackAt(0).m_value))
1148 ){}}
1149
804public class ArgumentDeclarationList_1 : ArgumentDeclarationList { 1150public class ArgumentDeclarationList_1 : ArgumentDeclarationList {
805 public ArgumentDeclarationList_1(Parser yyq):base(yyq, 1151 public ArgumentDeclarationList_1(Parser yyq):base(yyq,
806 ((Declaration)(yyq.StackAt(0).m_value)) 1152 ((Declaration)(yyq.StackAt(0).m_value))
@@ -813,6 +1159,48 @@ public class ArgumentDeclarationList_2 : ArgumentDeclarationList {
813 ((Declaration)(yyq.StackAt(0).m_value)) 1159 ((Declaration)(yyq.StackAt(0).m_value))
814 ){}} 1160 ){}}
815 1161
1162public class KeyArgumentDeclarationList_1 : KeyArgumentDeclarationList {
1163 public KeyArgumentDeclarationList_1(Parser yyq):base(yyq,
1164 ((KeyDeclaration)(yyq.StackAt(0).m_value))
1165 ){}}
1166
1167public class IntArgumentDeclarationList_1 : IntArgumentDeclarationList {
1168 public IntArgumentDeclarationList_1(Parser yyq):base(yyq,
1169 ((IntDeclaration)(yyq.StackAt(0).m_value))
1170 ){}}
1171
1172public class VectorArgumentDeclarationList_1 : VectorArgumentDeclarationList {
1173 public VectorArgumentDeclarationList_1(Parser yyq):base(yyq,
1174 ((VecDeclaration)(yyq.StackAt(0).m_value))
1175 ){}}
1176
1177public class IntRotRotArgumentDeclarationList_1 : IntRotRotArgumentDeclarationList {
1178 public IntRotRotArgumentDeclarationList_1(Parser yyq):base(yyq,
1179 ((IntDeclaration)(yyq.StackAt(4).m_value))
1180 ,
1181 ((RotDeclaration)(yyq.StackAt(2).m_value))
1182 ,
1183 ((RotDeclaration)(yyq.StackAt(0).m_value))
1184 ){}}
1185
1186public class IntVecVecArgumentDeclarationList_1 : IntVecVecArgumentDeclarationList {
1187 public IntVecVecArgumentDeclarationList_1(Parser yyq):base(yyq,
1188 ((IntDeclaration)(yyq.StackAt(4).m_value))
1189 ,
1190 ((VecDeclaration)(yyq.StackAt(2).m_value))
1191 ,
1192 ((VecDeclaration)(yyq.StackAt(0).m_value))
1193 ){}}
1194
1195public class KeyIntIntArgumentDeclarationList_1 : KeyIntIntArgumentDeclarationList {
1196 public KeyIntIntArgumentDeclarationList_1(Parser yyq):base(yyq,
1197 ((KeyDeclaration)(yyq.StackAt(4).m_value))
1198 ,
1199 ((IntDeclaration)(yyq.StackAt(2).m_value))
1200 ,
1201 ((IntDeclaration)(yyq.StackAt(0).m_value))
1202 ){}}
1203
816public class Declaration_1 : Declaration { 1204public class Declaration_1 : Declaration {
817 public Declaration_1(Parser yyq):base(yyq, 1205 public Declaration_1(Parser yyq):base(yyq,
818 ((Typename)(yyq.StackAt(1).m_value)) 1206 ((Typename)(yyq.StackAt(1).m_value))
@@ -820,6 +1208,34 @@ public class Declaration_1 : Declaration {
820 ((IDENT)(yyq.StackAt(0).m_value)) 1208 ((IDENT)(yyq.StackAt(0).m_value))
821 .yytext){}} 1209 .yytext){}}
822 1210
1211public class KeyDeclaration_1 : KeyDeclaration {
1212 public KeyDeclaration_1(Parser yyq):base(yyq,
1213 ((KEY_TYPE)(yyq.StackAt(1).m_value))
1214 .yytext,
1215 ((IDENT)(yyq.StackAt(0).m_value))
1216 .yytext){}}
1217
1218public class IntDeclaration_1 : IntDeclaration {
1219 public IntDeclaration_1(Parser yyq):base(yyq,
1220 ((INTEGER_TYPE)(yyq.StackAt(1).m_value))
1221 .yytext,
1222 ((IDENT)(yyq.StackAt(0).m_value))
1223 .yytext){}}
1224
1225public class VecDeclaration_1 : VecDeclaration {
1226 public VecDeclaration_1(Parser yyq):base(yyq,
1227 ((VECTOR_TYPE)(yyq.StackAt(1).m_value))
1228 .yytext,
1229 ((IDENT)(yyq.StackAt(0).m_value))
1230 .yytext){}}
1231
1232public class RotDeclaration_1 : RotDeclaration {
1233 public RotDeclaration_1(Parser yyq):base(yyq,
1234 ((ROTATION_TYPE)(yyq.StackAt(1).m_value))
1235 .yytext,
1236 ((IDENT)(yyq.StackAt(0).m_value))
1237 .yytext){}}
1238
823public class CompoundStatement_1 : CompoundStatement { 1239public class CompoundStatement_1 : CompoundStatement {
824 public CompoundStatement_1(Parser yyq):base(yyq){}} 1240 public CompoundStatement_1(Parser yyq):base(yyq){}}
825 1241
@@ -1780,172 +2196,172 @@ public class Typename_7 : Typename {
1780 2196
1781public class Event_1 : Event { 2197public class Event_1 : Event {
1782 public Event_1(Parser yyq):base(yyq, 2198 public Event_1(Parser yyq):base(yyq,
1783 ((AT_ROT_TARGET_EVENT)(yyq.StackAt(0).m_value)) 2199 ((DATASERVER_EVENT)(yyq.StackAt(0).m_value))
1784 .yytext){}} 2200 .yytext){}}
1785 2201
1786public class Event_2 : Event { 2202public class Event_2 : Event {
1787 public Event_2(Parser yyq):base(yyq, 2203 public Event_2(Parser yyq):base(yyq,
1788 ((AT_TARGET_EVENT)(yyq.StackAt(0).m_value)) 2204 ((EMAIL_EVENT)(yyq.StackAt(0).m_value))
1789 .yytext){}} 2205 .yytext){}}
1790 2206
1791public class Event_3 : Event { 2207public class Event_3 : Event {
1792 public Event_3(Parser yyq):base(yyq, 2208 public Event_3(Parser yyq):base(yyq,
1793 ((ATTACH_EVENT)(yyq.StackAt(0).m_value)) 2209 ((HTTP_RESPONSE_EVENT)(yyq.StackAt(0).m_value))
1794 .yytext){}} 2210 .yytext){}}
1795 2211
1796public class Event_4 : Event { 2212public class Event_4 : Event {
1797 public Event_4(Parser yyq):base(yyq, 2213 public Event_4(Parser yyq):base(yyq,
1798 ((CHANGED_EVENT)(yyq.StackAt(0).m_value)) 2214 ((LINK_MESSAGE_EVENT)(yyq.StackAt(0).m_value))
1799 .yytext){}} 2215 .yytext){}}
1800 2216
1801public class Event_5 : Event { 2217public class Event_5 : Event {
1802 public Event_5(Parser yyq):base(yyq, 2218 public Event_5(Parser yyq):base(yyq,
1803 ((COLLISION_EVENT)(yyq.StackAt(0).m_value)) 2219 ((LISTEN_EVENT)(yyq.StackAt(0).m_value))
1804 .yytext){}} 2220 .yytext){}}
1805 2221
1806public class Event_6 : Event { 2222public class Event_6 : Event {
1807 public Event_6(Parser yyq):base(yyq, 2223 public Event_6(Parser yyq):base(yyq,
1808 ((COLLISION_END_EVENT)(yyq.StackAt(0).m_value)) 2224 ((MONEY_EVENT)(yyq.StackAt(0).m_value))
1809 .yytext){}} 2225 .yytext){}}
1810 2226
1811public class Event_7 : Event { 2227public class Event_7 : Event {
1812 public Event_7(Parser yyq):base(yyq, 2228 public Event_7(Parser yyq):base(yyq,
1813 ((COLLISION_START_EVENT)(yyq.StackAt(0).m_value)) 2229 ((REMOTE_DATA_EVENT)(yyq.StackAt(0).m_value))
1814 .yytext){}} 2230 .yytext){}}
1815 2231
1816public class Event_8 : Event { 2232public class Event_8 : Event {
1817 public Event_8(Parser yyq):base(yyq, 2233 public Event_8(Parser yyq):base(yyq,
1818 ((CONTROL_EVENT)(yyq.StackAt(0).m_value)) 2234 ((HTTP_REQUEST_EVENT)(yyq.StackAt(0).m_value))
1819 .yytext){}} 2235 .yytext){}}
1820 2236
1821public class Event_9 : Event { 2237public class VoidArgEvent_1 : VoidArgEvent {
1822 public Event_9(Parser yyq):base(yyq, 2238 public VoidArgEvent_1(Parser yyq):base(yyq,
1823 ((DATASERVER_EVENT)(yyq.StackAt(0).m_value)) 2239 ((STATE_ENTRY_EVENT)(yyq.StackAt(0).m_value))
1824 .yytext){}} 2240 .yytext){}}
1825 2241
1826public class Event_10 : Event { 2242public class VoidArgEvent_2 : VoidArgEvent {
1827 public Event_10(Parser yyq):base(yyq, 2243 public VoidArgEvent_2(Parser yyq):base(yyq,
1828 ((EMAIL_EVENT)(yyq.StackAt(0).m_value)) 2244 ((STATE_EXIT_EVENT)(yyq.StackAt(0).m_value))
1829 .yytext){}} 2245 .yytext){}}
1830 2246
1831public class Event_11 : Event { 2247public class VoidArgEvent_3 : VoidArgEvent {
1832 public Event_11(Parser yyq):base(yyq, 2248 public VoidArgEvent_3(Parser yyq):base(yyq,
1833 ((HTTP_RESPONSE_EVENT)(yyq.StackAt(0).m_value)) 2249 ((MOVING_END_EVENT)(yyq.StackAt(0).m_value))
1834 .yytext){}} 2250 .yytext){}}
1835 2251
1836public class Event_12 : Event { 2252public class VoidArgEvent_4 : VoidArgEvent {
1837 public Event_12(Parser yyq):base(yyq, 2253 public VoidArgEvent_4(Parser yyq):base(yyq,
1838 ((LAND_COLLISION_EVENT)(yyq.StackAt(0).m_value)) 2254 ((MOVING_START_EVENT)(yyq.StackAt(0).m_value))
1839 .yytext){}} 2255 .yytext){}}
1840 2256
1841public class Event_13 : Event { 2257public class VoidArgEvent_5 : VoidArgEvent {
1842 public Event_13(Parser yyq):base(yyq, 2258 public VoidArgEvent_5(Parser yyq):base(yyq,
1843 ((LAND_COLLISION_END_EVENT)(yyq.StackAt(0).m_value)) 2259 ((NO_SENSOR_EVENT)(yyq.StackAt(0).m_value))
1844 .yytext){}} 2260 .yytext){}}
1845 2261
1846public class Event_14 : Event { 2262public class VoidArgEvent_6 : VoidArgEvent {
1847 public Event_14(Parser yyq):base(yyq, 2263 public VoidArgEvent_6(Parser yyq):base(yyq,
1848 ((LAND_COLLISION_START_EVENT)(yyq.StackAt(0).m_value)) 2264 ((NOT_AT_ROT_TARGET_EVENT)(yyq.StackAt(0).m_value))
1849 .yytext){}} 2265 .yytext){}}
1850 2266
1851public class Event_15 : Event { 2267public class VoidArgEvent_7 : VoidArgEvent {
1852 public Event_15(Parser yyq):base(yyq, 2268 public VoidArgEvent_7(Parser yyq):base(yyq,
1853 ((LINK_MESSAGE_EVENT)(yyq.StackAt(0).m_value)) 2269 ((NOT_AT_TARGET_EVENT)(yyq.StackAt(0).m_value))
1854 .yytext){}} 2270 .yytext){}}
1855 2271
1856public class Event_16 : Event { 2272public class VoidArgEvent_8 : VoidArgEvent {
1857 public Event_16(Parser yyq):base(yyq, 2273 public VoidArgEvent_8(Parser yyq):base(yyq,
1858 ((LISTEN_EVENT)(yyq.StackAt(0).m_value)) 2274 ((TIMER_EVENT)(yyq.StackAt(0).m_value))
1859 .yytext){}} 2275 .yytext){}}
1860 2276
1861public class Event_17 : Event { 2277public class KeyArgEvent_1 : KeyArgEvent {
1862 public Event_17(Parser yyq):base(yyq, 2278 public KeyArgEvent_1(Parser yyq):base(yyq,
1863 ((MONEY_EVENT)(yyq.StackAt(0).m_value)) 2279 ((ATTACH_EVENT)(yyq.StackAt(0).m_value))
1864 .yytext){}} 2280 .yytext){}}
1865 2281
1866public class Event_18 : Event { 2282public class KeyArgEvent_2 : KeyArgEvent {
1867 public Event_18(Parser yyq):base(yyq, 2283 public KeyArgEvent_2(Parser yyq):base(yyq,
1868 ((MOVING_END_EVENT)(yyq.StackAt(0).m_value)) 2284 ((OBJECT_REZ_EVENT)(yyq.StackAt(0).m_value))
1869 .yytext){}} 2285 .yytext){}}
1870 2286
1871public class Event_19 : Event { 2287public class IntArgEvent_1 : IntArgEvent {
1872 public Event_19(Parser yyq):base(yyq, 2288 public IntArgEvent_1(Parser yyq):base(yyq,
1873 ((MOVING_START_EVENT)(yyq.StackAt(0).m_value)) 2289 ((CHANGED_EVENT)(yyq.StackAt(0).m_value))
1874 .yytext){}} 2290 .yytext){}}
1875 2291
1876public class Event_20 : Event { 2292public class IntArgEvent_2 : IntArgEvent {
1877 public Event_20(Parser yyq):base(yyq, 2293 public IntArgEvent_2(Parser yyq):base(yyq,
1878 ((NO_SENSOR_EVENT)(yyq.StackAt(0).m_value)) 2294 ((COLLISION_EVENT)(yyq.StackAt(0).m_value))
1879 .yytext){}} 2295 .yytext){}}
1880 2296
1881public class Event_21 : Event { 2297public class IntArgEvent_3 : IntArgEvent {
1882 public Event_21(Parser yyq):base(yyq, 2298 public IntArgEvent_3(Parser yyq):base(yyq,
1883 ((NOT_AT_ROT_TARGET_EVENT)(yyq.StackAt(0).m_value)) 2299 ((COLLISION_END_EVENT)(yyq.StackAt(0).m_value))
1884 .yytext){}} 2300 .yytext){}}
1885 2301
1886public class Event_22 : Event { 2302public class IntArgEvent_4 : IntArgEvent {
1887 public Event_22(Parser yyq):base(yyq, 2303 public IntArgEvent_4(Parser yyq):base(yyq,
1888 ((NOT_AT_TARGET_EVENT)(yyq.StackAt(0).m_value)) 2304 ((COLLISION_START_EVENT)(yyq.StackAt(0).m_value))
1889 .yytext){}} 2305 .yytext){}}
1890 2306
1891public class Event_23 : Event { 2307public class IntArgEvent_5 : IntArgEvent {
1892 public Event_23(Parser yyq):base(yyq, 2308 public IntArgEvent_5(Parser yyq):base(yyq,
1893 ((OBJECT_REZ_EVENT)(yyq.StackAt(0).m_value)) 2309 ((ON_REZ_EVENT)(yyq.StackAt(0).m_value))
1894 .yytext){}} 2310 .yytext){}}
1895 2311
1896public class Event_24 : Event { 2312public class IntArgEvent_6 : IntArgEvent {
1897 public Event_24(Parser yyq):base(yyq, 2313 public IntArgEvent_6(Parser yyq):base(yyq,
1898 ((ON_REZ_EVENT)(yyq.StackAt(0).m_value)) 2314 ((RUN_TIME_PERMISSIONS_EVENT)(yyq.StackAt(0).m_value))
1899 .yytext){}} 2315 .yytext){}}
1900 2316
1901public class Event_25 : Event { 2317public class IntArgEvent_7 : IntArgEvent {
1902 public Event_25(Parser yyq):base(yyq, 2318 public IntArgEvent_7(Parser yyq):base(yyq,
1903 ((REMOTE_DATA_EVENT)(yyq.StackAt(0).m_value)) 2319 ((SENSOR_EVENT)(yyq.StackAt(0).m_value))
1904 .yytext){}} 2320 .yytext){}}
1905 2321
1906public class Event_26 : Event { 2322public class IntArgEvent_8 : IntArgEvent {
1907 public Event_26(Parser yyq):base(yyq, 2323 public IntArgEvent_8(Parser yyq):base(yyq,
1908 ((RUN_TIME_PERMISSIONS_EVENT)(yyq.StackAt(0).m_value)) 2324 ((TOUCH_EVENT)(yyq.StackAt(0).m_value))
1909 .yytext){}} 2325 .yytext){}}
1910 2326
1911public class Event_27 : Event { 2327public class IntArgEvent_9 : IntArgEvent {
1912 public Event_27(Parser yyq):base(yyq, 2328 public IntArgEvent_9(Parser yyq):base(yyq,
1913 ((SENSOR_EVENT)(yyq.StackAt(0).m_value)) 2329 ((TOUCH_END_EVENT)(yyq.StackAt(0).m_value))
1914 .yytext){}} 2330 .yytext){}}
1915 2331
1916public class Event_28 : Event { 2332public class IntArgEvent_10 : IntArgEvent {
1917 public Event_28(Parser yyq):base(yyq, 2333 public IntArgEvent_10(Parser yyq):base(yyq,
1918 ((STATE_ENTRY_EVENT)(yyq.StackAt(0).m_value)) 2334 ((TOUCH_START_EVENT)(yyq.StackAt(0).m_value))
1919 .yytext){}} 2335 .yytext){}}
1920 2336
1921public class Event_29 : Event { 2337public class VectorArgEvent_1 : VectorArgEvent {
1922 public Event_29(Parser yyq):base(yyq, 2338 public VectorArgEvent_1(Parser yyq):base(yyq,
1923 ((STATE_EXIT_EVENT)(yyq.StackAt(0).m_value)) 2339 ((LAND_COLLISION_EVENT)(yyq.StackAt(0).m_value))
1924 .yytext){}} 2340 .yytext){}}
1925 2341
1926public class Event_30 : Event { 2342public class VectorArgEvent_2 : VectorArgEvent {
1927 public Event_30(Parser yyq):base(yyq, 2343 public VectorArgEvent_2(Parser yyq):base(yyq,
1928 ((TIMER_EVENT)(yyq.StackAt(0).m_value)) 2344 ((LAND_COLLISION_END_EVENT)(yyq.StackAt(0).m_value))
1929 .yytext){}} 2345 .yytext){}}
1930 2346
1931public class Event_31 : Event { 2347public class VectorArgEvent_3 : VectorArgEvent {
1932 public Event_31(Parser yyq):base(yyq, 2348 public VectorArgEvent_3(Parser yyq):base(yyq,
1933 ((TOUCH_EVENT)(yyq.StackAt(0).m_value)) 2349 ((LAND_COLLISION_START_EVENT)(yyq.StackAt(0).m_value))
1934 .yytext){}} 2350 .yytext){}}
1935 2351
1936public class Event_32 : Event { 2352public class IntRotRotArgEvent_1 : IntRotRotArgEvent {
1937 public Event_32(Parser yyq):base(yyq, 2353 public IntRotRotArgEvent_1(Parser yyq):base(yyq,
1938 ((TOUCH_END_EVENT)(yyq.StackAt(0).m_value)) 2354 ((AT_ROT_TARGET_EVENT)(yyq.StackAt(0).m_value))
1939 .yytext){}} 2355 .yytext){}}
1940 2356
1941public class Event_33 : Event { 2357public class IntVecVecArgEvent_1 : IntVecVecArgEvent {
1942 public Event_33(Parser yyq):base(yyq, 2358 public IntVecVecArgEvent_1(Parser yyq):base(yyq,
1943 ((TOUCH_START_EVENT)(yyq.StackAt(0).m_value)) 2359 ((AT_TARGET_EVENT)(yyq.StackAt(0).m_value))
1944 .yytext){}} 2360 .yytext){}}
1945 2361
1946public class Event_34 : Event { 2362public class KeyIntIntArgEvent_1 : KeyIntIntArgEvent {
1947 public Event_34(Parser yyq):base(yyq, 2363 public KeyIntIntArgEvent_1(Parser yyq):base(yyq,
1948 ((HTTP_REQUEST_EVENT)(yyq.StackAt(0).m_value)) 2364 ((CONTROL_EVENT)(yyq.StackAt(0).m_value))
1949 .yytext){}} 2365 .yytext){}}
1950public class yyLSLSyntax 2366public class yyLSLSyntax
1951: YyParser { 2367: YyParser {
@@ -1979,9 +2395,9 @@ public yyLSLSyntax
197997,0,109,0,82, 239597,0,109,0,82,
19800,111,0,111,0, 23960,111,0,111,0,
1981116,0,1,96,1, 2397116,0,1,96,1,
19822,104,18,1,2717, 23982,104,18,1,2841,
1983102,2,0,105,5, 2399102,2,0,105,5,
1984320,1,0,106,18, 2400394,1,0,106,18,
19851,0,0,2,0, 24011,0,0,2,0,
19861,1,107,18,1, 24021,1,107,18,1,
19871,108,20,109,4, 24031,108,20,109,4,
@@ -2042,7 +2458,7 @@ public yyLSLSyntax
2042121,0,112,0,101, 2458121,0,112,0,101,
20430,110,0,97,0, 24590,110,0,97,0,
2044109,0,101,0,1, 2460109,0,101,0,1,
2045106,1,2,2,0, 2461123,1,2,2,0,
20461,9,131,18,1, 24621,9,131,18,1,
20479,132,20,133,4, 24639,132,20,133,4,
204810,73,0,68,0, 246410,73,0,68,0,
@@ -2071,518 +2487,665 @@ public yyLSLSyntax
2071105,0,111,0,110, 2487105,0,111,0,110,
20720,76,0,105,0, 24880,76,0,105,0,
2073115,0,116,0,1, 2489115,0,116,0,1,
2074104,1,2,2,0, 2490111,1,2,2,0,
20751,21,142,18,1, 24911,21,142,18,1,
207621,143,20,144,4, 249221,143,20,144,4,
207710,67,0,79,0, 249310,67,0,79,0,
207877,0,77,0,65, 249477,0,77,0,65,
20790,1,14,1,1, 24950,1,14,1,1,
20802,0,1,1694,145, 24962,0,1,2807,145,
208118,1,1694,146,20, 249718,1,2807,146,20,
2082147,4,32,70,0, 2498147,4,18,83,0,
249969,0,77,0,73,
25000,67,0,79,0,
250176,0,79,0,78,
25020,1,11,1,1,
25032,0,1,1694,148,
250418,1,1694,149,20,
2505150,4,32,70,0,
2083111,0,114,0,76, 2506111,0,114,0,76,
20840,111,0,111,0, 25070,111,0,111,0,
2085112,0,83,0,116, 2508112,0,83,0,116,
20860,97,0,116,0, 25090,97,0,116,0,
2087101,0,109,0,101, 2510101,0,109,0,101,
20880,110,0,116,0, 25110,110,0,116,0,
20891,122,1,2,2, 25121,146,1,2,2,
20900,1,1695,148,18, 25130,1,1695,151,18,
20911,1695,143,2,0, 25141,1695,143,2,0,
20921,30,149,18,1, 25151,2645,152,18,1,
209330,150,20,151,4, 25162645,153,20,154,4,
209422,68,0,101,0, 251734,86,0,111,0,
2518105,0,100,0,65,
25190,114,0,103,0,
252083,0,116,0,97,
25210,116,0,101,0,
252269,0,118,0,101,
25230,110,0,116,0,
25241,104,1,2,2,
25250,1,2646,155,18,
25261,2646,156,20,157,
25274,20,83,0,116,
25280,97,0,116,0,
2529101,0,69,0,118,
25300,101,0,110,0,
2531116,0,1,103,1,
25322,2,0,1,30,
2533158,18,1,30,159,
253420,160,4,22,68,
25350,101,0,99,0,
2536108,0,97,0,114,
25370,97,0,116,0,
2538105,0,111,0,110,
25390,1,118,1,2,
25402,0,1,31,161,
254118,1,31,162,20,
2542163,4,22,82,0,
254373,0,71,0,72,
25440,84,0,95,0,
254580,0,65,0,82,
25460,69,0,78,0,
25471,17,1,1,2,
25480,1,32,164,18,
25491,32,165,20,166,
25504,20,76,0,69,
25510,70,0,84,0,
255295,0,66,0,82,
25530,65,0,67,0,
255469,0,1,12,1,
25551,2,0,1,2650,
2556167,18,1,2650,168,
255720,169,4,44,73,
25580,110,0,116,0,
255982,0,111,0,116,
25600,82,0,111,0,
2561116,0,65,0,114,
25620,103,0,83,0,
2563116,0,97,0,116,
25640,101,0,69,0,
2565118,0,101,0,110,
25660,116,0,1,108,
25671,2,2,0,1,
25682819,170,18,1,2819,
2569171,20,172,4,34,
257071,0,108,0,111,
25710,98,0,97,0,
2572108,0,68,0,101,
25730,102,0,105,0,
2574110,0,105,0,116,
25750,105,0,111,0,
2576110,0,115,0,1,
257797,1,2,2,0,
25781,2652,173,18,1,
25792652,174,20,175,4,
258032,73,0,110,0,
2581116,0,65,0,114,
25820,103,0,83,0,
2583116,0,97,0,116,
25840,101,0,69,0,
2585118,0,101,0,110,
25860,116,0,1,106,
25871,2,2,0,1,
25881114,176,18,1,1114,
2589132,2,0,1,2654,
2590177,18,1,2654,153,
25912,0,1,1152,178,
259218,1,1152,179,20,
2593180,4,32,83,0,
2594105,0,109,0,112,
25950,108,0,101,0,
259665,0,115,0,115,
25970,105,0,103,0,
2598110,0,109,0,101,
25990,110,0,116,0,
26001,137,1,2,2,
26010,1,1117,181,18,
26021,1117,182,20,183,
26034,28,80,0,69,
26040,82,0,67,0,
260569,0,78,0,84,
26060,95,0,69,0,
260781,0,85,0,65,
26080,76,0,83,0,
26091,10,1,1,2,
26100,1,40,184,18,
26111,40,132,2,0,
26121,41,185,18,1,
261341,135,2,0,1,
261442,186,18,1,42,
2615187,20,188,4,20,
261669,0,120,0,112,
26170,114,0,101,0,
2618115,0,115,0,105,
26190,111,0,110,0,
26201,155,1,2,2,
26210,1,43,189,18,
26221,43,190,20,191,
26234,22,82,0,73,
26240,71,0,72,0,
262584,0,95,0,83,
26260,72,0,73,0,
262770,0,84,0,1,
262841,1,1,2,0,
26291,44,192,18,1,
263044,132,2,0,1,
26311159,193,18,1,1159,
2632187,2,0,1,46,
2633194,18,1,46,195,
263420,196,4,12,80,
26350,69,0,82,0,
263673,0,79,0,68,
26370,1,24,1,1,
26382,0,1,47,197,
263918,1,47,132,2,
26400,1,48,198,18,
26411,48,199,20,200,
26424,18,68,0,69,
26430,67,0,82,0,
264469,0,77,0,69,
26450,78,0,84,0,
26461,5,1,1,2,
26470,1,49,201,18,
26481,49,202,20,203,
26494,18,73,0,78,
26500,67,0,82,0,
265169,0,77,0,69,
26520,78,0,84,0,
26531,4,1,1,2,
26540,1,50,204,18,
26551,50,199,2,0,
26561,51,205,18,1,
265751,202,2,0,1,
265852,206,18,1,52,
2659135,2,0,1,2281,
2660207,18,1,2281,179,
26612,0,1,2839,208,
266218,1,2839,209,20,
2663210,4,48,71,0,
2664108,0,111,0,98,
26650,97,0,108,0,
266670,0,117,0,110,
26670,99,0,116,0,
2668105,0,111,0,110,
26690,68,0,101,0,
2670102,0,105,0,110,
26710,105,0,116,0,
2672105,0,111,0,110,
26730,1,99,1,2,
26742,0,1,2840,211,
267518,1,2840,212,20,
2676213,4,50,71,0,
2677108,0,111,0,98,
26780,97,0,108,0,
267986,0,97,0,114,
26800,105,0,97,0,
268198,0,108,0,101,
26820,68,0,101,0,
209599,0,108,0,97, 268399,0,108,0,97,
20960,114,0,97,0, 26840,114,0,97,0,
2097116,0,105,0,111, 2685116,0,105,0,111,
20980,110,0,1,105, 26860,110,0,1,98,
20991,2,2,0,1, 26871,2,2,0,1,
210031,152,18,1,31, 26882841,104,1,2842,214,
2101153,20,154,4,22, 268918,1,2842,215,23,
210282,0,73,0,71, 2690216,4,6,69,0,
21030,72,0,84,0, 269179,0,70,0,1,
210495,0,80,0,65, 26922,1,6,2,0,
21050,82,0,69,0, 26931,1730,217,18,1,
210678,0,1,17,1, 26941730,179,2,0,1,
21071,2,0,1,32, 26951731,218,18,1,1731,
2108155,18,1,32,156, 2696146,2,0,1,61,
210920,157,4,20,76, 2697219,18,1,61,129,
21100,69,0,70,0, 26982,0,1,62,220,
211184,0,95,0,66, 269918,1,62,162,2,
21120,82,0,65,0, 27000,1,63,221,18,
211367,0,69,0,1,
211412,1,1,2,0,
21151,1114,158,18,1,
21161114,132,2,0,1,
21171152,159,18,1,1152,
2118160,20,161,4,32,
211983,0,105,0,109,
21200,112,0,108,0,
2121101,0,65,0,115,
21220,115,0,105,0,
2123103,0,110,0,109,
21240,101,0,110,0,
2125116,0,1,113,1,
21262,2,0,1,1117,
2127162,18,1,1117,163,
212820,164,4,28,80,
21290,69,0,82,0,
213067,0,69,0,78,
21310,84,0,95,0,
213269,0,81,0,85,
21330,65,0,76,0,
213483,0,1,10,1,
21351,2,0,1,40,
2136165,18,1,40,132,
21372,0,1,41,166,
213818,1,41,135,2,
21390,1,42,167,18,
21401,42,168,20,169,
21414,20,69,0,120,
21420,112,0,114,0,
2143101,0,115,0,115,
21440,105,0,111,0,
2145110,0,1,131,1,
21462,2,0,1,43,
2147170,18,1,43,171,
214820,172,4,22,82,
21490,73,0,71,0,
215072,0,84,0,95,
21510,83,0,72,0,
215273,0,70,0,84,
21530,1,41,1,1,
21542,0,1,44,173,
215518,1,44,132,2,
21560,1,1159,174,18,
21571,1159,168,2,0,
21581,46,175,18,1,
215946,176,20,177,4,
216012,80,0,69,0,
216182,0,73,0,79,
21620,68,0,1,24,
21631,1,2,0,1,
216447,178,18,1,47,
2165132,2,0,1,48,
2166179,18,1,48,180,
216720,181,4,18,68,
21680,69,0,67,0,
216982,0,69,0,77,
21700,69,0,78,0,
217184,0,1,5,1,
21721,2,0,1,49,
2173182,18,1,49,183,
217420,184,4,18,73,
21750,78,0,67,0,
217682,0,69,0,77,
21770,69,0,78,0,
217884,0,1,4,1,
21791,2,0,1,50,
2180185,18,1,50,180,
21812,0,1,51,186,
218218,1,51,183,2,
21830,1,52,187,18,
21841,52,135,2,0,
21851,2281,188,18,1,
21862281,160,2,0,1,
21871730,189,18,1,1730,
2188160,2,0,1,1731,
2189190,18,1,1731,191,
219020,192,4,18,83,
21910,69,0,77,0,
219273,0,67,0,79,
21930,76,0,79,0,
219478,0,1,11,1,
21951,2,0,1,61,
2196193,18,1,61,129,
21972,0,1,62,194,
219818,1,62,153,2,
21990,1,63,195,18,
22001,63,132,2,0, 27011,63,132,2,0,
22011,65,196,18,1, 27021,65,222,18,1,
220265,176,2,0,1, 270365,195,2,0,1,
220366,197,18,1,66, 270466,223,18,1,66,
2204132,2,0,1,67, 2705132,2,0,1,67,
2205198,18,1,67,180, 2706224,18,1,67,199,
22062,0,1,68,199, 27072,0,1,68,225,
220718,1,68,183,2, 270818,1,68,202,2,
22080,1,69,200,18, 27090,1,69,226,18,
22091,69,180,2,0, 27101,69,199,2,0,
22101,70,201,18,1, 27111,70,227,18,1,
221170,183,2,0,1, 271270,202,2,0,1,
221271,202,18,1,71, 271371,228,18,1,71,
2213135,2,0,1,73, 2714135,2,0,1,73,
2214203,18,1,73,168, 2715229,18,1,73,187,
22152,0,1,74,204, 27162,0,1,74,230,
221618,1,74,153,2, 271718,1,74,162,2,
22170,1,1189,205,18, 27180,1,1189,231,18,
22181,1189,206,20,207, 27191,1189,232,20,233,
22194,22,83,0,84, 27204,22,83,0,84,
22200,65,0,82,0, 27210,65,0,82,0,
222195,0,69,0,81, 272295,0,69,0,81,
22220,85,0,65,0, 27230,85,0,65,0,
222376,0,83,0,1, 272476,0,83,0,1,
22248,1,1,2,0, 27258,1,1,2,0,
22251,76,208,18,1, 27261,76,234,18,1,
222676,209,20,210,4, 272776,235,20,236,4,
222720,76,0,69,0, 272820,76,0,69,0,
222870,0,84,0,95, 272970,0,84,0,95,
22290,83,0,72,0, 27300,83,0,72,0,
223073,0,70,0,84, 273173,0,70,0,84,
22310,1,40,1,1, 27320,1,40,1,1,
22322,0,1,1153,211, 27332,0,1,1153,237,
223318,1,1153,212,20, 273418,1,1153,238,20,
2234213,4,24,83,0, 2735239,4,24,83,0,
223576,0,65,0,83, 273676,0,65,0,83,
22360,72,0,95,0, 27370,72,0,95,0,
223769,0,81,0,85, 273869,0,81,0,85,
22380,65,0,76,0, 27390,65,0,76,0,
223983,0,1,9,1, 274083,0,1,9,1,
22401,2,0,1,79, 27411,2,0,1,79,
2241214,18,1,79,215, 2742240,18,1,79,241,
224220,216,4,10,84, 274320,242,4,10,84,
22430,73,0,76,0, 27440,73,0,76,0,
224468,0,69,0,1, 274568,0,69,0,1,
224536,1,1,2,0, 274636,1,1,2,0,
22461,1195,217,18,1, 27471,1195,243,18,1,
22471195,168,2,0,1, 27481195,187,2,0,1,
224882,218,18,1,82, 274982,244,18,1,82,
2249168,2,0,1,1123, 2750187,2,0,1,1123,
2250219,18,1,1123,168, 2751245,18,1,1123,187,
22512,0,1,85,220, 27522,0,1,85,246,
225218,1,85,221,20, 275318,1,85,247,20,
2253222,4,26,83,0, 2754248,4,26,83,0,
225484,0,82,0,79, 275584,0,82,0,79,
22550,75,0,69,0, 27560,75,0,69,0,
225695,0,83,0,84, 275795,0,83,0,84,
22570,82,0,79,0, 27580,82,0,79,0,
225875,0,69,0,1, 275975,0,69,0,1,
225939,1,1,2,0, 276039,1,1,2,0,
22601,89,223,18,1, 27611,2547,249,18,1,
226189,224,20,225,4, 27622547,250,20,251,4,
226210,77,0,73,0, 276364,73,0,110,0,
226378,0,85,0,83, 2764116,0,82,0,111,
22640,1,19,1,1, 27650,116,0,82,0,
22652,0,1,2318,226, 2766111,0,116,0,65,
226618,1,2318,191,2, 27670,114,0,103,0,
22670,1,93,227,18, 2768117,0,109,0,101,
22681,93,168,2,0, 27690,110,0,116,0,
22691,97,228,18,1, 277068,0,101,0,99,
227097,229,20,230,4, 27710,108,0,97,0,
2772114,0,97,0,116,
27730,105,0,111,0,
2774110,0,76,0,105,
27750,115,0,116,0,
27761,115,1,2,2,
27770,1,89,252,18,
27781,89,253,20,254,
27794,10,77,0,73,
27800,78,0,85,0,
278183,0,1,19,1,
27821,2,0,1,2318,
2783255,18,1,2318,146,
27842,0,1,2788,256,
278518,1,2788,187,2,
27860,1,93,257,18,
27871,93,187,2,0,
27881,97,258,18,1,
278997,259,20,260,4,
227114,65,0,77,0, 279014,65,0,77,0,
227280,0,95,0,65, 279180,0,95,0,65,
22730,77,0,80,0, 27920,77,0,80,0,
22741,38,1,1,2, 27931,38,1,1,2,
22750,1,102,231,18, 27940,1,102,261,18,
22761,102,232,20,233, 27951,102,262,20,263,
22774,22,69,0,88, 27964,22,69,0,88,
22780,67,0,76,0, 27970,67,0,76,0,
227965,0,77,0,65, 279865,0,77,0,65,
22800,84,0,73,0, 27990,84,0,73,0,
228179,0,78,0,1, 280079,0,78,0,1,
228237,1,1,2,0, 280137,1,1,2,0,
22831,1775,234,18,1, 28021,1775,264,18,1,
22841775,153,2,0,1, 28031775,162,2,0,1,
22852718,235,18,1,2718, 2804107,265,18,1,107,
2286236,23,237,4,6, 2805187,2,0,1,2337,
228769,0,79,0,70, 2806266,18,1,2337,162,
22880,1,2,1,6, 28072,0,1,1224,267,
22892,0,1,107,238, 280818,1,1224,179,2,
229018,1,107,168,2, 28090,1,1225,268,18,
22910,1,2337,239,18, 28101,1225,269,20,270,
22921,2337,153,2,0, 28114,24,77,0,73,
22931,1224,240,18,1, 28120,78,0,85,0,
22941224,160,2,0,1, 281383,0,95,0,69,
22951225,241,18,1,1225, 28140,81,0,85,0,
2296242,20,243,4,24, 281565,0,76,0,83,
229777,0,73,0,78, 28160,1,7,1,1,
22980,85,0,83,0, 28172,0,1,112,271,
229995,0,69,0,81, 281818,1,112,272,20,
23000,85,0,65,0, 2819273,4,28,71,0,
230176,0,83,0,1, 282082,0,69,0,65,
23027,1,1,2,0, 28210,84,0,69,0,
23031,112,244,18,1, 282282,0,95,0,69,
2304112,245,20,246,4, 28230,81,0,85,0,
230528,71,0,82,0, 282465,0,76,0,83,
230669,0,65,0,84, 28250,1,32,1,1,
23070,69,0,82,0, 28262,0,1,1188,274,
230895,0,69,0,81, 282718,1,1188,179,2,
23090,85,0,65,0, 28280,1,1231,275,18,
231076,0,83,0,1, 28291,1231,187,2,0,
231132,1,1,2,0, 28301,118,276,18,1,
23121,1188,247,18,1, 2831118,187,2,0,1,
23131188,160,2,0,1, 28321737,277,18,1,1737,
23141231,248,18,1,1231, 2833187,2,0,1,2818,
2315168,2,0,1,118, 2834278,18,1,2818,146,
2316249,18,1,118,168, 28352,0,1,124,279,
23172,0,1,1737,250, 283618,1,124,280,20,
231818,1,1737,168,2, 2837281,4,22,76,0,
23190,1,124,251,18, 283869,0,83,0,83,
23201,124,252,20,253, 28390,95,0,69,0,
23214,22,76,0,69, 284081,0,85,0,65,
23220,83,0,83,0, 28410,76,0,83,0,
232395,0,69,0,81, 28421,31,1,1,2,
23240,85,0,65,0, 28430,1,2657,282,18,
232576,0,83,0,1, 28441,2657,165,2,0,
232631,1,1,2,0, 28451,130,283,18,1,
23271,2657,254,18,1, 2846130,187,2,0,1,
23282657,150,2,0,1, 28471803,284,18,1,1803,
23292658,255,18,1,2658, 2848285,20,286,4,18,
2330256,20,257,4,12, 284983,0,116,0,97,
233169,0,81,0,85, 28500,116,0,101,0,
23320,65,0,76,0, 2851109,0,101,0,110,
233383,0,1,15,1, 28520,116,0,1,134,
23341,2,0,1,130, 28531,2,2,0,1,
2335258,18,1,130,168, 28541804,287,18,1,1804,
23362,0,1,1803,259, 2855288,20,289,4,4,
233718,1,1803,260,20, 285668,0,79,0,1,
2338261,4,18,83,0, 285744,1,1,2,0,
2339116,0,97,0,116, 28581,2830,290,18,1,
23400,101,0,109,0, 28592830,291,20,292,4,
2341101,0,110,0,116, 286012,83,0,116,0,
23420,1,110,1,2, 286197,0,116,0,101,
23432,0,1,1804,262, 28620,115,0,1,100,
234418,1,1804,263,20, 28631,2,2,0,1,
2345264,4,4,68,0, 28642364,293,18,1,2364,
234679,0,1,44,1, 2865285,2,0,1,137,
23471,2,0,1,2364, 2866294,18,1,137,295,
2348265,18,1,2364,260, 286720,296,4,36,69,
23492,0,1,137,266, 28680,88,0,67,0,
235018,1,137,267,20, 286976,0,65,0,77,
2351268,4,36,69,0, 28700,65,0,84,0,
235288,0,67,0,76, 287173,0,79,0,78,
23530,65,0,77,0, 28720,95,0,69,0,
235465,0,84,0,73, 287381,0,85,0,65,
23550,79,0,78,0, 28740,76,0,83,0,
235695,0,69,0,81, 28751,30,1,1,2,
23570,85,0,65,0, 28760,1,2293,297,18,
235876,0,83,0,1, 28771,2293,146,2,0,
235930,1,1,2,0, 28781,1701,298,18,1,
23601,2293,269,18,1, 28791701,187,2,0,1,
23612293,191,2,0,1, 28801756,299,18,1,1756,
23621701,270,18,1,1701, 2881146,2,0,1,2527,
2363168,2,0,1,1756, 2882300,18,1,2527,132,
2364271,18,1,1756,191, 28832,0,1,143,301,
23652,0,1,143,272, 288418,1,143,187,2,
236618,1,143,168,2, 28850,1,2299,302,18,
23670,1,2299,273,18, 28861,2299,187,2,0,
23681,2299,168,2,0, 28871,1260,303,18,1,
23691,1260,274,18,1, 28881260,179,2,0,1,
23701260,160,2,0,1, 28891261,304,18,1,1261,
23711261,275,18,1,1261, 2890305,20,306,4,22,
2372276,20,277,4,22,
237380,0,76,0,85, 289180,0,76,0,85,
23740,83,0,95,0, 28920,83,0,95,0,
237569,0,81,0,85, 289369,0,81,0,85,
23760,65,0,76,0, 28940,65,0,76,0,
237783,0,1,6,1, 289583,0,1,6,1,
23781,2,0,1,151, 28961,2,0,1,2528,
2379278,18,1,151,279, 2897307,18,1,2528,308,
238020,280,4,26,69, 289820,309,4,28,86,
28990,101,0,99,0,
290068,0,101,0,99,
29010,108,0,97,0,
2902114,0,97,0,116,
29030,105,0,111,0,
2904110,0,1,121,1,
29052,2,0,1,151,
2906310,18,1,151,311,
290720,312,4,26,69,
23810,81,0,85,0, 29080,81,0,85,0,
238265,0,76,0,83, 290965,0,76,0,83,
23830,95,0,69,0, 29100,95,0,69,0,
238481,0,85,0,65, 291181,0,85,0,65,
23850,76,0,83,0, 29120,76,0,83,0,
23861,29,1,1,2, 29131,29,1,1,2,
23870,1,1267,281,18, 29140,1,1267,313,18,
23881,1267,168,2,0, 29151,1267,187,2,0,
23891,157,282,18,1, 29161,2765,314,18,1,
2390157,168,2,0,1, 29172765,132,2,0,1,
23911773,283,18,1,1773, 2918157,315,18,1,157,
2392146,2,0,1,1832, 2919187,2,0,1,1773,
2393284,18,1,1832,260, 2920316,18,1,1773,149,
23942,0,1,1833,285, 29212,0,1,1832,317,
239518,1,1833,286,20, 292218,1,1832,285,2,
2396287,4,10,87,0, 29230,1,1833,318,18,
239772,0,73,0,76, 29241,1833,319,20,320,
23980,69,0,1,45, 29254,10,87,0,72,
29260,73,0,76,0,
292769,0,1,45,1,
29281,2,0,1,1834,
2929321,18,1,1834,135,
29302,0,1,166,322,
293118,1,166,323,20,
2932324,4,20,76,0,
293369,0,70,0,84,
29340,95,0,65,0,
293578,0,71,0,76,
29360,69,0,1,25,
23991,1,2,0,1, 29371,1,2,0,1,
24001834,288,18,1,1834, 29381840,325,18,1,1840,
2401135,2,0,1,166, 2939187,2,0,1,2779,
2402289,18,1,166,290, 2940326,18,1,2779,327,
240320,291,4,20,76, 294120,328,4,34,67,
24040,69,0,70,0, 29420,111,0,109,0,
240584,0,95,0,65, 2943112,0,111,0,117,
24060,78,0,71,0, 29440,110,0,100,0,
240776,0,69,0,1,
240825,1,1,2,0,
24091,1840,292,18,1,
24101840,168,2,0,1,
2411172,293,18,1,172,
2412168,2,0,1,2706,
2413294,18,1,2706,295,
241420,296,4,12,83,
24150,116,0,97,0,
2416116,0,101,0,115,
24170,1,100,1,2,
24182,0,1,2335,297,
241918,1,2335,146,2,
24200,1,1296,298,18,
24211,1296,160,2,0,
24221,1297,299,18,1,
24231297,256,2,0,1,
24242413,300,18,1,2413,
2425301,20,302,4,26,
242683,0,116,0,97, 294583,0,116,0,97,
24270,116,0,101,0, 29460,116,0,101,0,
2428109,0,101,0,110, 2947109,0,101,0,110,
24290,116,0,76,0, 29480,116,0,1,132,
2430105,0,115,0,116, 29491,2,2,0,1,
24310,1,109,1,2, 2950172,329,18,1,172,
24322,0,1,1859,303, 2951187,2,0,1,2335,
243318,1,1859,153,2, 2952330,18,1,2335,149,
24340,1,1860,304,18, 29532,0,1,1296,331,
24351,1860,191,2,0, 295418,1,1296,179,2,
24361,188,305,18,1, 29550,1,1297,332,18,
2437188,168,2,0,1, 29561,1297,333,20,334,
2438182,306,18,1,182, 29574,12,69,0,81,
2439307,20,308,4,22, 29580,85,0,65,0,
244082,0,73,0,71, 295976,0,83,0,1,
24410,72,0,84,0, 296015,1,1,2,0,
244295,0,65,0,78, 29611,2413,335,18,1,
24430,71,0,76,0, 29622413,336,20,337,4,
244469,0,1,26,1, 296326,83,0,116,0,
24451,2,0,1,199, 296497,0,116,0,101,
2446309,18,1,199,310, 29650,109,0,101,0,
244720,311,4,10,67, 2966110,0,116,0,76,
24480,65,0,82,0, 29670,105,0,115,0,
244969,0,84,0,1, 2968116,0,1,133,1,
245035,1,1,2,0, 29692,2,0,1,1859,
24511,1871,312,18,1, 2970338,18,1,1859,162,
24521871,160,2,0,1, 29712,0,1,1860,339,
24531872,313,18,1,1872, 297218,1,1860,146,2,
2454153,2,0,1,1873, 29730,1,188,340,18,
2455314,18,1,1873,191, 29741,188,187,2,0,
24562,0,1,1875,315, 29751,182,341,18,1,
245718,1,1875,286,2, 2976182,342,20,343,4,
24580,1,205,316,18, 297722,82,0,73,0,
24591,205,168,2,0, 297871,0,72,0,84,
24601,2515,317,18,1, 29790,95,0,65,0,
24612515,140,2,0,1, 298078,0,71,0,76,
24621882,318,18,1,1882, 29810,69,0,1,26,
2463168,2,0,1,2227, 29821,1,2,0,1,
2464319,18,1,2227,260, 2983199,344,18,1,199,
24652,0,1,217,320, 2984345,20,346,4,10,
246618,1,217,321,20, 298567,0,65,0,82,
2467322,4,12,83,0, 29860,69,0,84,0,
29871,35,1,1,2,
29880,1,1871,347,18,
29891,1871,179,2,0,
29901,1872,348,18,1,
29911872,162,2,0,1,
29921873,349,18,1,1873,
2993146,2,0,1,1875,
2994350,18,1,1875,319,
29952,0,1,205,351,
299618,1,205,187,2,
29970,1,2581,352,18,
29981,2581,135,2,0,
29991,1882,353,18,1,
30001882,187,2,0,1,
30012227,354,18,1,2227,
3002285,2,0,1,2590,
3003355,18,1,2590,140,
30042,0,1,217,356,
300518,1,217,357,20,
3006358,4,12,83,0,
246884,0,82,0,79, 300784,0,82,0,79,
24690,75,0,69,0, 30080,75,0,69,0,
24701,34,1,1,2, 30091,34,1,1,2,
24710,1,1332,323,18, 30100,1,1332,359,18,
24721,1332,160,2,0, 30111,1332,179,2,0,
24731,1335,324,18,1, 30121,1335,360,18,1,
24741335,163,2,0,1, 30131335,182,2,0,1,
2475223,325,18,1,223, 3014223,361,18,1,223,
2476168,2,0,1,1341, 3015187,2,0,1,1341,
2477326,18,1,1341,168, 3016362,18,1,1341,187,
24782,0,1,1901,327, 30172,0,1,1901,363,
247918,1,1901,153,2, 301818,1,1901,162,2,
24800,1,1303,328,18, 30190,1,1303,364,18,
24811,1303,168,2,0, 30201,1303,187,2,0,
24821,2462,329,18,1, 30211,2837,365,18,1,
24832462,260,2,0,1, 30222837,209,2,0,1,
2484236,330,18,1,236, 30232838,366,18,1,2838,
2485331,20,332,4,6, 3024212,2,0,1,2462,
248665,0,77,0,80, 3025367,18,1,2462,285,
24870,1,33,1,1, 30262,0,1,236,368,
24882,0,1,2466,333, 302718,1,236,369,20,
248918,1,2466,334,20, 3028370,4,6,65,0,
2490335,4,34,67,0, 302977,0,80,0,1,
2491111,0,109,0,112, 303033,1,1,2,0,
24920,111,0,117,0, 30311,2466,371,18,1,
2493110,0,100,0,83, 30322466,327,2,0,1,
24940,116,0,97,0, 30332467,372,18,1,2467,
2495116,0,101,0,109, 3034159,2,0,1,2468,
24960,101,0,110,0, 3035373,18,1,2468,374,
2497116,0,1,108,1, 303620,375,4,10,83,
24982,2,0,1,2467, 30370,84,0,65,0,
2499336,18,1,2467,150, 303884,0,69,0,1,
25002,0,1,2468,337, 303948,1,1,2,0,
250118,1,2468,338,20, 30401,2469,376,18,1,
2502339,4,10,83,0, 30412469,132,2,0,1,
250384,0,65,0,84, 3042242,377,18,1,242,
25040,69,0,1,48, 3043187,2,0,1,2471,
25051,1,2,0,1, 3044378,18,1,2471,379,
25062469,340,18,1,2469, 304520,380,4,26,67,
2507132,2,0,1,242, 30460,79,0,78,0,
2508341,18,1,242,168, 304784,0,82,0,79,
25092,0,1,2471,342, 30480,76,0,95,0,
251018,1,2471,343,20,
2511344,4,36,72,0,
251284,0,84,0,80,
25130,95,0,82,0,
251469,0,81,0,85,
25150,69,0,83,0,
251684,0,95,0,69,
25170,86,0,69,0,
251878,0,84,0,1,
251991,1,1,2,0,
25201,2472,345,18,1,
25212472,346,20,347,4,
252234,84,0,79,0,
252385,0,67,0,72,
25240,95,0,83,0,
252584,0,65,0,82,
25260,84,0,95,0,
252769,0,86,0,69, 304969,0,86,0,69,
25280,78,0,84,0, 30500,78,0,84,0,
25291,89,1,1,2, 30511,65,1,1,2,
25300,1,2473,348,18, 30520,1,2472,381,18,
25311,2473,349,20,350, 30531,2472,382,20,383,
25324,30,84,0,79, 30544,30,65,0,84,
25330,85,0,67,0, 30550,95,0,84,0,
253472,0,95,0,69, 305665,0,82,0,71,
25350,78,0,68,0, 30570,69,0,84,0,
305895,0,69,0,86,
30590,69,0,78,0,
306084,0,1,59,1,
30611,2,0,1,2473,
3062384,18,1,2473,385,
306320,386,4,38,65,
30640,84,0,95,0,
306582,0,79,0,84,
30660,95,0,84,0,
306765,0,82,0,71,
30680,69,0,84,0,
253695,0,69,0,86, 306995,0,69,0,86,
25370,69,0,78,0, 30700,69,0,78,0,
253884,0,1,90,1, 307184,0,1,58,1,
25391,2,0,1,2474, 30721,2,0,1,2474,
2540351,18,1,2474,352, 3073387,18,1,2474,388,
254120,353,4,22,84, 307420,389,4,52,76,
25420,79,0,85,0, 30750,65,0,78,0,
254367,0,72,0,95, 307668,0,95,0,67,
30770,79,0,76,0,
307876,0,73,0,83,
30790,73,0,79,0,
308078,0,95,0,83,
30810,84,0,65,0,
308282,0,84,0,95,
25440,69,0,86,0, 30830,69,0,86,0,
254569,0,78,0,84, 308469,0,78,0,84,
25460,1,88,1,1, 30850,1,71,1,1,
25472,0,1,2475,354, 30862,0,1,2475,390,
254818,1,2475,355,20, 308718,1,2475,391,20,
2549356,4,22,84,0, 3088392,4,48,76,0,
255073,0,77,0,69, 308965,0,78,0,68,
25510,82,0,95,0, 30900,95,0,67,0,
255269,0,86,0,69, 309179,0,76,0,76,
25530,78,0,84,0, 30920,73,0,83,0,
25541,87,1,1,2, 309373,0,79,0,78,
25550,1,2476,357,18, 30940,95,0,69,0,
25561,2476,358,20,359, 309578,0,68,0,95,
25574,32,83,0,84, 30960,69,0,86,0,
25580,65,0,84,0, 309769,0,78,0,84,
255969,0,95,0,69, 30980,1,70,1,1,
25600,88,0,73,0, 30992,0,1,2476,393,
310018,1,2476,394,20,
3101395,4,40,76,0,
310265,0,78,0,68,
31030,95,0,67,0,
310479,0,76,0,76,
31050,73,0,83,0,
310673,0,79,0,78,
31070,95,0,69,0,
310886,0,69,0,78,
31090,84,0,1,69,
31101,1,2,0,1,
31112477,396,18,1,2477,
3112397,20,398,4,34,
311384,0,79,0,85,
31140,67,0,72,0,
311595,0,83,0,84,
31160,65,0,82,0,
256184,0,95,0,69, 311784,0,95,0,69,
25620,86,0,69,0, 31180,86,0,69,0,
256378,0,84,0,1, 311978,0,84,0,1,
256486,1,1,2,0, 312089,1,1,2,0,
25651,2477,360,18,1, 31211,2478,399,18,1,
25662477,361,20,362,4, 31222478,400,20,401,4,
256734,83,0,84,0, 312330,84,0,79,0,
256865,0,84,0,69, 312485,0,67,0,72,
25690,95,0,69,0, 31250,95,0,69,0,
257078,0,84,0,82, 312678,0,68,0,95,
25710,89,0,95,0, 31270,69,0,86,0,
312869,0,78,0,84,
31290,1,90,1,1,
31302,0,1,2479,402,
313118,1,2479,403,20,
3132404,4,22,84,0,
313379,0,85,0,67,
31340,72,0,95,0,
257269,0,86,0,69, 313569,0,86,0,69,
25730,78,0,84,0, 31360,78,0,84,0,
25741,85,1,1,2, 31371,88,1,1,2,
25750,1,2478,363,18, 31380,1,2480,405,18,
25761,2478,364,20,365, 31391,2480,406,20,407,
25774,24,83,0,69, 31404,24,83,0,69,
25780,78,0,83,0, 31410,78,0,83,0,
257979,0,82,0,95, 314279,0,82,0,95,
25800,69,0,86,0, 31430,69,0,86,0,
258169,0,78,0,84, 314469,0,78,0,84,
25820,1,84,1,1, 31450,1,84,1,1,
25832,0,1,2479,366, 31462,0,1,2481,408,
258418,1,2479,367,20, 314718,1,2481,409,20,
2585368,4,52,82,0, 3148410,4,52,82,0,
258685,0,78,0,95, 314985,0,78,0,95,
25870,84,0,73,0, 31500,84,0,73,0,
258877,0,69,0,95, 315177,0,69,0,95,
@@ -2594,291 +3157,125 @@ public yyLSLSyntax
259469,0,86,0,69, 315769,0,86,0,69,
25950,78,0,84,0, 31580,78,0,84,0,
25961,83,1,1,2, 31591,83,1,1,2,
25970,1,2480,369,18, 31600,1,2482,411,18,
25981,2480,370,20,371, 31611,2482,412,20,413,
25994,34,82,0,69, 31624,24,79,0,78,
26000,77,0,79,0,
260184,0,69,0,95,
26020,68,0,65,0,
260384,0,65,0,95,
26040,69,0,86,0,
260569,0,78,0,84,
26060,1,82,1,1,
26072,0,1,2481,372,
260818,1,2481,373,20,
2609374,4,24,79,0,
261078,0,95,0,82,
26110,69,0,90,0,
261295,0,69,0,86,
26130,69,0,78,0,
261484,0,1,81,1,
26151,2,0,1,2482,
2616375,18,1,2482,376,
261720,377,4,32,79,
26180,66,0,74,0,
261969,0,67,0,84,
26200,95,0,82,0, 31630,95,0,82,0,
262169,0,90,0,95, 316469,0,90,0,95,
26220,69,0,86,0, 31650,69,0,86,0,
262369,0,78,0,84, 316669,0,78,0,84,
26240,1,80,1,1, 31670,1,81,1,1,
26252,0,1,2483,378, 31682,0,1,2483,414,
262618,1,2483,379,20, 316918,1,2483,415,20,
2627380,4,38,78,0, 3170416,4,42,67,0,
262879,0,84,0,95,
26290,65,0,84,0,
263095,0,84,0,65,
26310,82,0,71,0,
263269,0,84,0,95,
26330,69,0,86,0,
263469,0,78,0,84,
26350,1,79,1,1,
26362,0,1,256,381,
263718,1,256,382,20,
2638383,4,14,80,0,
263969,0,82,0,67,
26400,69,0,78,0,
264184,0,1,22,1,
26421,2,0,1,1371,
2643384,18,1,1371,212,
26442,0,1,2486,385,
264518,1,2486,386,20,
2646387,4,36,77,0,
264779,0,86,0,73,
26480,78,0,71,0,
264995,0,83,0,84,
26500,65,0,82,0,
265184,0,95,0,69,
26520,86,0,69,0,
265378,0,84,0,1,
265476,1,1,2,0,
26551,2487,388,18,1,
26562487,389,20,390,4,
265732,77,0,79,0,
265886,0,73,0,78,
26590,71,0,95,0,
266069,0,78,0,68,
26610,95,0,69,0,
266286,0,69,0,78,
26630,84,0,1,75,
26641,1,2,0,1,
26651931,391,18,1,1931,
2666260,2,0,1,1932,
2667392,18,1,1932,393,
266820,394,4,4,73,
26690,70,0,1,42,
26701,1,2,0,1,
2671262,395,18,1,262,
2672168,2,0,1,1377,
2673396,18,1,1377,168,
26742,0,1,2492,397,
267518,1,2492,398,20,
2676399,4,48,76,0,
267765,0,78,0,68,
26780,95,0,67,0,
267979,0,76,0,76, 317179,0,76,0,76,
26800,73,0,83,0, 31720,73,0,83,0,
268173,0,79,0,78, 317373,0,79,0,78,
26820,95,0,69,0, 31740,95,0,83,0,
268378,0,68,0,95, 317584,0,65,0,82,
26840,69,0,86,0, 31760,84,0,95,0,
268569,0,78,0,84,
26860,1,70,1,1,
26872,0,1,1876,400,
268818,1,1876,135,2,
26890,1,2494,401,18,
26901,2494,402,20,403,
26914,38,72,0,84,
26920,84,0,80,0,
269395,0,82,0,69,
26940,83,0,80,0,
269579,0,78,0,83,
26960,69,0,95,0,
269769,0,86,0,69, 317769,0,86,0,69,
26980,78,0,84,0, 31780,78,0,84,0,
26991,68,1,1,2, 31791,64,1,1,2,
27000,1,2495,404,18, 31800,1,256,417,18,
27011,2495,405,20,406, 31811,256,418,20,419,
27024,22,69,0,77, 31824,14,80,0,69,
27030,65,0,73,0, 31830,82,0,67,0,
270476,0,95,0,69,
27050,86,0,69,0,
270678,0,84,0,1,
270767,1,1,2,0,
27081,1939,407,18,1,
27091939,168,2,0,1,
27102497,408,18,1,2497,
2711409,20,410,4,26,
271267,0,79,0,78,
27130,84,0,82,0,
271479,0,76,0,95,
27150,69,0,86,0,
271669,0,78,0,84, 318469,0,78,0,84,
27170,1,65,1,1, 31850,1,22,1,1,
27182,0,1,827,411, 31862,0,1,1371,420,
271918,1,827,168,2, 318718,1,1371,238,2,
27200,1,2499,412,18, 31880,1,2486,421,18,
27211,2499,413,20,414, 31891,2486,422,20,423,
27224,38,67,0,79, 31904,26,67,0,72,
27230,76,0,76,0, 31910,65,0,78,0,
272473,0,83,0,73, 319271,0,69,0,68,
27250,79,0,78,0, 31930,95,0,69,0,
272695,0,69,0,78, 319486,0,69,0,78,
27270,68,0,95,0, 31950,84,0,1,61,
272869,0,86,0,69, 31961,1,2,0,1,
27290,78,0,84,0, 31972487,424,18,1,2487,
27301,63,1,1,2, 3198425,20,426,4,32,
27310,1,2500,415,18, 319979,0,66,0,74,
27321,2500,416,20,417, 32000,69,0,67,0,
27334,30,67,0,79, 320184,0,95,0,82,
27340,76,0,76,0, 32020,69,0,90,0,
273573,0,83,0,73, 320395,0,69,0,86,
27360,79,0,78,0, 32040,69,0,78,0,
320584,0,1,80,1,
32061,2,0,1,1931,
3207427,18,1,1931,285,
32082,0,1,1932,428,
320918,1,1932,429,20,
3210430,4,4,73,0,
321170,0,1,42,1,
32121,2,0,1,262,
3213431,18,1,262,187,
32142,0,1,1377,432,
321518,1,1377,187,2,
32160,1,2492,433,18,
32171,2492,434,20,435,
32184,30,78,0,79,
32190,95,0,83,0,
322069,0,78,0,83,
32210,79,0,82,0,
273795,0,69,0,86, 322295,0,69,0,86,
27380,69,0,78,0, 32230,69,0,78,0,
273984,0,1,62,1, 322484,0,1,77,1,
27401,2,0,1,2501, 32251,2,0,1,1876,
2741418,18,1,2501,419, 3226436,18,1,1876,135,
274220,420,4,26,67, 32272,0,1,2494,437,
27430,72,0,65,0, 322818,1,2494,438,20,
274478,0,71,0,69, 3229439,4,32,77,0,
323079,0,86,0,73,
32310,78,0,71,0,
323295,0,69,0,78,
27450,68,0,95,0, 32330,68,0,95,0,
274669,0,86,0,69, 323469,0,86,0,69,
27470,78,0,84,0, 32350,78,0,84,0,
27481,61,1,1,2, 32361,75,1,1,2,
27490,1,2502,421,18, 32370,1,2495,440,18,
27501,2502,422,20,423, 32381,2495,441,20,442,
27514,24,65,0,84, 32394,32,83,0,84,
27520,84,0,65,0, 32400,65,0,84,0,
275367,0,72,0,95, 324169,0,95,0,69,
32420,88,0,73,0,
324384,0,95,0,69,
32440,86,0,69,0,
324578,0,84,0,1,
324686,1,1,2,0,
32471,1939,443,18,1,
32481939,187,2,0,1,
32492497,444,18,1,2497,
3250445,20,446,4,36,
325172,0,84,0,84,
32520,80,0,95,0,
325382,0,69,0,81,
32540,85,0,69,0,
325583,0,84,0,95,
27540,69,0,86,0, 32560,69,0,86,0,
275569,0,78,0,84, 325769,0,78,0,84,
27560,1,60,1,1, 32580,1,91,1,1,
27572,0,1,2503,424, 32592,0,1,827,447,
275818,1,2503,425,20, 326018,1,827,187,2,
2759426,4,30,65,0, 32610,1,2499,448,18,
276084,0,95,0,84, 32621,2499,449,20,450,
27610,65,0,82,0,
276271,0,69,0,84,
27630,95,0,69,0,
276486,0,69,0,78,
27650,84,0,1,59,
27661,1,2,0,1,
27672504,427,18,1,2504,
2768428,20,429,4,38,
276965,0,84,0,95,
27700,82,0,79,0,
277184,0,95,0,84,
27720,65,0,82,0,
277371,0,69,0,84,
27740,95,0,69,0,
277586,0,69,0,78,
27760,84,0,1,58,
27771,1,2,0,1,
2778277,430,18,1,277,
2779431,20,432,4,10,
278083,0,76,0,65,
27810,83,0,72,0,
27821,21,1,1,2,
27830,1,2506,433,18,
27841,2506,135,2,0,
27851,283,434,18,1,
2786283,168,2,0,1,
27871958,435,18,1,1958,
2788153,2,0,1,2517,
2789436,18,1,2517,153,
27902,0,1,2519,437,
279118,1,2519,334,2,
27920,1,1406,438,18,
27931,1406,160,2,0,
27941,1407,439,18,1,
27951407,206,2,0,1,
2796299,440,18,1,299,
2797441,20,442,4,8,
279883,0,84,0,65,
27990,82,0,1,20,
28001,1,2,0,1,
28011370,443,18,1,1370,
2802160,2,0,1,305,
2803444,18,1,305,168,
28042,0,1,2458,445,
280518,1,2458,260,2,
28060,1,2459,446,18,
28071,2459,447,20,448,
28084,22,82,0,73,
28090,71,0,72,0,
281084,0,95,0,66,
28110,82,0,65,0,
281267,0,69,0,1,
281313,1,1,2,0,
28141,2464,449,18,1,
28152464,447,2,0,1,
28161989,450,18,1,1989,
2817260,2,0,1,1990,
2818451,18,1,1990,452,
281920,453,4,8,69,
28200,76,0,83,0,
282169,0,1,43,1,
28221,2,0,1,2470,
2823454,18,1,2470,156,
28242,0,1,322,455,
282518,1,322,224,2,
28260,1,1933,456,18,
28271,1933,135,2,0,
28281,883,457,18,1,
2829883,168,2,0,1,
2830328,458,18,1,328,
2831168,2,0,1,1443,
2832459,18,1,1443,242,
28332,0,1,2558,460,
283418,1,2558,447,2,
28350,1,2559,461,18,
28361,2559,462,20,463,
28374,20,83,0,116,
28380,97,0,116,0,
2839101,0,69,0,118,
28400,101,0,110,0,
2841116,0,1,103,1,
28422,2,0,1,2560,
2843464,18,1,2560,465,
284420,466,4,26,68,
28450,69,0,70,0,
284665,0,85,0,76,
28470,84,0,95,0,
284883,0,84,0,65,
28490,84,0,69,0,
28501,47,1,1,2,
28510,1,2561,467,18,
28521,2561,156,2,0,
28531,1449,468,18,1,
28541449,168,2,0,1,
28552485,469,18,1,2485,
2856470,20,471,4,30,
285778,0,79,0,95,
28580,83,0,69,0,
285978,0,83,0,79,
28600,82,0,95,0,
286169,0,86,0,69,
28620,78,0,84,0,
28631,77,1,1,2,
28640,1,2488,472,18,
28651,2488,473,20,474,
28664,22,77,0,79, 32634,22,77,0,79,
28670,78,0,69,0, 32640,78,0,69,0,
286889,0,95,0,69, 326589,0,95,0,69,
28690,86,0,69,0, 32660,86,0,69,0,
287078,0,84,0,1, 326778,0,84,0,1,
287174,1,1,2,0, 326874,1,1,2,0,
28721,2489,475,18,1, 32691,2500,451,18,1,
28732489,476,20,477,4, 32702500,452,20,453,4,
287424,76,0,73,0, 327124,76,0,73,0,
287583,0,84,0,69, 327283,0,84,0,69,
28760,78,0,95,0, 32730,78,0,95,0,
287769,0,86,0,69, 327469,0,86,0,69,
28780,78,0,84,0, 32750,78,0,84,0,
28791,73,1,1,2, 32761,73,1,1,2,
28800,1,2490,478,18, 32770,1,2501,454,18,
28811,2490,479,20,480, 32781,2501,455,20,456,
28824,36,76,0,73, 32794,36,76,0,73,
28830,78,0,75,0, 32800,78,0,75,0,
288495,0,77,0,69, 328195,0,77,0,69,
@@ -2888,480 +3285,889 @@ public yyLSLSyntax
288886,0,69,0,78, 328586,0,69,0,78,
28890,84,0,1,72, 32860,84,0,1,72,
28901,1,2,0,1, 32871,1,2,0,1,
28912491,481,18,1,2491, 32882502,457,18,1,2502,
2892482,20,483,4,52, 3289458,20,459,4,38,
289376,0,65,0,78, 329072,0,84,0,84,
28940,68,0,95,0, 32910,80,0,95,0,
329282,0,69,0,83,
32930,80,0,79,0,
329478,0,83,0,69,
32950,95,0,69,0,
329686,0,69,0,78,
32970,84,0,1,68,
32981,1,2,0,1,
32992503,460,18,1,2503,
3300461,20,462,4,22,
330169,0,77,0,65,
33020,73,0,76,0,
330395,0,69,0,86,
33040,69,0,78,0,
330584,0,1,67,1,
33061,2,0,1,2504,
3307463,18,1,2504,464,
330820,465,4,32,68,
33090,65,0,84,0,
331065,0,83,0,69,
33110,82,0,86,0,
331269,0,82,0,95,
33130,69,0,86,0,
331469,0,78,0,84,
33150,1,66,1,1,
33162,0,1,277,466,
331718,1,277,467,20,
3318468,4,10,83,0,
331976,0,65,0,83,
33200,72,0,1,21,
33211,1,2,0,1,
33222506,469,18,1,2506,
3323135,2,0,1,2507,
3324470,18,1,2507,117,
33252,0,1,2508,471,
332618,1,2508,132,2,
33270,1,2509,472,18,
33281,2509,473,20,474,
33294,28,75,0,101,
33300,121,0,68,0,
3331101,0,99,0,108,
33320,97,0,114,0,
333397,0,116,0,105,
33340,111,0,110,0,
33351,119,1,2,2,
33360,1,2510,475,18,
33371,2510,143,2,0,
33381,283,476,18,1,
3339283,187,2,0,1,
33402512,477,18,1,2512,
3341132,2,0,1,2513,
3342478,18,1,2513,479,
334320,480,4,28,73,
33440,110,0,116,0,
334568,0,101,0,99,
33460,108,0,97,0,
3347114,0,97,0,116,
33480,105,0,111,0,
3349110,0,1,120,1,
33502,2,0,1,2514,
3351481,18,1,2514,143,
33522,0,1,1958,482,
335318,1,1958,162,2,
33540,1,2516,483,18,
33551,2516,479,2,0,
33561,2517,484,18,1,
33572517,485,20,486,4,
335864,75,0,101,0,
3359121,0,73,0,110,
33600,116,0,73,0,
3361110,0,116,0,65,
33620,114,0,103,0,
3363117,0,109,0,101,
33640,110,0,116,0,
336568,0,101,0,99,
33660,108,0,97,0,
3367114,0,97,0,116,
33680,105,0,111,0,
3369110,0,76,0,105,
33700,115,0,116,0,
33711,117,1,2,2,
33720,1,2518,487,18,
33731,2518,162,2,0,
33741,1406,488,18,1,
33751406,179,2,0,1,
33761407,489,18,1,1407,
3377232,2,0,1,2522,
3378490,18,1,2522,135,
33792,0,1,2524,491,
338018,1,2524,479,2,
33810,1,2525,492,18,
33821,2525,143,2,0,
33831,2526,493,18,1,
33842526,114,2,0,1,
3385299,494,18,1,299,
3386495,20,496,4,8,
338783,0,84,0,65,
33880,82,0,1,20,
33891,1,2,0,1,
33901370,497,18,1,1370,
3391179,2,0,1,2529,
3392498,18,1,2529,143,
33932,0,1,2531,499,
339418,1,2531,308,2,
33950,1,2532,500,18,
33961,2532,501,20,502,
33974,64,73,0,110,
33980,116,0,86,0,
3399101,0,99,0,86,
34000,101,0,99,0,
340165,0,114,0,103,
34020,117,0,109,0,
3403101,0,110,0,116,
34040,68,0,101,0,
340599,0,108,0,97,
34060,114,0,97,0,
3407116,0,105,0,111,
34080,110,0,76,0,
3409105,0,115,0,116,
34100,1,116,1,2,
34112,0,1,305,503,
341218,1,305,187,2,
34130,1,2535,504,18,
34141,2535,327,2,0,
34151,2458,505,18,1,
34162458,285,2,0,1,
34172459,506,18,1,2459,
3418507,20,508,4,22,
341982,0,73,0,71,
34200,72,0,84,0,
342195,0,66,0,82,
34220,65,0,67,0,
342369,0,1,13,1,
34241,2,0,1,2539,
3425509,18,1,2539,479,
34262,0,1,2540,510,
342718,1,2540,143,2,
34280,1,2541,511,18,
34291,2541,111,2,0,
34301,2542,512,18,1,
34312542,132,2,0,1,
34322464,513,18,1,2464,
3433507,2,0,1,2544,
3434514,18,1,2544,143,
34352,0,1,1989,515,
343618,1,1989,285,2,
34370,1,1990,516,18,
34381,1990,517,20,518,
34394,8,69,0,76,
34400,83,0,69,0,
34411,43,1,1,2,
34420,1,2548,519,18,
34431,2548,162,2,0,
34441,2470,520,18,1,
34452470,165,2,0,1,
3446322,521,18,1,322,
3447253,2,0,1,2551,
3448522,18,1,2551,523,
344920,524,4,28,86,
34500,101,0,99,0,
3451116,0,111,0,114,
34520,65,0,114,0,
3453103,0,69,0,118,
34540,101,0,110,0,
3455116,0,1,128,1,
34562,2,0,1,1933,
3457525,18,1,1933,135,
34582,0,1,883,526,
345918,1,883,187,2,
34600,1,2555,527,18,
34611,2555,528,20,529,
34624,58,86,0,101,
34630,99,0,116,0,
3464111,0,114,0,65,
34650,114,0,103,0,
3466117,0,109,0,101,
34670,110,0,116,0,
346868,0,101,0,99,
34690,108,0,97,0,
3470114,0,97,0,116,
34710,105,0,111,0,
3472110,0,76,0,105,
34730,115,0,116,0,
34741,114,1,2,2,
34750,1,328,530,18,
34761,328,187,2,0,
34771,1443,531,18,1,
34781443,269,2,0,1,
34792558,532,18,1,2558,
3480327,2,0,1,2559,
3481533,18,1,2559,534,
348220,535,4,22,73,
34830,110,0,116,0,
348465,0,114,0,103,
34850,69,0,118,0,
3486101,0,110,0,116,
34870,1,127,1,2,
34882,0,1,2560,536,
348918,1,2560,135,2,
34900,1,2562,537,18,
34911,2562,479,2,0,
34921,1449,538,18,1,
34931449,187,2,0,1,
34942485,539,18,1,2485,
3495540,20,541,4,30,
289567,0,79,0,76, 349667,0,79,0,76,
28960,76,0,73,0, 34970,76,0,73,0,
289783,0,73,0,79, 349883,0,73,0,79,
28980,78,0,95,0, 34990,78,0,95,0,
289983,0,84,0,65, 350069,0,86,0,69,
29000,82,0,84,0, 35010,78,0,84,0,
35021,62,1,1,2,
35030,1,2566,542,18,
35041,2566,327,2,0,
35051,2488,543,18,1,
35062488,544,20,545,4,
350724,65,0,84,0,
350884,0,65,0,67,
35090,72,0,95,0,
351069,0,86,0,69,
35110,78,0,84,0,
35121,60,1,1,2,
35130,1,2489,546,18,
35141,2489,547,20,548,
35154,22,84,0,73,
35160,77,0,69,0,
351782,0,95,0,69,
35180,86,0,69,0,
351978,0,84,0,1,
352087,1,1,2,0,
35211,2490,549,18,1,
35222490,550,20,551,4,
352338,78,0,79,0,
352484,0,95,0,65,
35250,84,0,95,0,
352684,0,65,0,82,
35270,71,0,69,0,
352884,0,95,0,69,
35290,86,0,69,0,
353078,0,84,0,1,
353179,1,1,2,0,
35321,2491,552,18,1,
35332491,553,20,554,4,
353446,78,0,79,0,
353584,0,95,0,65,
35360,84,0,95,0,
353782,0,79,0,84,
35380,95,0,84,0,
353965,0,82,0,71,
35400,69,0,84,0,
290195,0,69,0,86, 354195,0,69,0,86,
29020,69,0,78,0, 35420,69,0,78,0,
290384,0,1,71,1, 354384,0,1,78,1,
29041,2,0,1,2493, 35441,2,0,1,2571,
2905484,18,1,2493,485, 3545555,18,1,2571,556,
290620,486,4,40,76, 354620,557,4,52,75,
29070,65,0,78,0, 35470,101,0,121,0,
290868,0,95,0,67, 354865,0,114,0,103,
29090,79,0,76,0, 35490,117,0,109,0,
291076,0,73,0,83, 3550101,0,110,0,116,
29110,73,0,79,0, 35510,68,0,101,0,
291278,0,95,0,69, 355299,0,108,0,97,
35530,114,0,97,0,
3554116,0,105,0,111,
35550,110,0,76,0,
3556105,0,115,0,116,
35570,1,112,1,2,
35582,0,1,2493,558,
355918,1,2493,559,20,
3560560,4,36,77,0,
356179,0,86,0,73,
35620,78,0,71,0,
356395,0,83,0,84,
35640,65,0,82,0,
356584,0,95,0,69,
29130,86,0,69,0, 35660,86,0,69,0,
291478,0,84,0,1, 356778,0,84,0,1,
291569,1,1,2,0, 356876,1,1,2,0,
29161,1413,487,18,1, 35691,1413,561,18,1,
29171413,168,2,0,1, 35701413,187,2,0,1,
2918346,488,18,1,346, 3571346,562,18,1,346,
2919489,20,490,4,8, 3572563,20,564,4,8,
292080,0,76,0,85, 357380,0,76,0,85,
29210,83,0,1,18, 35740,83,0,1,18,
29221,1,2,0,1, 35751,1,2,0,1,
29232496,491,18,1,2496, 35762575,565,18,1,2575,
2924492,20,493,4,32, 3577566,20,567,4,24,
292568,0,65,0,84, 357886,0,111,0,105,
29260,65,0,83,0, 35790,100,0,65,0,
292769,0,82,0,86, 3580114,0,103,0,69,
29280,69,0,82,0, 35810,118,0,101,0,
292995,0,69,0,86, 3582110,0,116,0,1,
29300,69,0,78,0, 3583125,1,2,2,0,
293184,0,1,66,1, 35841,2496,568,18,1,
29321,2,0,1,2021, 35852496,569,20,570,4,
2933494,18,1,2021,260, 358634,83,0,84,0,
29342,0,1,2022,495, 358765,0,84,0,69,
293518,1,2022,338,2, 35880,95,0,69,0,
29360,1,352,496,18, 358978,0,84,0,82,
29371,352,168,2,0, 35900,89,0,95,0,
29381,2024,497,18,1, 359169,0,86,0,69,
29392024,132,2,0,1, 35920,78,0,84,0,
29402025,498,18,1,2025, 35931,85,1,1,2,
2941499,20,500,4,8, 35940,1,2577,571,18,
294274,0,85,0,77, 35951,2577,162,2,0,
29430,80,0,1,49, 35961,2021,572,18,1,
29441,1,2,0,1, 35972021,285,2,0,1,
29452026,501,18,1,2026, 35982022,573,18,1,2022,
2946132,2,0,1,2027, 3599374,2,0,1,352,
2947502,18,1,2027,503, 3600574,18,1,352,187,
294820,504,4,4,65, 36012,0,1,2024,575,
29490,84,0,1,23, 360218,1,2024,132,2,
29501,1,2,0,1, 36030,1,2025,576,18,
29512028,505,18,1,2028, 36041,2025,577,20,578,
2952132,2,0,1,2029, 36054,8,74,0,85,
2953506,18,1,2029,334, 36060,77,0,80,0,
29542,0,1,2030,507, 36071,49,1,1,2,
295518,1,2030,508,20, 36080,1,2026,579,18,
2956509,4,14,70,0, 36091,2026,132,2,0,
2957111,0,114,0,76, 36101,2027,580,18,1,
29580,111,0,111,0, 36112027,581,20,582,4,
2959112,0,1,121,1, 36124,65,0,84,0,
29602,2,0,1,2031, 36131,23,1,1,2,
2961510,18,1,2031,511, 36140,1,2028,583,18,
296220,512,4,32,68, 36151,2028,132,2,0,
29630,111,0,87,0, 36161,2029,584,18,1,
2964104,0,105,0,108, 36172029,327,2,0,1,
29650,101,0,83,0, 36182030,585,18,1,2030,
2966116,0,97,0,116, 3619586,20,587,4,14,
29670,101,0,109,0, 362070,0,111,0,114,
2968101,0,110,0,116, 36210,76,0,111,0,
29690,1,120,1,2, 3622111,0,112,0,1,
29702,0,1,2032,513, 3623145,1,2,2,0,
297118,1,2032,514,20, 36241,2031,588,18,1,
2972515,4,28,87,0, 36252031,589,20,590,4,
2973104,0,105,0,108, 362632,68,0,111,0,
29740,101,0,83,0, 362787,0,104,0,105,
2975116,0,97,0,116, 36280,108,0,101,0,
29760,101,0,109,0, 362983,0,116,0,97,
2977101,0,110,0,116, 36300,116,0,101,0,
29780,1,119,1,2, 3631109,0,101,0,110,
29792,0,1,2033,516, 36320,116,0,1,144,
298018,1,2033,517,20, 36331,2,2,0,1,
2981518,4,22,73,0, 36342032,591,18,1,2032,
2982102,0,83,0,116, 3635592,20,593,4,28,
29830,97,0,116,0, 363687,0,104,0,105,
2984101,0,109,0,101, 36370,108,0,101,0,
29850,110,0,116,0, 363883,0,116,0,97,
29861,118,1,2,2, 36390,116,0,101,0,
29870,1,2034,519,18, 3640109,0,101,0,110,
29881,2034,520,20,521, 36410,116,0,1,143,
29894,22,83,0,116, 36421,2,2,0,1,
29900,97,0,116,0, 36432033,594,18,1,2033,
2991101,0,67,0,104, 3644595,20,596,4,22,
29920,97,0,110,0, 364573,0,102,0,83,
2993103,0,101,0,1,
2994117,1,2,2,0,
29951,1478,522,18,1,
29961478,160,2,0,1,
29971479,523,18,1,1479,
2998276,2,0,1,2037,
2999524,18,1,2037,191,
30002,0,1,2038,525,
300118,1,2038,526,20,
3002527,4,18,74,0,
3003117,0,109,0,112,
30040,76,0,97,0,
300598,0,101,0,108,
30060,1,115,1,2,
30072,0,1,2039,528,
300818,1,2039,191,2,
30090,1,2040,529,18,
30101,2040,530,20,531,
30114,30,82,0,101,
30120,116,0,117,0,
3013114,0,110,0,83,
30140,116,0,97,0, 36460,116,0,97,0,
3015116,0,101,0,109, 3647116,0,101,0,109,
30160,101,0,110,0, 36480,101,0,110,0,
3017116,0,1,114,1, 3649116,0,1,142,1,
30182,2,0,1,2041, 36502,2,0,1,2034,
3019532,18,1,2041,191, 3651597,18,1,2034,598,
30202,0,1,1485,533, 365220,599,4,22,83,
302118,1,1485,168,2, 36530,116,0,97,0,
30220,1,372,534,18, 3654116,0,101,0,67,
30231,372,180,2,0, 36550,104,0,97,0,
30241,373,535,18,1, 3656110,0,103,0,101,
3025373,132,2,0,1, 36570,1,141,1,2,
3026374,536,18,1,374, 36582,0,1,1478,600,
3027176,2,0,1,375, 365918,1,1478,179,2,
3028537,18,1,375,132, 36600,1,1479,601,18,
30292,0,1,376,538, 36611,1479,305,2,0,
303018,1,376,183,2, 36621,2037,602,18,1,
30310,1,377,539,18, 36632037,146,2,0,1,
30321,377,132,2,0, 36642038,603,18,1,2038,
30331,378,540,18,1, 3665604,20,605,4,18,
3034378,176,2,0,1, 366674,0,117,0,109,
3035379,541,18,1,379, 36670,112,0,76,0,
3036132,2,0,1,380, 366897,0,98,0,101,
3037542,18,1,380,543, 36690,108,0,1,139,
303820,544,4,16,67, 36701,2,2,0,1,
30390,111,0,110,0, 36712039,606,18,1,2039,
3040115,0,116,0,97, 3672146,2,0,1,2040,
3673607,18,1,2040,608,
367420,609,4,30,82,
36750,101,0,116,0,
3676117,0,114,0,110,
36770,83,0,116,0,
367897,0,116,0,101,
36790,109,0,101,0,
3680110,0,116,0,1,
3681138,1,2,2,0,
36821,2041,610,18,1,
36832041,146,2,0,1,
36841485,611,18,1,1485,
3685187,2,0,1,372,
3686612,18,1,372,199,
36872,0,1,373,613,
368818,1,373,132,2,
36890,1,374,614,18,
36901,374,195,2,0,
36911,375,615,18,1,
3692375,132,2,0,1,
3693376,616,18,1,376,
3694202,2,0,1,377,
3695617,18,1,377,132,
36962,0,1,378,618,
369718,1,378,195,2,
36980,1,379,619,18,
36991,379,132,2,0,
37001,380,620,18,1,
3701380,621,20,622,4,
370216,67,0,111,0,
3703110,0,115,0,116,
37040,97,0,110,0,
3705116,0,1,151,1,
37062,2,0,1,381,
3707623,18,1,381,323,
37082,0,1,371,624,
370918,1,371,625,20,
3710626,4,24,70,0,
3711117,0,110,0,99,
37120,116,0,105,0,
3713111,0,110,0,67,
37140,97,0,108,0,
3715108,0,1,147,1,
37162,2,0,1,942,
3717627,18,1,942,187,
37182,0,1,2533,628,
371918,1,2533,162,2,
37200,1,387,629,18,
37211,387,187,2,0,
37221,2536,630,18,1,
37232536,631,20,632,4,
372434,73,0,110,0,
3725116,0,82,0,111,
37260,116,0,82,0,
3727111,0,116,0,65,
37280,114,0,103,0,
372969,0,118,0,101,
30410,110,0,116,0, 37300,110,0,116,0,
30421,127,1,2,2, 37311,129,1,2,2,
30430,1,381,545,18, 37320,1,2537,633,18,
30441,381,290,2,0, 37331,2537,135,2,0,
30451,371,546,18,1, 37341,2543,634,18,1,
3046371,547,20,548,4, 37352543,635,20,636,4,
304724,70,0,117,0, 373628,82,0,111,0,
3048110,0,99,0,116, 3737116,0,68,0,101,
30490,105,0,111,0, 37380,99,0,108,0,
3050110,0,67,0,97, 373997,0,114,0,97,
30510,108,0,108,0, 37400,116,0,105,0,
30521,123,1,2,2, 3741111,0,110,0,1,
30530,1,942,549,18, 3742122,1,2,2,0,
30541,942,168,2,0, 37431,2546,637,18,1,
30551,387,550,18,1, 37442546,635,2,0,1,
3056387,168,2,0,1, 37451514,638,18,1,1514,
30571514,551,18,1,1514, 3746179,2,0,1,1515,
3058160,2,0,1,1515, 3747639,18,1,1515,333,
3059552,18,1,1515,256, 37482,0,1,2074,640,
30602,0,1,2074,553, 374918,1,2074,179,2,
306118,1,2074,160,2, 37500,1,2075,641,18,
30620,1,2075,554,18, 37511,2075,162,2,0,
30631,2075,153,2,0, 37521,2552,642,18,1,
30641,406,555,18,1, 37532552,135,2,0,1,
3065406,143,2,0,1, 3754406,643,18,1,406,
30661521,556,18,1,1521, 3755143,2,0,1,1521,
3067168,2,0,1,2636, 3756644,18,1,1521,187,
3068557,18,1,2636,295, 37572,0,1,2556,645,
30692,0,1,2557,558, 375818,1,2556,162,2,
307018,1,2557,462,2, 37590,1,2639,646,18,
30710,1,2639,559,18, 37601,2639,647,20,648,
30721,2639,560,20,561, 37614,44,75,0,101,
30734,10,83,0,116, 37620,121,0,73,0,
30740,97,0,116,0, 3763110,0,116,0,73,
3075101,0,1,101,1,
30762,2,0,1,412,
3077562,18,1,412,168,
30782,0,1,2641,563,
307918,1,2641,132,2,
30800,1,2484,564,18,
30811,2484,565,20,566,
30824,46,78,0,79,
30830,84,0,95,0,
308465,0,84,0,95,
30850,82,0,79,0,
308684,0,95,0,84,
30870,65,0,82,0,
308871,0,69,0,84,
30890,95,0,69,0,
309086,0,69,0,78,
30910,84,0,1,78,
30921,1,2,0,1,
30932023,567,18,1,2023,
3094465,2,0,1,1442,
3095568,18,1,1442,160,
30962,0,1,2651,569,
309718,1,2651,140,2,
30980,1,2653,570,18,
30991,2653,153,2,0,
31001,2655,571,18,1,
31012655,334,2,0,1,
31022035,572,18,1,2035,
3103191,2,0,1,2036,
3104573,18,1,2036,574,
310520,575,4,26,74,
31060,117,0,109,0,
3107112,0,83,0,116,
31080,97,0,116,0,
3109101,0,109,0,101,
31100,110,0,116,0, 37640,110,0,116,0,
31111,116,1,2,2, 376565,0,114,0,103,
31120,1,431,576,18, 37660,83,0,116,0,
31131,431,143,2,0, 376797,0,116,0,101,
31141,2105,577,18,1, 37680,69,0,118,0,
31152105,260,2,0,1, 3769101,0,110,0,116,
31162106,578,18,1,2106, 37700,1,110,1,2,
3117452,2,0,1,1550, 37712,0,1,412,649,
3118579,18,1,1550,160, 377218,1,412,187,2,
31192,0,1,437,580, 37730,1,2641,650,18,
312018,1,437,168,2, 37741,2641,168,2,0,
31210,1,2044,581,18, 37751,2484,651,18,1,
31221,2044,582,20,583, 37762484,652,20,653,4,
31234,28,69,0,109, 377738,67,0,79,0,
31240,112,0,116,0, 377876,0,76,0,73,
3125121,0,83,0,116, 37790,83,0,73,0,
378079,0,78,0,95,
37810,69,0,78,0,
378268,0,95,0,69,
37830,86,0,69,0,
378478,0,84,0,1,
378563,1,1,2,0,
37861,2643,654,18,1,
37872643,174,2,0,1,
37882644,655,18,1,2644,
3789656,20,657,4,32,
379075,0,101,0,121,
37910,65,0,114,0,
3792103,0,83,0,116,
31260,97,0,116,0, 37930,97,0,116,0,
3127101,0,109,0,101, 3794101,0,69,0,118,
37950,101,0,110,0,
3796116,0,1,105,1,
37972,2,0,1,2023,
3798658,18,1,2023,659,
379920,660,4,26,68,
38000,69,0,70,0,
380165,0,85,0,76,
38020,84,0,95,0,
380383,0,84,0,65,
38040,84,0,69,0,
38051,47,1,1,2,
38060,1,2564,661,18,
38071,2564,162,2,0,
38081,2647,662,18,1,
38092647,507,2,0,1,
38102648,663,18,1,2648,
3811647,2,0,1,2567,
3812664,18,1,2567,665,
381320,666,4,22,75,
38140,101,0,121,0,
381565,0,114,0,103,
38160,69,0,118,0,
3817101,0,110,0,116,
38180,1,126,1,2,
38192,0,1,1442,667,
382018,1,1442,179,2,
38210,1,2651,668,18,
38221,2651,669,20,670,
38234,38,86,0,101,
38240,99,0,116,0,
3825111,0,114,0,65,
38260,114,0,103,0,
382783,0,116,0,97,
38280,116,0,101,0,
382969,0,118,0,101,
31280,110,0,116,0, 38300,110,0,116,0,
31291,111,1,2,2, 38311,107,1,2,2,
31300,1,2045,584,18, 38320,1,2570,671,18,
31311,2045,191,2,0, 38331,2570,473,2,0,
31321,1555,585,18,1, 38341,2653,672,18,1,
31331555,168,2,0,1, 38352653,656,2,0,1,
31341001,586,18,1,1001, 38362572,673,18,1,2572,
3135547,2,0,1,1002, 3837162,2,0,1,2655,
3136587,18,1,1002,543, 3838674,18,1,2655,156,
31372,0,1,447,588, 38392,0,1,2574,675,
313818,1,447,307,2, 384018,1,2574,327,2,
31390,1,2597,589,18, 38410,1,2035,676,18,
31401,2597,590,20,591, 38421,2035,146,2,0,
31414,18,83,0,116, 38431,2036,677,18,1,
31420,97,0,116,0, 38442036,678,20,679,4,
3143101,0,66,0,111, 384526,74,0,117,0,
31440,100,0,121,0, 3846109,0,112,0,83,
31451,102,1,2,2, 38470,116,0,97,0,
31460,1,1010,592,18, 3848116,0,101,0,109,
31471,1010,160,2,0, 38490,101,0,110,0,
31481,1011,593,18,1, 3850116,0,1,140,1,
31491011,153,2,0,1, 38512,2,0,1,431,
31501012,594,18,1,1012, 3852680,18,1,431,143,
3151168,2,0,1,1013, 38532,0,1,2579,681,
3152595,18,1,1013,153, 385418,1,2579,327,2,
31532,0,1,459,596, 38550,1,2105,682,18,
315418,1,459,597,20, 38561,2105,285,2,0,
3155598,4,24,76,0, 38571,2106,683,18,1,
315669,0,70,0,84, 38582106,517,2,0,1,
31570,95,0,66,0, 38591550,684,18,1,1550,
315882,0,65,0,67, 3860179,2,0,1,437,
31590,75,0,69,0, 3861685,18,1,437,187,
316084,0,1,27,1, 38622,0,1,2044,686,
31611,2,0,1,1574, 386318,1,2044,687,20,
3162599,18,1,1574,191, 3864688,4,28,69,0,
31632,0,1,461,600, 3865109,0,112,0,116,
316418,1,461,601,20, 38660,121,0,83,0,
3165602,4,24,65,0, 3867116,0,97,0,116,
3166114,0,103,0,117, 38680,101,0,109,0,
31670,109,0,101,0, 3869101,0,110,0,116,
3168110,0,116,0,76, 38700,1,135,1,2,
31690,105,0,115,0, 38712,0,1,2045,689,
3170116,0,1,124,1, 387218,1,2045,146,2,
31712,2,0,1,462, 38730,1,1555,690,18,
3172603,18,1,462,143, 38741,1555,187,2,0,
31732,0,1,464,604, 38751,2511,691,18,1,
317418,1,464,605,20, 38762511,126,2,0,1,
3175606,4,16,65,0, 38771001,692,18,1,1001,
3176114,0,103,0,117, 3878625,2,0,1,1002,
31770,109,0,101,0, 3879693,18,1,1002,621,
3178110,0,116,0,1, 38802,0,1,447,694,
3179125,1,2,2,0, 388118,1,447,342,2,
31801,2136,607,18,1, 38820,1,2594,695,18,
31812136,260,2,0,1, 38831,2594,327,2,0,
31822694,608,18,1,2694, 38841,2596,696,18,1,
3183191,2,0,1,2695, 38852596,697,20,698,4,
3184609,18,1,2695,610, 388618,83,0,116,0,
318520,611,4,34,71, 388797,0,116,0,101,
31860,108,0,111,0, 38880,66,0,111,0,
318798,0,97,0,108, 3889100,0,121,0,1,
31880,68,0,101,0, 3890102,1,2,2,0,
3189102,0,105,0,110, 38911,2520,699,18,1,
31900,105,0,116,0, 38922520,327,2,0,1,
3191105,0,111,0,110, 38931010,700,18,1,1010,
31920,115,0,1,97, 3894179,2,0,1,1011,
31931,2,2,0,1, 3895701,18,1,1011,162,
31941585,612,18,1,1585, 38962,0,1,1012,702,
3195613,20,614,4,12, 389718,1,1012,187,2,
319682,0,69,0,84, 38980,1,1013,703,18,
31970,85,0,82,0, 38991,1013,162,2,0,
319878,0,1,50,1, 39001,459,704,18,1,
31991,2,0,1,476, 3901459,705,20,706,4,
3200615,18,1,476,616, 390224,76,0,69,0,
320120,617,4,30,83, 390370,0,84,0,95,
32020,84,0,82,0, 39040,66,0,82,0,
320373,0,78,0,71, 390565,0,67,0,75,
32040,95,0,67,0, 39060,69,0,84,0,
320579,0,78,0,83, 39071,27,1,1,2,
32060,84,0,65,0, 39080,1,1574,707,18,
320778,0,84,0,1, 39091,1574,146,2,0,
32083,1,1,2,0, 39101,461,708,18,1,
32091,477,618,18,1, 3911461,709,20,710,4,
3210477,619,20,620,4, 391224,65,0,114,0,
321128,70,0,76,0, 3913103,0,117,0,109,
321279,0,65,0,84, 39140,101,0,110,0,
32130,95,0,67,0, 3915116,0,76,0,105,
321479,0,78,0,83, 39160,115,0,116,0,
32150,84,0,65,0, 39171,148,1,2,2,
321678,0,84,0,1, 39180,1,462,711,18,
321795,1,1,2,0, 39191,462,143,2,0,
32181,478,621,18,1, 39201,464,712,18,1,
3219478,622,20,623,4, 3921464,713,20,714,4,
322040,72,0,69,0, 392216,65,0,114,0,
322188,0,95,0,73, 3923103,0,117,0,109,
32220,78,0,84,0, 39240,101,0,110,0,
322369,0,71,0,69, 3925116,0,1,149,1,
32240,82,0,95,0, 39262,2,0,1,2136,
3927715,18,1,2136,285,
39282,0,1,1585,716,
392918,1,1585,717,20,
3930718,4,12,82,0,
393169,0,84,0,85,
39320,82,0,78,0,
39331,50,1,1,2,
39340,1,2700,719,18,
39351,2700,697,2,0,
39361,476,720,18,1,
3937476,721,20,722,4,
393830,83,0,84,0,
393982,0,73,0,78,
39400,71,0,95,0,
322567,0,79,0,78, 394167,0,79,0,78,
32260,83,0,84,0, 39420,83,0,84,0,
322765,0,78,0,84, 394365,0,78,0,84,
32280,1,94,1,1, 39440,1,3,1,1,
32292,0,1,479,624, 39452,0,1,477,723,
323018,1,479,625,20, 394618,1,477,724,20,
3231626,4,32,73,0, 3947725,4,28,70,0,
323278,0,84,0,69, 394876,0,79,0,65,
32330,71,0,69,0, 39490,84,0,95,0,
323482,0,95,0,67, 395067,0,79,0,78,
32350,79,0,78,0, 39510,83,0,84,0,
323683,0,84,0,65, 395265,0,78,0,84,
32370,78,0,84,0, 39530,1,95,1,1,
32381,93,1,1,2, 39542,0,1,478,726,
32390,1,480,627,18, 395518,1,478,727,20,
32401,480,628,20,629, 3956728,4,40,72,0,
32414,26,82,0,73, 395769,0,88,0,95,
32420,71,0,72,0, 39580,73,0,78,0,
324384,0,95,0,66, 395984,0,69,0,71,
32440,82,0,65,0, 39600,69,0,82,0,
324567,0,75,0,69, 396195,0,67,0,79,
32460,84,0,1,28, 39620,78,0,83,0,
396384,0,65,0,78,
39640,84,0,1,94,
32471,1,2,0,1, 39651,1,2,0,1,
3248481,630,18,1,481, 3966479,729,18,1,479,
3249605,2,0,1,2713, 3967730,20,731,4,32,
3250631,18,1,2713,632, 396873,0,78,0,84,
325120,633,4,48,71, 39690,69,0,71,0,
32520,108,0,111,0, 397069,0,82,0,95,
325398,0,97,0,108, 39710,67,0,79,0,
32540,70,0,117,0, 397278,0,83,0,84,
3255110,0,99,0,116, 39730,65,0,78,0,
32560,105,0,111,0, 397484,0,1,93,1,
3257110,0,68,0,101, 39751,2,0,1,480,
32580,102,0,105,0, 3976732,18,1,480,733,
3259110,0,105,0,116, 397720,734,4,26,82,
39780,73,0,71,0,
397972,0,84,0,95,
39800,66,0,82,0,
398165,0,67,0,75,
39820,69,0,84,0,
39831,28,1,1,2,
39840,1,481,735,18,
39851,481,713,2,0,
39861,2550,736,18,1,
39872550,327,2,0,1,
39882554,737,18,1,2554,
3989308,2,0,1,1048,
3990738,18,1,1048,187,
39912,0,1,2640,739,
399218,1,2640,740,20,
3993741,4,44,73,0,
3994110,0,116,0,86,
39950,101,0,99,0,
399686,0,101,0,99,
39970,65,0,114,0,
3998103,0,83,0,116,
39990,97,0,116,0,
4000101,0,69,0,118,
40010,101,0,110,0,
4002116,0,1,109,1,
40032,2,0,1,2642,
4004742,18,1,2642,669,
40052,0,1,2563,743,
400618,1,2563,744,20,
4007745,4,52,73,0,
4008110,0,116,0,65,
40090,114,0,103,0,
4010117,0,109,0,101,
40110,110,0,116,0,
401268,0,101,0,99,
40130,108,0,97,0,
4014114,0,97,0,116,
32600,105,0,111,0, 40150,105,0,111,0,
3261110,0,1,99,1, 4016110,0,76,0,105,
32622,2,0,1,2714, 40170,115,0,116,0,
3263634,18,1,2714,635, 40181,113,1,2,2,
326420,636,4,50,71, 40190,1,2042,746,18,
32650,108,0,111,0, 40201,2042,747,20,748,
326698,0,97,0,108, 40214,20,65,0,115,
32670,86,0,97,0, 40220,115,0,105,0,
3268114,0,105,0,97, 4023103,0,110,0,109,
32690,98,0,108,0,
3270101,0,68,0,101,
32710,99,0,108,0,
327297,0,114,0,97,
32730,116,0,105,0,
3274111,0,110,0,1,
327598,1,2,2,0,
32761,2715,637,18,1,
32772715,632,2,0,1,
32782716,638,18,1,2716,
3279635,2,0,1,2717,
3280104,1,2634,639,18,
32811,2634,447,2,0,
32821,1048,640,18,1,
32831048,168,2,0,1,
32842640,641,18,1,2640,
3285560,2,0,1,2642,
3286642,18,1,2642,135,
32872,0,1,2042,643,
328818,1,2042,644,20,
3289645,4,20,65,0,
3290115,0,115,0,105,
32910,103,0,110,0,
3292109,0,101,0,110,
32930,116,0,1,112,
32941,2,2,0,1,
32952043,646,18,1,2043,
3296191,2,0,1,1620,
3297647,18,1,1620,160,
32982,0,1,1621,648,
329918,1,1621,150,2,
33000,1,1622,649,18,
33011,1622,256,2,0,
33021,509,650,18,1,
3303509,143,2,0,1,
33042498,651,18,1,2498,
3305652,20,653,4,42,
330667,0,79,0,76,
33070,76,0,73,0,
330883,0,73,0,79,
33090,78,0,95,0,
331083,0,84,0,65,
33110,82,0,84,0,
331295,0,69,0,86,
33130,69,0,78,0,
331484,0,1,64,1,
33151,2,0,1,1628,
3316654,18,1,1628,168,
33172,0,1,515,655,
331818,1,515,168,2,
33190,1,2505,656,18,
33201,2505,657,20,658,
33214,10,69,0,118,
33220,101,0,110,0, 40240,101,0,110,0,
3323116,0,1,107,1, 4025116,0,1,136,1,
33242,2,0,1,2664, 40262,2,0,1,2043,
3325659,18,1,2664,168, 4027749,18,1,2043,146,
33262,0,1,525,660, 40282,0,1,2568,750,
332718,1,525,307,2, 402918,1,2568,135,2,
33280,1,2197,661,18, 40300,1,2649,751,18,
33291,2197,160,2,0, 40311,2649,740,2,0,
33301,2198,662,18,1, 40321,1620,752,18,1,
33312198,153,2,0,1, 40331620,179,2,0,1,
33321591,663,18,1,1591, 40341621,753,18,1,1621,
3333168,2,0,1,2521, 4035159,2,0,1,1622,
3334664,18,1,2521,590, 4036754,18,1,1622,333,
33352,0,1,1094,665, 40372,0,1,509,755,
333618,1,1094,601,2, 403818,1,509,143,2,
33370,1,1096,666,18, 40390,1,2498,756,18,
33381,1096,153,2,0, 40401,2498,757,20,758,
33391,2683,667,18,1, 40414,34,82,0,69,
33402683,191,2,0,1, 40420,77,0,79,0,
33411657,668,18,1,1657, 404384,0,69,0,95,
3342191,2,0,1,1658, 40440,68,0,65,0,
3343669,18,1,1658,670, 404584,0,65,0,95,
334420,671,4,6,70, 40460,69,0,86,0,
33450,79,0,82,0, 404769,0,78,0,84,
33461,46,1,1,2, 40480,1,82,1,1,
33470,1,1659,672,18, 40492,0,1,2576,759,
33481,1659,135,2,0, 405018,1,2576,135,2,
33491,1665,673,18,1, 40510,1,2656,760,18,
33501665,168,2,0,1, 40521,2656,659,2,0,
33511113,674,18,1,1113, 40531,1628,761,18,1,
3352176,2,0,675,5, 40541628,187,2,0,1,
33530,676,5,324,1, 4055515,762,18,1,515,
33542,677,19,237,1, 4056187,2,0,1,2580,
33552,678,5,6,1, 4057763,18,1,2580,764,
33562706,679,17,680,15, 405820,765,4,10,69,
3357681,4,30,37,0, 40590,118,0,101,0,
4060110,0,116,0,1,
4061124,1,2,2,0,
40621,2505,766,18,1,
40632505,767,20,768,4,
406434,75,0,101,0,
4065121,0,73,0,110,
40660,116,0,73,0,
4067110,0,116,0,65,
40680,114,0,103,0,
406969,0,118,0,101,
40700,110,0,116,0,
40711,131,1,2,2,
40720,1,2751,769,18,
40731,2751,507,2,0,
40741,525,770,18,1,
4075525,342,2,0,1,
40762197,771,18,1,2197,
4077179,2,0,1,2198,
4078772,18,1,2198,162,
40792,0,1,1591,773,
408018,1,1591,187,2,
40810,1,2592,774,18,
40821,2592,162,2,0,
40831,2760,775,18,1,
40842760,291,2,0,1,
40852521,776,18,1,2521,
4086777,20,778,4,34,
408773,0,110,0,116,
40880,86,0,101,0,
408999,0,86,0,101,
40900,99,0,65,0,
4091114,0,103,0,69,
40920,118,0,101,0,
4093110,0,116,0,1,
4094130,1,2,2,0,
40951,2763,779,18,1,
40962763,780,20,781,4,
409710,83,0,116,0,
409897,0,116,0,101,
40990,1,101,1,2,
41002,0,1,2764,782,
410118,1,2764,780,2,
41020,1,1094,783,18,
41031,1094,709,2,0,
41041,2766,784,18,1,
41052766,135,2,0,1,
41061096,785,18,1,1096,
4107162,2,0,1,1657,
4108786,18,1,1657,146,
41092,0,1,1658,787,
411018,1,1658,788,20,
4111789,4,6,70,0,
411279,0,82,0,1,
411346,1,1,2,0,
41141,1659,790,18,1,
41151659,135,2,0,1,
41162775,791,18,1,2775,
4117140,2,0,1,2777,
4118792,18,1,2777,162,
41192,0,1,1665,793,
412018,1,1665,187,2,
41210,1,2781,794,18,
41221,2781,159,2,0,
41231,2782,795,18,1,
41242782,333,2,0,1,
41251113,796,18,1,1113,
4126195,2,0,797,5,
41270,798,5,379,1,
41282,799,19,216,1,
41292,800,5,6,1,
41302764,801,17,802,15,
4131803,4,14,37,0,
413283,0,116,0,97,
41330,116,0,101,0,
4134115,0,1,-1,1,
41355,804,20,805,4,
413616,83,0,116,0,
413797,0,116,0,101,
41380,115,0,95,0,
413949,0,1,176,1,
41403,1,2,1,1,
4141806,22,1,11,1,
41422751,807,17,808,15,
4143809,4,12,37,0,
414483,0,116,0,97,
41450,116,0,101,0,
41461,-1,1,5,810,
414720,811,4,14,83,
41480,116,0,97,0,
4149116,0,101,0,95,
41500,49,0,1,178,
41511,3,1,5,1,
41524,812,22,1,13,
41531,2763,813,17,814,
415415,803,1,-1,1,
41555,815,20,816,4,
415616,83,0,116,0,
415797,0,116,0,101,
41580,115,0,95,0,
415950,0,1,177,1,
41603,1,3,1,2,
4161817,22,1,12,1,
41622830,818,17,819,15,
4163820,4,30,37,0,
335876,0,83,0,76, 416476,0,83,0,76,
33590,80,0,114,0, 41650,80,0,114,0,
3360111,0,103,0,114, 4166111,0,103,0,114,
33610,97,0,109,0, 41670,97,0,109,0,
336282,0,111,0,111, 416882,0,111,0,111,
33630,116,0,1,-1, 41690,116,0,1,-1,
33641,5,682,20,683, 41701,5,821,20,822,
33654,32,76,0,83, 41714,32,76,0,83,
33660,76,0,80,0, 41720,76,0,80,0,
3367114,0,111,0,103, 4173114,0,111,0,103,
@@ -3369,265 +4175,233 @@ public yyLSLSyntax
3369109,0,82,0,111, 4175109,0,82,0,111,
33700,111,0,116,0, 41760,111,0,116,0,
337195,0,49,0,1, 417795,0,49,0,1,
3372142,1,3,1,3, 4178166,1,3,1,3,
33731,2,684,22,1, 41791,2,823,22,1,
33741,1,2640,685,17, 41801,1,2647,824,17,
3375686,15,687,4,14, 4181825,15,809,1,-1,
337637,0,83,0,116, 41821,5,826,20,827,
33770,97,0,116,0, 41834,14,83,0,116,
3378101,0,115,0,1,
3379-1,1,5,688,20,
3380689,4,16,83,0,
3381116,0,97,0,116,
33820,101,0,115,0,
338395,0,49,0,1,
3384152,1,3,1,2,
33851,1,690,22,1,
338611,1,2634,691,17,
3387692,15,693,4,12,
338837,0,83,0,116,
33890,97,0,116,0, 41840,97,0,116,0,
3390101,0,1,-1,1, 4185101,0,95,0,50,
33915,694,20,695,4, 41860,1,179,1,3,
339214,83,0,116,0, 41871,6,1,5,828,
339397,0,116,0,101, 418822,1,14,1,2760,
33940,95,0,49,0, 4189829,17,830,15,820,
33951,154,1,3,1, 41901,-1,1,5,831,
33965,1,4,696,22, 419120,832,4,32,76,
33971,13,1,2558,697, 41920,83,0,76,0,
339817,698,15,693,1, 419380,0,114,0,111,
3399-1,1,5,699,20, 41940,103,0,114,0,
3400700,4,14,83,0, 419597,0,109,0,82,
3401116,0,97,0,116, 41960,111,0,111,0,
34020,101,0,95,0, 4197116,0,95,0,50,
340350,0,1,155,1, 41980,1,167,1,3,
34043,1,6,1,5, 41991,2,1,1,833,
3405701,22,1,14,1, 420022,1,2,1,3,
34062636,702,17,703,15, 4201834,19,722,1,3,
3407681,1,-1,1,5, 4202835,5,95,1,256,
3408704,20,705,4,32, 4203836,16,0,720,1,
340976,0,83,0,76, 42041261,837,16,0,720,
34100,80,0,114,0, 42051,509,838,16,0,
3411111,0,103,0,114, 4206720,1,1515,839,16,
34120,97,0,109,0, 42070,720,1,2021,840,
341382,0,111,0,111, 420817,841,15,842,4,
34140,116,0,95,0,
341550,0,1,143,1,
34163,1,2,1,1,
3417706,22,1,2,1,
34182639,707,17,708,15,
3419687,1,-1,1,5,
3420709,20,710,4,16,
342183,0,116,0,97,
34220,116,0,101,0,
3423115,0,95,0,50,
34240,1,153,1,3,
34251,3,1,2,711,
342622,1,12,1,3,
3427712,19,617,1,3,
3428713,5,95,1,256,
3429714,16,0,615,1,
34301261,715,16,0,615,
34311,509,716,16,0,
3432615,1,1515,717,16,
34330,615,1,2021,718,
343417,719,15,720,4,
343524,37,0,73,0, 420924,37,0,73,0,
3436102,0,83,0,116, 4210102,0,83,0,116,
34370,97,0,116,0, 42110,97,0,116,0,
3438101,0,109,0,101, 4212101,0,109,0,101,
34390,110,0,116,0, 42130,110,0,116,0,
34401,-1,1,5,721, 42141,-1,1,5,843,
344120,722,4,26,73, 421520,844,4,26,73,
34420,102,0,83,0, 42160,102,0,83,0,
3443116,0,97,0,116, 4217116,0,97,0,116,
34440,101,0,109,0, 42180,101,0,109,0,
3445101,0,110,0,116, 4219101,0,110,0,116,
34460,95,0,50,0, 42200,95,0,50,0,
34471,185,1,3,1, 42211,240,1,3,1,
34488,1,7,723,22, 42228,1,7,845,22,
34491,45,1,1775,724, 42231,76,1,1775,846,
345016,0,615,1,2029, 422416,0,720,1,2029,
3451725,17,726,15,727, 4225847,17,848,15,849,
34524,20,37,0,83, 42264,20,37,0,83,
34530,116,0,97,0, 42270,116,0,97,0,
3454116,0,101,0,109, 4228116,0,101,0,109,
34550,101,0,110,0, 42290,101,0,110,0,
3456116,0,1,-1,1, 4230116,0,1,-1,1,
34575,728,20,729,4, 42315,850,20,851,4,
345824,83,0,116,0, 423224,83,0,116,0,
345997,0,116,0,101, 423397,0,116,0,101,
34600,109,0,101,0, 42340,109,0,101,0,
3461110,0,116,0,95, 4235110,0,116,0,95,
34620,49,0,51,0, 42360,49,0,51,0,
34631,179,1,3,1, 42371,234,1,3,1,
34642,1,1,730,22, 42382,1,1,852,22,
34651,39,1,2030,731, 42391,70,1,2030,853,
346617,732,15,727,1, 424017,854,15,849,1,
3467-1,1,5,733,20, 4241-1,1,5,855,20,
3468734,4,24,83,0, 4242856,4,24,83,0,
3469116,0,97,0,116, 4243116,0,97,0,116,
34700,101,0,109,0, 42440,101,0,109,0,
3471101,0,110,0,116, 4245101,0,110,0,116,
34720,95,0,49,0, 42460,95,0,49,0,
347350,0,1,178,1, 424750,0,1,233,1,
34743,1,2,1,1, 42483,1,2,1,1,
3475735,22,1,38,1, 4249857,22,1,69,1,
34762031,736,17,737,15, 42502031,858,17,859,15,
3477727,1,-1,1,5, 4251849,1,-1,1,5,
3478738,20,739,4,24, 4252860,20,861,4,24,
347983,0,116,0,97, 425383,0,116,0,97,
34800,116,0,101,0, 42540,116,0,101,0,
3481109,0,101,0,110, 4255109,0,101,0,110,
34820,116,0,95,0, 42560,116,0,95,0,
348349,0,49,0,1, 425749,0,49,0,1,
3484177,1,3,1,2, 4258232,1,3,1,2,
34851,1,740,22,1, 42591,1,862,22,1,
348637,1,2032,741,17, 426068,1,2032,863,17,
3487742,15,727,1,-1, 4261864,15,849,1,-1,
34881,5,743,20,744, 42621,5,865,20,866,
34894,24,83,0,116, 42634,24,83,0,116,
34900,97,0,116,0, 42640,97,0,116,0,
3491101,0,109,0,101, 4265101,0,109,0,101,
34920,110,0,116,0, 42660,110,0,116,0,
349395,0,49,0,48, 426795,0,49,0,48,
34940,1,176,1,3, 42680,1,231,1,3,
34951,2,1,1,745, 42691,2,1,1,867,
349622,1,36,1,2033, 427022,1,67,1,2033,
3497746,17,747,15,727, 4271868,17,869,15,849,
34981,-1,1,5,748, 42721,-1,1,5,870,
349920,749,4,22,83, 427320,871,4,22,83,
35000,116,0,97,0, 42740,116,0,97,0,
3501116,0,101,0,109, 4275116,0,101,0,109,
35020,101,0,110,0, 42760,101,0,110,0,
3503116,0,95,0,57, 4277116,0,95,0,57,
35040,1,175,1,3, 42780,1,230,1,3,
35051,2,1,1,750, 42791,2,1,1,872,
350622,1,35,1,277, 428022,1,66,1,277,
3507751,16,0,615,1, 4281873,16,0,720,1,
35082035,752,17,753,15, 42822035,874,17,875,15,
3509727,1,-1,1,5, 4283849,1,-1,1,5,
3510754,20,755,4,22, 4284876,20,877,4,22,
351183,0,116,0,97, 428583,0,116,0,97,
35120,116,0,101,0, 42860,116,0,101,0,
3513109,0,101,0,110, 4287109,0,101,0,110,
35140,116,0,95,0, 42880,116,0,95,0,
351556,0,1,174,1, 428956,0,1,229,1,
35163,1,3,1,2, 42903,1,3,1,2,
3517756,22,1,34,1, 4291878,22,1,65,1,
35182037,757,17,758,15, 42922037,879,17,880,15,
3519727,1,-1,1,5, 4293849,1,-1,1,5,
3520759,20,760,4,22, 4294881,20,882,4,22,
352183,0,116,0,97, 429583,0,116,0,97,
35220,116,0,101,0, 42960,116,0,101,0,
3523109,0,101,0,110, 4297109,0,101,0,110,
35240,116,0,95,0, 42980,116,0,95,0,
352555,0,1,173,1, 429955,0,1,228,1,
35263,1,3,1,2, 43003,1,3,1,2,
3527761,22,1,33,1, 4301883,22,1,64,1,
35282039,762,17,763,15, 43022039,884,17,885,15,
3529727,1,-1,1,5, 4303849,1,-1,1,5,
3530764,20,765,4,22, 4304886,20,887,4,22,
353183,0,116,0,97, 430583,0,116,0,97,
35320,116,0,101,0, 43060,116,0,101,0,
3533109,0,101,0,110, 4307109,0,101,0,110,
35340,116,0,95,0, 43080,116,0,95,0,
353554,0,1,172,1, 430954,0,1,227,1,
35363,1,3,1,2, 43103,1,3,1,2,
3537766,22,1,32,1, 4311888,22,1,63,1,
353832,767,16,0,615, 431232,889,16,0,720,
35391,2041,768,17,769, 43131,2041,890,17,891,
354015,727,1,-1,1, 431415,849,1,-1,1,
35415,770,20,771,4, 43155,892,20,893,4,
354222,83,0,116,0, 431622,83,0,116,0,
354397,0,116,0,101, 431797,0,116,0,101,
35440,109,0,101,0, 43180,109,0,101,0,
3545110,0,116,0,95, 4319110,0,116,0,95,
35460,53,0,1,171, 43200,53,0,1,226,
35471,3,1,3,1, 43211,3,1,3,1,
35482,772,22,1,31, 43222,894,22,1,62,
35491,2293,773,16,0, 43231,2293,895,16,0,
3550615,1,2043,774,17, 4324720,1,2043,896,17,
3551775,15,727,1,-1, 4325897,15,849,1,-1,
35521,5,776,20,777, 43261,5,898,20,899,
35534,22,83,0,116, 43274,22,83,0,116,
35540,97,0,116,0, 43280,97,0,116,0,
3555101,0,109,0,101, 4329101,0,109,0,101,
35560,110,0,116,0, 43300,110,0,116,0,
355795,0,51,0,1, 433195,0,51,0,1,
3558169,1,3,1,3, 4332224,1,3,1,3,
35591,2,778,22,1, 43331,2,900,22,1,
356029,1,2045,779,17, 433460,1,2045,901,17,
3561780,15,727,1,-1, 4335902,15,849,1,-1,
35621,5,781,20,782, 43361,5,903,20,904,
35634,22,83,0,116, 43374,22,83,0,116,
35640,97,0,116,0, 43380,97,0,116,0,
3565101,0,109,0,101, 4339101,0,109,0,101,
35660,110,0,116,0, 43400,110,0,116,0,
356795,0,49,0,1, 434195,0,49,0,1,
3568167,1,3,1,3, 4342222,1,3,1,3,
35691,2,783,22,1, 43431,2,905,22,1,
357027,1,41,784,16, 434458,1,41,906,16,
35710,615,1,1297,785, 43450,720,1,1297,907,
357216,0,615,1,43, 434616,0,720,1,43,
3573786,16,0,615,1, 4347908,16,0,720,1,
35741803,787,17,788,15, 43481803,909,17,910,15,
3575789,4,16,37,0, 4349911,4,16,37,0,
357670,0,111,0,114, 435070,0,111,0,114,
35770,76,0,111,0, 43510,76,0,111,0,
3578111,0,112,0,1, 4352111,0,112,0,1,
3579-1,1,5,790,20, 4353-1,1,5,912,20,
3580791,4,18,70,0, 4354913,4,18,70,0,
3581111,0,114,0,76, 4355111,0,114,0,76,
35820,111,0,111,0, 43560,111,0,111,0,
3583112,0,95,0,49, 4357112,0,95,0,49,
35840,1,192,1,3, 43580,1,247,1,3,
35851,10,1,9,792, 43591,10,1,9,914,
358622,1,52,1,1804, 436022,1,83,1,1804,
3587793,16,0,615,1, 4361915,16,0,720,1,
3588299,794,16,0,615, 4362299,916,16,0,720,
35891,52,795,16,0, 43631,52,917,16,0,
3590615,1,2318,796,16, 4364720,1,2318,918,16,
35910,615,1,62,797, 43650,720,1,62,919,
359216,0,615,1,2075, 436616,0,720,1,2075,
3593798,16,0,615,1, 4367920,16,0,720,1,
35941574,799,17,800,15, 43681574,921,17,922,15,
3595727,1,-1,1,5, 4369849,1,-1,1,5,
3596801,20,802,4,22, 4370923,20,924,4,22,
359783,0,116,0,97, 437183,0,116,0,97,
35980,116,0,101,0, 43720,116,0,101,0,
3599109,0,101,0,110, 4373109,0,101,0,110,
36000,116,0,95,0, 43740,116,0,95,0,
360152,0,1,170,1, 437552,0,1,225,1,
36023,1,3,1,2, 43763,1,3,1,2,
3603803,22,1,30,1, 4377925,22,1,61,1,
360471,804,16,0,615, 437871,926,16,0,720,
36051,76,805,16,0, 43791,76,927,16,0,
3606615,1,1834,806,16, 4380720,1,1834,928,16,
36070,615,1,2337,807, 43810,720,1,2337,929,
360816,0,615,1,79, 438216,0,720,1,79,
3609808,16,0,615,1, 4383930,16,0,720,1,
36101335,809,16,0,615, 43841335,931,16,0,720,
36111,322,810,16,0, 43851,322,932,16,0,
3612615,1,85,811,16, 4386720,1,85,933,16,
36130,615,1,89,812, 43870,720,1,89,934,
361416,0,615,1,346, 438816,0,720,1,346,
3615813,16,0,615,1, 4389935,16,0,720,1,
36162105,814,17,815,15, 43902105,936,17,937,15,
3617720,1,-1,1,5, 4391842,1,-1,1,5,
3618816,20,817,4,26, 4392938,20,939,4,26,
361973,0,102,0,83, 439373,0,102,0,83,
36200,116,0,97,0, 43940,116,0,97,0,
3621116,0,101,0,109, 4395116,0,101,0,109,
36220,101,0,110,0, 43960,101,0,110,0,
3623116,0,95,0,51, 4397116,0,95,0,51,
36240,1,186,1,3, 43980,1,241,1,3,
36251,6,1,5,818, 43991,6,1,5,940,
362622,1,46,1,2106, 440022,1,77,1,2106,
3627819,16,0,615,1, 4401941,16,0,720,1,
362897,820,16,0,615, 440297,942,16,0,720,
36291,1860,821,17,822, 44031,1860,943,17,944,
363015,823,4,34,37, 440415,945,4,34,37,
36310,68,0,111,0, 44050,68,0,111,0,
363287,0,104,0,105, 440687,0,104,0,105,
36330,108,0,101,0, 44070,108,0,101,0,
@@ -3635,7 +4409,7 @@ public yyLSLSyntax
36350,116,0,101,0, 44090,116,0,101,0,
3636109,0,101,0,110, 4410109,0,101,0,110,
36370,116,0,1,-1, 44110,116,0,1,-1,
36381,5,824,20,825, 44121,5,946,20,947,
36394,36,68,0,111, 44134,36,68,0,111,
36400,87,0,104,0, 44140,87,0,104,0,
3641105,0,108,0,101, 4415105,0,108,0,101,
@@ -3643,66 +4417,66 @@ public yyLSLSyntax
364397,0,116,0,101, 441797,0,116,0,101,
36440,109,0,101,0, 44180,109,0,101,0,
3645110,0,116,0,95, 4419110,0,116,0,95,
36460,49,0,1,190, 44200,49,0,1,245,
36471,3,1,8,1, 44211,3,1,8,1,
36487,826,22,1,50, 44227,948,22,1,81,
36491,2364,827,17,828, 44231,2364,949,17,950,
365015,789,1,-1,1, 442415,911,1,-1,1,
36515,829,20,830,4, 44255,951,20,952,4,
365218,70,0,111,0, 442618,70,0,111,0,
3653114,0,76,0,111, 4427114,0,76,0,111,
36540,111,0,112,0, 44280,111,0,112,0,
365595,0,50,0,1, 442995,0,50,0,1,
3656193,1,3,1,9, 4430248,1,3,1,9,
36571,8,831,22,1, 44311,8,953,22,1,
365853,1,102,832,16, 443284,1,102,954,16,
36590,615,1,112,833, 44330,720,1,2782,955,
366016,0,615,1,1117, 443416,0,720,1,112,
3661834,16,0,615,1, 4435956,16,0,720,1,
36621873,835,17,836,15, 44361117,957,16,0,720,
3663823,1,-1,1,5, 44371,1873,958,17,959,
3664837,20,838,4,36, 443815,945,1,-1,1,
366568,0,111,0,87, 44395,960,20,961,4,
36660,104,0,105,0, 444036,68,0,111,0,
3667108,0,101,0,83, 444187,0,104,0,105,
36680,116,0,97,0, 44420,108,0,101,0,
3669116,0,101,0,109,
36700,101,0,110,0,
3671116,0,95,0,50,
36720,1,191,1,3,
36731,8,1,7,839,
367422,1,51,1,1876,
3675840,16,0,615,1,
3676124,841,16,0,615,
36771,2136,842,17,843,
367815,720,1,-1,1,
36795,844,20,845,4,
368026,73,0,102,0,
368183,0,116,0,97, 444383,0,116,0,97,
36820,116,0,101,0, 44440,116,0,101,0,
3683109,0,101,0,110, 4445109,0,101,0,110,
36840,116,0,95,0, 44460,116,0,95,0,
368552,0,1,187,1, 444750,0,1,246,1,
36863,1,8,1,7, 44483,1,8,1,7,
3687846,22,1,47,1, 4449962,22,1,82,1,
3688381,847,16,0,615, 44501876,963,16,0,720,
36891,525,848,16,0, 44511,124,964,16,0,
3690615,1,137,849,16, 4452720,1,2136,965,17,
36910,615,1,1901,850, 4453966,15,842,1,-1,
369216,0,615,1,2658, 44541,5,967,20,968,
3693851,16,0,615,1, 44554,26,73,0,102,
36941153,852,16,0,615, 44560,83,0,116,0,
36951,151,853,16,0, 445797,0,116,0,101,
3696615,1,1407,854,16, 44580,109,0,101,0,
36970,615,1,1659,855, 4459110,0,116,0,95,
369816,0,615,1,2413, 44600,52,0,1,242,
3699856,16,0,615,1, 44611,3,1,8,1,
3700406,857,16,0,615, 44627,969,22,1,78,
37011,1371,858,16,0, 44631,381,970,16,0,
3702615,1,166,859,16, 4464720,1,525,971,16,
37030,615,1,1622,860, 44650,720,1,137,972,
370416,0,615,1,1931, 446616,0,720,1,1901,
3705861,17,862,15,863, 4467973,16,0,720,1,
44681153,974,16,0,720,
44691,151,975,16,0,
4470720,1,1407,976,16,
44710,720,1,1659,977,
447216,0,720,1,2413,
4473978,16,0,720,1,
4474406,979,16,0,720,
44751,1371,980,16,0,
4476720,1,166,981,16,
44770,720,1,1622,982,
447816,0,720,1,1931,
4479983,17,984,15,985,
37064,30,37,0,87, 44804,30,37,0,87,
37070,104,0,105,0, 44810,104,0,105,0,
3708108,0,101,0,83, 4482108,0,101,0,83,
@@ -3710,46 +4484,46 @@ public yyLSLSyntax
3710116,0,101,0,109, 4484116,0,101,0,109,
37110,101,0,110,0, 44850,101,0,110,0,
3712116,0,1,-1,1, 4486116,0,1,-1,1,
37135,864,20,865,4, 44875,986,20,987,4,
371432,87,0,104,0, 448832,87,0,104,0,
3715105,0,108,0,101, 4489105,0,108,0,101,
37160,83,0,116,0, 44900,83,0,116,0,
371797,0,116,0,101, 449197,0,116,0,101,
37180,109,0,101,0, 44920,109,0,101,0,
3719110,0,116,0,95, 4493110,0,116,0,95,
37200,49,0,1,188, 44940,49,0,1,243,
37211,3,1,6,1, 44951,3,1,6,1,
37225,866,22,1,48, 44965,988,22,1,79,
37231,1933,867,16,0, 44971,1933,989,16,0,
3724615,1,431,868,16, 4498720,1,431,990,16,
37250,615,1,1585,869, 44990,720,1,1585,991,
372616,0,615,1,182, 450016,0,720,1,182,
3727870,16,0,615,1, 4501992,16,0,720,1,
37281189,871,16,0,615, 45021189,993,16,0,720,
37291,1443,872,16,0, 45031,1443,994,16,0,
3730615,1,1695,873,16, 4504720,1,1695,995,16,
37310,615,1,2198,874, 45050,720,1,2198,996,
373216,0,615,1,447, 450616,0,720,1,447,
3733875,16,0,615,1, 4507997,16,0,720,1,
37342458,876,17,877,15, 45082458,998,17,999,15,
3735878,4,28,37,0, 45091000,4,28,37,0,
373683,0,116,0,97, 451083,0,116,0,97,
37370,116,0,101,0, 45110,116,0,101,0,
3738109,0,101,0,110, 4512109,0,101,0,110,
37390,116,0,76,0, 45130,116,0,76,0,
3740105,0,115,0,116, 4514105,0,115,0,116,
37410,1,-1,1,5, 45150,1,-1,1,5,
3742879,20,880,4,30, 45161001,20,1002,4,30,
374383,0,116,0,97, 451783,0,116,0,97,
37440,116,0,101,0, 45180,116,0,101,0,
3745109,0,101,0,110, 4519109,0,101,0,110,
37460,116,0,76,0, 45200,116,0,76,0,
3747105,0,115,0,116, 4521105,0,115,0,116,
37480,95,0,50,0, 45220,95,0,50,0,
37491,165,1,3,1, 45231,220,1,3,1,
37503,1,2,881,22, 45243,1,2,1003,22,
37511,25,1,2459,882, 45251,56,1,2459,1004,
375217,883,15,884,4, 452617,1005,15,1006,4,
375336,37,0,67,0, 452736,37,0,67,0,
3754111,0,109,0,112, 4528111,0,109,0,112,
37550,111,0,117,0, 45290,111,0,117,0,
@@ -3758,7 +4532,7 @@ public yyLSLSyntax
3758116,0,101,0,109, 4532116,0,101,0,109,
37590,101,0,110,0, 45330,101,0,110,0,
3760116,0,1,-1,1, 4534116,0,1,-1,1,
37615,885,20,886,4, 45355,1007,20,1008,4,
376238,67,0,111,0, 453638,67,0,111,0,
3763109,0,112,0,111, 4537109,0,112,0,111,
37640,117,0,110,0, 45380,117,0,110,0,
@@ -3767,34 +4541,34 @@ public yyLSLSyntax
3767101,0,109,0,101, 4541101,0,109,0,101,
37680,110,0,116,0, 45420,110,0,116,0,
376995,0,50,0,1, 454395,0,50,0,1,
3770163,1,3,1,4, 4544218,1,3,1,4,
37711,3,887,22,1, 45451,3,1009,22,1,
377223,1,1958,888,16, 454654,1,1958,1010,16,
37730,615,1,2462,889, 45470,720,1,2462,1011,
377417,890,15,878,1, 454817,1012,15,1000,1,
3775-1,1,5,891,20, 4549-1,1,5,1013,20,
3776892,4,30,83,0, 45501014,4,30,83,0,
3777116,0,97,0,116, 4551116,0,97,0,116,
37780,101,0,109,0, 45520,101,0,109,0,
3779101,0,110,0,116, 4553101,0,110,0,116,
37800,76,0,105,0, 45540,76,0,105,0,
3781115,0,116,0,95, 4555115,0,116,0,95,
37820,49,0,1,164, 45560,49,0,1,219,
37831,3,1,2,1, 45571,3,1,2,1,
37841,893,22,1,24, 45581,1015,22,1,55,
37851,1657,894,17,895, 45591,1657,1016,17,1017,
378615,727,1,-1,1, 456015,849,1,-1,1,
37875,896,20,897,4, 45615,1018,20,1019,4,
378822,83,0,116,0, 456222,83,0,116,0,
378997,0,116,0,101, 456397,0,116,0,101,
37900,109,0,101,0, 45640,109,0,101,0,
3791110,0,116,0,95, 4565110,0,116,0,95,
37920,50,0,1,168, 45660,50,0,1,223,
37931,3,1,3,1, 45671,3,1,3,1,
37942,898,22,1,28, 45682,1020,22,1,59,
37951,2464,899,17,900, 45691,2464,1021,17,1022,
379615,884,1,-1,1, 457015,1006,1,-1,1,
37975,901,20,902,4, 45715,1023,20,1024,4,
379838,67,0,111,0, 457238,67,0,111,0,
3799109,0,112,0,111, 4573109,0,112,0,111,
38000,117,0,110,0, 45740,117,0,110,0,
@@ -3803,280 +4577,280 @@ public yyLSLSyntax
3803101,0,109,0,101, 4577101,0,109,0,101,
38040,110,0,116,0, 45780,110,0,116,0,
380595,0,49,0,1, 457995,0,49,0,1,
3806162,1,3,1,3, 4580217,1,3,1,3,
38071,2,903,22,1, 45811,2,1025,22,1,
380822,1,199,904,16, 458253,1,199,1026,16,
38090,615,1,459,905, 45830,720,1,459,1027,
381016,0,615,1,462, 458416,0,720,1,462,
3811906,16,0,615,1, 45851028,16,0,720,1,
3812217,907,16,0,615, 4586217,1029,16,0,720,
38131,2227,908,17,909, 45871,2227,1030,17,1031,
381415,863,1,-1,1, 458815,985,1,-1,1,
38155,910,20,911,4, 45895,1032,20,1033,4,
381632,87,0,104,0, 459032,87,0,104,0,
3817105,0,108,0,101, 4591105,0,108,0,101,
38180,83,0,116,0, 45920,83,0,116,0,
381997,0,116,0,101, 459397,0,116,0,101,
38200,109,0,101,0, 45940,109,0,101,0,
3821110,0,116,0,95, 4595110,0,116,0,95,
38220,50,0,1,189, 45960,50,0,1,244,
38231,3,1,6,1, 45971,3,1,6,1,
38245,912,22,1,49, 45985,1034,22,1,80,
38251,1225,913,16,0, 45991,1225,1035,16,0,
3826615,1,1479,914,16, 4600720,1,1479,1036,16,
38270,615,1,1731,915, 46010,720,1,1731,1037,
382816,0,615,1,1989, 460216,0,720,1,1989,
3829916,17,917,15,720, 46031038,17,1039,15,842,
38301,-1,1,5,918, 46041,-1,1,5,1040,
383120,919,4,26,73, 460520,1041,4,26,73,
38320,102,0,83,0, 46060,102,0,83,0,
3833116,0,97,0,116, 4607116,0,97,0,116,
38340,101,0,109,0, 46080,101,0,109,0,
3835101,0,110,0,116, 4609101,0,110,0,116,
38360,95,0,49,0, 46100,95,0,49,0,
38371,184,1,3,1, 46111,239,1,3,1,
38386,1,5,920,22, 46126,1,5,1042,22,
38391,44,1,1990,921, 46131,75,1,1990,1043,
384016,0,615,1,236, 461416,0,720,1,236,
3841922,16,0,615,1, 46151044,16,0,720,1,
38421756,923,16,0,615, 46161756,1045,16,0,720,
38431,4,924,19,184, 46171,4,1046,19,203,
38441,4,925,5,100, 46181,4,1047,5,100,
38451,256,926,16,0, 46191,256,1048,16,0,
3846538,1,1261,927,16, 4620616,1,1261,1049,16,
38470,538,1,509,928, 46210,616,1,509,1050,
384816,0,538,1,1515, 462216,0,616,1,1515,
3849929,16,0,538,1, 46231051,16,0,616,1,
38502021,718,1,1775,930, 46242021,840,1,1775,1052,
385116,0,538,1,2029, 462516,0,616,1,2029,
3852725,1,2030,731,1, 4626847,1,2030,853,1,
38532031,736,1,2032,741, 46272031,858,1,2032,863,
38541,2033,746,1,277, 46281,2033,868,1,277,
3855931,16,0,538,1, 46291053,16,0,616,1,
38562035,752,1,2037,757, 46302035,874,1,2037,879,
38571,2039,762,1,32, 46311,2039,884,1,32,
3858932,16,0,538,1, 46321054,16,0,616,1,
38592041,768,1,2293,933, 46332041,890,1,2293,1055,
386016,0,538,1,2043, 463416,0,616,1,2043,
3861774,1,2045,779,1, 4635896,1,2045,901,1,
386240,934,16,0,186, 463640,1056,16,0,205,
38631,41,935,16,0, 46371,41,1057,16,0,
3864538,1,1297,936,16, 4638616,1,1297,1058,16,
38650,538,1,43,937, 46390,616,1,43,1059,
386616,0,538,1,44, 464016,0,616,1,44,
3867938,16,0,186,1, 46411060,16,0,205,1,
38681803,787,1,1804,939, 46421803,909,1,1804,1061,
386916,0,538,1,299, 464316,0,616,1,299,
3870940,16,0,538,1, 46441062,16,0,616,1,
387147,941,16,0,182, 464547,1063,16,0,201,
38721,52,942,16,0, 46461,52,1064,16,0,
3873538,1,2318,943,16, 4647616,1,2318,1065,16,
38740,538,1,63,944, 46480,616,1,63,1066,
387516,0,201,1,66, 464916,0,227,1,66,
3876945,16,0,199,1, 46501067,16,0,225,1,
38772075,946,16,0,538, 46512075,1068,16,0,616,
38781,1574,799,1,71, 46521,1574,921,1,71,
3879947,16,0,538,1, 46531069,16,0,616,1,
388076,948,16,0,538, 465476,1070,16,0,616,
38811,1834,949,16,0, 46551,1834,1071,16,0,
3882538,1,2337,950,16, 4656616,1,2337,1072,16,
38830,538,1,79,951, 46570,616,1,79,1073,
388416,0,538,1,1335, 465816,0,616,1,1335,
3885952,16,0,538,1, 46591074,16,0,616,1,
3886322,953,16,0,538, 4660322,1075,16,0,616,
38871,85,954,16,0, 46611,85,1076,16,0,
3888538,1,89,955,16, 4662616,1,89,1077,16,
38890,538,1,346,956, 46630,616,1,346,1078,
389016,0,538,1,97, 466416,0,616,1,97,
3891957,16,0,538,1, 46651079,16,0,616,1,
38922106,958,16,0,538, 46662106,1080,16,0,616,
38931,102,959,16,0, 46671,102,1081,16,0,
3894538,1,1860,821,1, 4668616,1,1860,943,1,
38952364,827,1,1114,960, 46692364,949,1,2782,1082,
389616,0,182,1,112, 467016,0,616,1,1114,
3897961,16,0,538,1, 46711083,16,0,201,1,
38981117,962,16,0,538, 4672112,1084,16,0,616,
38991,1873,835,1,1876, 46731,1117,1085,16,0,
3900963,16,0,538,1, 4674616,1,1873,958,1,
3901124,964,16,0,538, 46751876,1086,16,0,616,
39021,2136,842,1,381, 46761,124,1087,16,0,
3903965,16,0,538,1, 4677616,1,2136,965,1,
3904525,966,16,0,538, 4678381,1088,16,0,616,
39051,137,967,16,0, 46791,525,1089,16,0,
3906538,1,1901,968,16, 4680616,1,137,1090,16,
39070,538,1,2658,969, 46810,616,1,1901,1091,
390816,0,538,1,1153, 468216,0,616,1,1153,
3909970,16,0,538,1, 46831092,16,0,616,1,
3910151,971,16,0,538, 4684151,1093,16,0,616,
39111,1407,972,16,0, 46851,1407,1094,16,0,
3912538,1,1659,973,16, 4686616,1,1659,1095,16,
39130,538,1,2413,974, 46870,616,1,2413,1096,
391416,0,538,1,406, 468816,0,616,1,406,
3915975,16,0,538,1, 46891097,16,0,616,1,
39161371,976,16,0,538, 46901371,1098,16,0,616,
39171,2105,814,1,166, 46911,2105,936,1,166,
3918977,16,0,538,1, 46921099,16,0,616,1,
39191622,978,16,0,538, 46931622,1100,16,0,616,
39201,1931,861,1,1933, 46941,1931,983,1,1933,
3921979,16,0,538,1, 46951101,16,0,616,1,
3922431,980,16,0,538, 4696431,1102,16,0,616,
39231,1585,981,16,0, 46971,1585,1103,16,0,
3924538,1,182,982,16, 4698616,1,182,1104,16,
39250,538,1,1189,983, 46990,616,1,1189,1105,
392616,0,538,1,1443, 470016,0,616,1,1443,
3927984,16,0,538,1, 47011106,16,0,616,1,
39281695,985,16,0,538, 47021695,1107,16,0,616,
39291,2198,986,16,0, 47031,2198,1108,16,0,
3930538,1,447,987,16, 4704616,1,447,1109,16,
39310,538,1,2458,876, 47050,616,1,2458,998,
39321,2459,882,1,1958, 47061,2459,1004,1,1958,
3933988,16,0,538,1, 47071110,16,0,616,1,
39342462,889,1,1657,894, 47082462,1011,1,1657,1016,
39351,2464,899,1,199, 47091,2464,1021,1,199,
3936989,16,0,538,1, 47101111,16,0,616,1,
3937459,990,16,0,538, 4711459,1112,16,0,616,
39381,462,991,16,0, 47121,462,1113,16,0,
3939538,1,217,992,16, 4713616,1,217,1114,16,
39400,538,1,2227,908, 47140,616,1,2227,1030,
39411,1225,993,16,0, 47151,1225,1115,16,0,
3942538,1,1479,994,16, 4716616,1,1479,1116,16,
39430,538,1,1731,995, 47170,616,1,1731,1117,
394416,0,538,1,1989, 471816,0,616,1,1989,
3945916,1,1990,996,16, 47191038,1,1990,1118,16,
39460,538,1,236,997, 47200,616,1,236,1119,
394716,0,538,1,1756, 472116,0,616,1,1756,
3948998,16,0,538,1, 47221120,16,0,616,1,
39495,999,19,181,1, 47235,1121,19,200,1,
39505,1000,5,100,1, 47245,1122,5,100,1,
3951256,1001,16,0,534, 4725256,1123,16,0,612,
39521,1261,1002,16,0, 47261,1261,1124,16,0,
3953534,1,509,1003,16, 4727612,1,509,1125,16,
39540,534,1,1515,1004, 47280,612,1,1515,1126,
395516,0,534,1,2021, 472916,0,612,1,2021,
3956718,1,1775,1005,16, 4730840,1,1775,1127,16,
39570,534,1,2029,725, 47310,612,1,2029,847,
39581,2030,731,1,2031, 47321,2030,853,1,2031,
3959736,1,2032,741,1, 4733858,1,2032,863,1,
39602033,746,1,277,1006, 47342033,868,1,277,1128,
396116,0,534,1,2035, 473516,0,612,1,2035,
3962752,1,2037,757,1, 4736874,1,2037,879,1,
39632039,762,1,32,1007, 47372039,884,1,32,1129,
396416,0,534,1,2041, 473816,0,612,1,2041,
3965768,1,2293,1008,16, 4739890,1,2293,1130,16,
39660,534,1,2043,774, 47400,612,1,2043,896,
39671,2045,779,1,40, 47411,2045,901,1,40,
39681009,16,0,185,1, 47421131,16,0,204,1,
396941,1010,16,0,534, 474341,1132,16,0,612,
39701,1297,1011,16,0, 47441,1297,1133,16,0,
3971534,1,43,1012,16, 4745612,1,43,1134,16,
39720,534,1,44,1013, 47460,612,1,44,1135,
397316,0,185,1,1803, 474716,0,204,1,1803,
3974787,1,1804,1014,16, 4748909,1,1804,1136,16,
39750,534,1,299,1015, 47490,612,1,299,1137,
397616,0,534,1,47, 475016,0,612,1,47,
39771016,16,0,179,1, 47511138,16,0,198,1,
397852,1017,16,0,534, 475252,1139,16,0,612,
39791,2318,1018,16,0, 47531,2318,1140,16,0,
3980534,1,63,1019,16, 4754612,1,63,1141,16,
39810,200,1,66,1020, 47550,226,1,66,1142,
398216,0,198,1,2075, 475616,0,224,1,2075,
39831021,16,0,534,1, 47571143,16,0,612,1,
39841574,799,1,71,1022, 47581574,921,1,71,1144,
398516,0,534,1,76, 475916,0,612,1,76,
39861023,16,0,534,1, 47601145,16,0,612,1,
39871834,1024,16,0,534, 47611834,1146,16,0,612,
39881,2337,1025,16,0, 47621,2337,1147,16,0,
3989534,1,79,1026,16, 4763612,1,79,1148,16,
39900,534,1,1335,1027, 47640,612,1,1335,1149,
399116,0,534,1,322, 476516,0,612,1,322,
39921028,16,0,534,1, 47661150,16,0,612,1,
399385,1029,16,0,534, 476785,1151,16,0,612,
39941,89,1030,16,0, 47681,89,1152,16,0,
3995534,1,346,1031,16, 4769612,1,346,1153,16,
39960,534,1,97,1032, 47700,612,1,97,1154,
399716,0,534,1,2106, 477116,0,612,1,2106,
39981033,16,0,534,1, 47721155,16,0,612,1,
3999102,1034,16,0,534, 4773102,1156,16,0,612,
40001,1860,821,1,2364, 47741,1860,943,1,2364,
4001827,1,1114,1035,16, 4775949,1,2782,1157,16,
40020,179,1,112,1036, 47760,612,1,1114,1158,
400316,0,534,1,1117, 477716,0,198,1,112,
40041037,16,0,534,1, 47781159,16,0,612,1,
40051873,835,1,1876,1038, 47791117,1160,16,0,612,
400616,0,534,1,124, 47801,1873,958,1,1876,
40071039,16,0,534,1, 47811161,16,0,612,1,
40082136,842,1,381,1040, 4782124,1162,16,0,612,
400916,0,534,1,525, 47831,2136,965,1,381,
40101041,16,0,534,1, 47841163,16,0,612,1,
4011137,1042,16,0,534, 4785525,1164,16,0,612,
40121,1901,1043,16,0, 47861,137,1165,16,0,
4013534,1,2658,1044,16, 4787612,1,1901,1166,16,
40140,534,1,1153,1045, 47880,612,1,1153,1167,
401516,0,534,1,151, 478916,0,612,1,151,
40161046,16,0,534,1, 47901168,16,0,612,1,
40171407,1047,16,0,534, 47911407,1169,16,0,612,
40181,1659,1048,16,0, 47921,1659,1170,16,0,
4019534,1,2413,1049,16, 4793612,1,2413,1171,16,
40200,534,1,406,1050, 47940,612,1,406,1172,
402116,0,534,1,1371, 479516,0,612,1,1371,
40221051,16,0,534,1, 47961173,16,0,612,1,
40232105,814,1,166,1052, 47972105,936,1,166,1174,
402416,0,534,1,1622, 479816,0,612,1,1622,
40251053,16,0,534,1, 47991175,16,0,612,1,
40261931,861,1,1933,1054, 48001931,983,1,1933,1176,
402716,0,534,1,431, 480116,0,612,1,431,
40281055,16,0,534,1, 48021177,16,0,612,1,
40291585,1056,16,0,534, 48031585,1178,16,0,612,
40301,182,1057,16,0, 48041,182,1179,16,0,
4031534,1,1189,1058,16, 4805612,1,1189,1180,16,
40320,534,1,1443,1059, 48060,612,1,1443,1181,
403316,0,534,1,1695, 480716,0,612,1,1695,
40341060,16,0,534,1, 48081182,16,0,612,1,
40352198,1061,16,0,534, 48092198,1183,16,0,612,
40361,447,1062,16,0, 48101,447,1184,16,0,
4037534,1,2458,876,1, 4811612,1,2458,998,1,
40382459,882,1,1958,1063, 48122459,1004,1,1958,1185,
403916,0,534,1,2462, 481316,0,612,1,2462,
4040889,1,1657,894,1, 48141011,1,1657,1016,1,
40412464,899,1,199,1064, 48152464,1021,1,199,1186,
404216,0,534,1,459, 481616,0,612,1,459,
40431065,16,0,534,1, 48171187,16,0,612,1,
4044462,1066,16,0,534, 4818462,1188,16,0,612,
40451,217,1067,16,0, 48191,217,1189,16,0,
4046534,1,2227,908,1, 4820612,1,2227,1030,1,
40471225,1068,16,0,534, 48211225,1190,16,0,612,
40481,1479,1069,16,0, 48221,1479,1191,16,0,
4049534,1,1731,1070,16, 4823612,1,1731,1192,16,
40500,534,1,1989,916, 48240,612,1,1989,1038,
40511,1990,1071,16,0, 48251,1990,1193,16,0,
4052534,1,236,1072,16, 4826612,1,236,1194,16,
40530,534,1,1756,1073, 48270,612,1,1756,1195,
405416,0,534,1,6, 482816,0,612,1,6,
40551074,19,277,1,6, 48291196,19,306,1,6,
40561075,5,2,1,1114, 48301197,5,2,1,1114,
40571076,16,0,275,1, 48311198,16,0,304,1,
405840,1077,16,0,523, 483240,1199,16,0,601,
40591,7,1078,19,243, 48331,7,1200,19,270,
40601,7,1079,5,2, 48341,7,1201,5,2,
40611,1114,1080,16,0, 48351,1114,1202,16,0,
4062241,1,40,1081,16, 4836268,1,40,1203,16,
40630,459,1,8,1082, 48370,531,1,8,1204,
406419,207,1,8,1083, 483819,233,1,8,1205,
40655,2,1,1114,1084, 48395,2,1,1114,1206,
406616,0,205,1,40, 484016,0,231,1,40,
40671085,16,0,439,1, 48411207,16,0,489,1,
40689,1086,19,213,1, 48429,1208,19,239,1,
40699,1087,5,2,1, 48439,1209,5,2,1,
40701114,1088,16,0,211, 48441114,1210,16,0,237,
40711,40,1089,16,0, 48451,40,1211,16,0,
4072384,1,10,1090,19, 4846420,1,10,1212,19,
4073164,1,10,1091,5, 4847183,1,10,1213,5,
40742,1,1114,1092,16, 48482,1,1114,1214,16,
40750,162,1,40,1093, 48490,181,1,40,1215,
407616,0,324,1,11, 485016,0,360,1,11,
40771094,19,192,1,11, 48511216,19,147,1,11,
40781095,5,146,1,1260, 48521217,5,146,1,1260,
40791096,17,1097,15,1098, 48531218,17,1219,15,1220,
40804,34,37,0,83, 48544,34,37,0,83,
40810,105,0,109,0, 48550,105,0,109,0,
4082112,0,108,0,101, 4856112,0,108,0,101,
@@ -4085,7 +4859,7 @@ public yyLSLSyntax
40850,110,0,109,0, 48590,110,0,109,0,
4086101,0,110,0,116, 4860101,0,110,0,116,
40870,1,-1,1,5, 48610,1,-1,1,5,
40881099,20,1100,4,38, 48621221,20,1222,4,38,
408983,0,105,0,109, 486383,0,105,0,109,
40900,112,0,108,0, 48640,112,0,108,0,
4091101,0,65,0,115, 4865101,0,65,0,115,
@@ -4093,11 +4867,11 @@ public yyLSLSyntax
4093103,0,110,0,109, 4867103,0,110,0,109,
40940,101,0,110,0, 48680,101,0,110,0,
4095116,0,95,0,50, 4869116,0,95,0,50,
40960,49,0,1,220, 48700,49,0,1,275,
40971,3,1,6,1, 48711,3,1,6,1,
40985,1101,22,1,80, 48725,1223,22,1,111,
40991,1011,1102,17,1103, 48731,1011,1224,17,1225,
410015,1104,4,44,37, 487415,1226,4,44,37,
41010,80,0,97,0, 48750,80,0,97,0,
4102114,0,101,0,110, 4876114,0,101,0,110,
41030,116,0,104,0, 48770,116,0,104,0,
@@ -4107,7 +4881,7 @@ public yyLSLSyntax
41070,101,0,115,0, 48810,101,0,115,0,
4108115,0,105,0,111, 4882115,0,105,0,111,
41090,110,0,1,-1, 48830,110,0,1,-1,
41101,5,1105,20,1106, 48841,5,1227,20,1228,
41114,46,80,0,97, 48854,46,80,0,97,
41120,114,0,101,0, 48860,114,0,101,0,
4113110,0,116,0,104, 4887110,0,116,0,104,
@@ -4117,12 +4891,12 @@ public yyLSLSyntax
4117114,0,101,0,115, 4891114,0,101,0,115,
41180,115,0,105,0, 48920,115,0,105,0,
4119111,0,110,0,95, 4893111,0,110,0,95,
41200,50,0,1,267, 48940,50,0,1,322,
41211,3,1,4,1, 48951,3,1,4,1,
41223,1107,22,1,127, 48963,1229,22,1,158,
41231,1514,1108,17,1109, 48971,1514,1230,17,1231,
412415,1098,1,-1,1, 489815,1220,1,-1,1,
41255,1110,20,1111,4, 48995,1232,20,1233,4,
412638,83,0,105,0, 490038,83,0,105,0,
4127109,0,112,0,108, 4901109,0,112,0,108,
41280,101,0,65,0, 49020,101,0,65,0,
@@ -4131,26 +4905,26 @@ public yyLSLSyntax
4131109,0,101,0,110, 4905109,0,101,0,110,
41320,116,0,95,0, 49060,116,0,95,0,
413349,0,52,0,1, 490749,0,52,0,1,
4134213,1,3,1,4, 4908268,1,3,1,4,
41351,3,1112,22,1, 49091,3,1234,22,1,
413673,1,9,1113,17, 4910104,1,9,1235,17,
41371114,15,1115,4,24, 49111236,15,1237,4,24,
413837,0,68,0,101, 491237,0,68,0,101,
41390,99,0,108,0, 49130,99,0,108,0,
414097,0,114,0,97, 491497,0,114,0,97,
41410,116,0,105,0, 49150,116,0,105,0,
4142111,0,110,0,1, 4916111,0,110,0,1,
4143-1,1,5,1116,20, 4917-1,1,5,1238,20,
41441117,4,26,68,0, 49181239,4,26,68,0,
4145101,0,99,0,108, 4919101,0,99,0,108,
41460,97,0,114,0, 49200,97,0,114,0,
414797,0,116,0,105, 492197,0,116,0,105,
41480,111,0,110,0, 49220,111,0,110,0,
414995,0,49,0,1, 492395,0,49,0,1,
4150161,1,3,1,3, 4924212,1,3,1,3,
41511,2,1118,22,1, 49251,2,1240,22,1,
415221,1,262,1119,17, 492648,1,262,1241,17,
41531120,15,1121,4,34, 49271242,15,1243,4,34,
415437,0,66,0,105, 492837,0,66,0,105,
41550,110,0,97,0, 49290,110,0,97,0,
4156114,0,121,0,69, 4930114,0,121,0,69,
@@ -4158,8 +4932,8 @@ public yyLSLSyntax
4158114,0,101,0,115, 4932114,0,101,0,115,
41590,115,0,105,0, 49330,115,0,105,0,
4160111,0,110,0,1, 4934111,0,110,0,1,
4161-1,1,5,1122,20, 4935-1,1,5,1244,20,
41621123,4,36,66,0, 49361245,4,36,66,0,
4163105,0,110,0,97, 4937105,0,110,0,97,
41640,114,0,121,0, 49380,114,0,121,0,
416569,0,120,0,112, 493969,0,120,0,112,
@@ -4167,11 +4941,11 @@ public yyLSLSyntax
4167115,0,115,0,105, 4941115,0,115,0,105,
41680,111,0,110,0, 49420,111,0,110,0,
416995,0,53,0,1, 494395,0,53,0,1,
4170249,1,3,1,4, 4944304,1,3,1,4,
41711,3,1124,22,1, 49451,3,1246,22,1,
4172109,1,1267,1125,17, 4946140,1,1267,1247,17,
41731126,15,1098,1,-1, 49471248,15,1220,1,-1,
41741,5,1127,20,1128, 49481,5,1249,20,1250,
41754,36,83,0,105, 49494,36,83,0,105,
41760,109,0,112,0, 49500,109,0,112,0,
4177108,0,101,0,65, 4951108,0,101,0,65,
@@ -4179,13 +4953,13 @@ public yyLSLSyntax
4179105,0,103,0,110, 4953105,0,103,0,110,
41800,109,0,101,0, 49540,109,0,101,0,
4181110,0,116,0,95, 4955110,0,116,0,95,
41820,56,0,1,207, 49560,56,0,1,262,
41831,3,1,6,1, 49571,3,1,6,1,
41845,1129,22,1,67, 49585,1251,22,1,98,
41851,2021,718,1,1521, 49591,2021,840,1,1521,
41861130,17,1131,15,1098, 49601252,17,1253,15,1220,
41871,-1,1,5,1132, 49611,-1,1,5,1254,
418820,1133,4,36,83, 496220,1255,4,36,83,
41890,105,0,109,0, 49630,105,0,109,0,
4190112,0,108,0,101, 4964112,0,108,0,101,
41910,65,0,115,0, 49650,65,0,115,0,
@@ -4193,26 +4967,26 @@ public yyLSLSyntax
41930,110,0,109,0, 49670,110,0,109,0,
4194101,0,110,0,116, 4968101,0,110,0,116,
41950,95,0,49,0, 49690,95,0,49,0,
41961,200,1,3,1, 49701,255,1,3,1,
41974,1,3,1134,22, 49714,1,3,1256,22,
41981,60,1,2024,1135, 49721,91,1,2024,1257,
419917,1136,15,1137,4, 497317,1258,15,1259,4,
420024,37,0,83,0, 497424,37,0,83,0,
4201116,0,97,0,116, 4975116,0,97,0,116,
42020,101,0,67,0, 49760,101,0,67,0,
4203104,0,97,0,110, 4977104,0,97,0,110,
42040,103,0,101,0, 49780,103,0,101,0,
42051,-1,1,5,1138, 49791,-1,1,5,1260,
420620,1139,4,26,83, 498020,1261,4,26,83,
42070,116,0,97,0, 49810,116,0,97,0,
4208116,0,101,0,67, 4982116,0,101,0,67,
42090,104,0,97,0, 49830,104,0,97,0,
4210110,0,103,0,101, 4984110,0,103,0,101,
42110,95,0,49,0, 49850,95,0,49,0,
42121,182,1,3,1, 49861,237,1,3,1,
42133,1,2,1140,22, 49873,1,2,1262,22,
42141,42,1,1775,1141, 49881,73,1,1775,1263,
421517,1142,15,1143,4, 498917,1264,15,1265,4,
421630,37,0,69,0, 499030,37,0,69,0,
4217109,0,112,0,116, 4991109,0,112,0,116,
42180,121,0,83,0, 49920,121,0,83,0,
@@ -4220,34 +4994,34 @@ public yyLSLSyntax
42200,101,0,109,0, 49940,101,0,109,0,
4221101,0,110,0,116, 4995101,0,110,0,116,
42220,1,-1,1,5, 49960,1,-1,1,5,
42231144,20,1145,4,32, 49971266,20,1267,4,32,
422469,0,109,0,112, 499869,0,109,0,112,
42250,116,0,121,0, 49990,116,0,121,0,
422683,0,116,0,97, 500083,0,116,0,97,
42270,116,0,101,0, 50010,116,0,101,0,
4228109,0,101,0,110, 5002109,0,101,0,110,
42290,116,0,95,0, 50030,116,0,95,0,
423049,0,1,166,1, 500449,0,1,221,1,
42313,1,1,1,0, 50053,1,1,1,0,
42321146,22,1,26,1, 50061268,22,1,57,1,
423319,1147,17,1114,1, 500719,1269,17,1236,1,
42342,1118,1,2028,1148, 50082,1240,1,2028,1270,
423517,1149,15,1150,4, 500917,1271,15,1272,4,
423620,37,0,74,0, 501020,37,0,74,0,
4237117,0,109,0,112, 5011117,0,109,0,112,
42380,76,0,97,0, 50120,76,0,97,0,
423998,0,101,0,108, 501398,0,101,0,108,
42400,1,-1,1,5, 50140,1,-1,1,5,
42411151,20,1152,4,22, 50151273,20,1274,4,22,
424274,0,117,0,109, 501674,0,117,0,109,
42430,112,0,76,0, 50170,112,0,76,0,
424497,0,98,0,101, 501897,0,98,0,101,
42450,108,0,95,0, 50190,108,0,95,0,
424649,0,1,180,1, 502049,0,1,235,1,
42473,1,3,1,2, 50213,1,3,1,2,
42481153,22,1,40,1, 50221275,22,1,71,1,
42492029,725,1,2281,1154, 50232029,847,1,2281,1276,
425017,1155,15,1156,4, 502417,1277,15,1278,4,
425134,37,0,70,0, 502534,37,0,70,0,
4252111,0,114,0,76, 5026111,0,114,0,76,
42530,111,0,111,0, 50270,111,0,111,0,
@@ -4255,8 +5029,8 @@ public yyLSLSyntax
42550,97,0,116,0, 50290,97,0,116,0,
4256101,0,109,0,101, 5030101,0,109,0,101,
42570,110,0,116,0, 50310,110,0,116,0,
42581,-1,1,5,1157, 50321,-1,1,5,1279,
425920,1158,4,36,70, 503320,1280,4,36,70,
42600,111,0,114,0, 50340,111,0,114,0,
426176,0,111,0,111, 503576,0,111,0,111,
42620,112,0,83,0, 50360,112,0,83,0,
@@ -4264,124 +5038,107 @@ public yyLSLSyntax
42640,101,0,109,0, 50380,101,0,109,0,
4265101,0,110,0,116, 5039101,0,110,0,116,
42660,95,0,50,0, 50400,95,0,50,0,
42671,195,1,3,1, 50411,250,1,3,1,
42682,1,1,1159,22, 50422,1,1,1281,22,
42691,55,1,2031,736, 50431,86,1,2031,858,
42701,2032,741,1,2033, 50441,2032,863,1,2033,
4271746,1,2034,1160,16, 5045868,1,2034,1282,16,
42720,572,1,2035,752, 50460,676,1,2788,1283,
42731,2036,1161,16,0, 504716,0,145,1,2036,
4274524,1,2037,757,1, 50481284,16,0,602,1,
42752038,1162,16,0,528, 50492037,879,1,2038,1285,
42761,2039,762,1,32, 505016,0,606,1,2039,
42771163,17,1142,1,0, 5051884,1,32,1286,17,
42781146,1,2041,768,1, 50521264,1,0,1268,1,
42792042,1164,16,0,646, 50532041,890,1,2042,1287,
42801,2043,774,1,2044, 505416,0,749,1,2043,
42811165,16,0,584,1, 5055896,1,2044,1288,16,
42822045,779,1,2299,1166, 50560,689,1,2045,901,
428316,0,226,1,1296, 50571,2299,1289,16,0,
42841167,17,1168,15,1098, 5058255,1,1296,1290,17,
42851,-1,1,5,1169, 50591291,15,1220,1,-1,
428620,1170,4,38,83, 50601,5,1292,20,1293,
42870,105,0,109,0, 50614,38,83,0,105,
4288112,0,108,0,101, 50620,109,0,112,0,
42890,65,0,115,0, 5063108,0,101,0,65,
4290115,0,105,0,103, 50640,115,0,115,0,
42910,110,0,109,0, 5065105,0,103,0,110,
4292101,0,110,0,116, 50660,109,0,101,0,
42930,95,0,50,0, 5067110,0,116,0,95,
429448,0,1,219,1, 50680,50,0,48,0,
42953,1,6,1,5, 50691,274,1,3,1,
42961171,22,1,79,1, 50706,1,5,1294,22,
4297283,1172,17,1173,15, 50711,110,1,283,1295,
42981121,1,-1,1,5, 507217,1296,15,1243,1,
42991174,20,1175,4,36, 5073-1,1,5,1297,20,
430066,0,105,0,110, 50741298,4,36,66,0,
43010,97,0,114,0, 5075105,0,110,0,97,
4302121,0,69,0,120, 50760,114,0,121,0,
43030,112,0,114,0, 507769,0,120,0,112,
4304101,0,115,0,115, 50780,114,0,101,0,
43050,105,0,111,0, 5079115,0,115,0,105,
4306110,0,95,0,52, 50800,111,0,110,0,
43070,1,248,1,3, 508195,0,52,0,1,
43081,4,1,3,1176, 5082303,1,3,1,4,
430922,1,108,1,40, 50831,3,1299,22,1,
43101177,17,1178,15,1179, 5084139,1,40,1300,17,
43114,32,37,0,73, 50851301,15,1302,4,32,
43120,100,0,101,0, 508637,0,73,0,100,
4313110,0,116,0,69, 50870,101,0,110,0,
43140,120,0,112,0,
4315114,0,101,0,115,
43160,115,0,105,0,
4317111,0,110,0,1,
4318-1,1,5,1180,20,
43191181,4,34,73,0,
4320100,0,101,0,110,
43210,116,0,69,0,
4322120,0,112,0,114,
43230,101,0,115,0,
4324115,0,105,0,111,
43250,110,0,95,0,
432649,0,1,234,1,
43273,1,2,1,1,
43281182,22,1,94,1,
432944,1183,17,1178,1,
43301,1182,1,1803,787,
43311,47,1184,17,1185,
433215,1186,4,38,37,
43330,73,0,100,0,
4334101,0,110,0,116,
43350,68,0,111,0,
4336116,0,69,0,120, 5088116,0,69,0,120,
43370,112,0,114,0, 50890,112,0,114,0,
4338101,0,115,0,115, 5090101,0,115,0,115,
43390,105,0,111,0, 50910,105,0,111,0,
4340110,0,1,-1,1, 5092110,0,1,-1,1,
43415,1187,20,1188,4, 50935,1303,20,1304,4,
434240,73,0,100,0, 509434,73,0,100,0,
4343101,0,110,0,116, 5095101,0,110,0,116,
43440,68,0,111,0, 50960,69,0,120,0,
4345116,0,69,0,120, 5097112,0,114,0,101,
43460,112,0,114,0, 50980,115,0,115,0,
4347101,0,115,0,115, 5099105,0,111,0,110,
43480,105,0,111,0, 51000,95,0,49,0,
4349110,0,95,0,49, 51011,289,1,3,1,
43500,1,235,1,3, 51022,1,1,1305,22,
43511,4,1,3,1189, 51031,125,1,44,1306,
435222,1,95,1,48, 510417,1301,1,1,1305,
43531190,17,1191,15,1192, 51051,1803,909,1,47,
43544,58,37,0,73, 51061307,17,1308,15,1309,
43550,110,0,99,0, 51074,38,37,0,73,
4356114,0,101,0,109, 51080,100,0,101,0,
43570,101,0,110,0, 5109110,0,116,0,68,
4358116,0,68,0,101, 51100,111,0,116,0,
43590,99,0,114,0,
4360101,0,109,0,101,
43610,110,0,116,0,
436269,0,120,0,112, 511169,0,120,0,112,
43630,114,0,101,0, 51120,114,0,101,0,
4364115,0,115,0,105, 5113115,0,115,0,105,
43650,111,0,110,0, 51140,111,0,110,0,
43661,-1,1,5,1193, 51151,-1,1,5,1310,
436720,1194,4,60,73, 511620,1311,4,40,73,
43680,110,0,99,0, 51170,100,0,101,0,
4369114,0,101,0,109, 5118110,0,116,0,68,
43700,101,0,110,0, 51190,111,0,116,0,
4371116,0,68,0,101,
43720,99,0,114,0,
4373101,0,109,0,101,
43740,110,0,116,0,
437569,0,120,0,112, 512069,0,120,0,112,
43760,114,0,101,0, 51210,114,0,101,0,
4377115,0,115,0,105, 5122115,0,115,0,105,
43780,111,0,110,0, 51230,111,0,110,0,
437995,0,52,0,1, 512495,0,49,0,1,
4380239,1,3,1,5, 5125290,1,3,1,4,
43811,4,1195,22,1, 51261,3,1312,22,1,
438299,1,49,1196,17, 5127126,1,48,1313,17,
43831197,15,1192,1,-1, 51281314,15,1315,4,58,
43841,5,1198,20,1199, 512937,0,73,0,110,
51300,99,0,114,0,
5131101,0,109,0,101,
51320,110,0,116,0,
513368,0,101,0,99,
51340,114,0,101,0,
5135109,0,101,0,110,
51360,116,0,69,0,
5137120,0,112,0,114,
51380,101,0,115,0,
5139115,0,105,0,111,
51400,110,0,1,-1,
51411,5,1316,20,1317,
43854,60,73,0,110, 51424,60,73,0,110,
43860,99,0,114,0, 51430,99,0,114,0,
4387101,0,109,0,101, 5144101,0,109,0,101,
@@ -4394,12 +5151,12 @@ public yyLSLSyntax
43940,101,0,115,0, 51510,101,0,115,0,
4395115,0,105,0,111, 5152115,0,105,0,111,
43960,110,0,95,0, 51530,110,0,95,0,
439751,0,1,238,1, 515452,0,1,294,1,
43983,1,5,1,4, 51553,1,5,1,4,
43991200,22,1,98,1, 51561318,22,1,130,1,
440050,1201,17,1202,15, 515749,1319,17,1320,15,
44011192,1,-1,1,5, 51581315,1,-1,1,5,
44021203,20,1204,4,60, 51591321,20,1322,4,60,
440373,0,110,0,99, 516073,0,110,0,99,
44040,114,0,101,0, 51610,114,0,101,0,
4405109,0,101,0,110, 5162109,0,101,0,110,
@@ -4411,13 +5168,13 @@ public yyLSLSyntax
4411112,0,114,0,101, 5168112,0,114,0,101,
44120,115,0,115,0, 51690,115,0,115,0,
4413105,0,111,0,110, 5170105,0,111,0,110,
44140,95,0,50,0, 51710,95,0,51,0,
44151,237,1,3,1, 51721,293,1,3,1,
44163,1,2,1205,22, 51735,1,4,1323,22,
44171,97,1,51,1206, 51741,129,1,50,1324,
441817,1207,15,1192,1, 517517,1325,15,1315,1,
4419-1,1,5,1208,20, 5176-1,1,5,1326,20,
44201209,4,60,73,0, 51771327,4,60,73,0,
4421110,0,99,0,114, 5178110,0,99,0,114,
44220,101,0,109,0, 51790,101,0,109,0,
4423101,0,110,0,116, 5180101,0,110,0,116,
@@ -4429,67 +5186,71 @@ public yyLSLSyntax
4429114,0,101,0,115, 5186114,0,101,0,115,
44300,115,0,105,0, 51870,115,0,105,0,
4431111,0,110,0,95, 5188111,0,110,0,95,
44320,49,0,1,236, 51890,50,0,1,292,
44331,3,1,3,1, 51901,3,1,3,1,
44342,1210,22,1,96, 51912,1328,22,1,128,
44351,305,1211,17,1212, 51921,51,1329,17,1330,
443615,1121,1,-1,1, 519315,1315,1,-1,1,
44375,1213,20,1214,4, 51945,1331,20,1332,4,
443836,66,0,105,0, 519560,73,0,110,0,
4439110,0,97,0,114, 519699,0,114,0,101,
44400,121,0,69,0, 51970,109,0,101,0,
4441120,0,112,0,114, 5198110,0,116,0,68,
44420,101,0,115,0,
4443115,0,105,0,111,
44440,110,0,95,0,
444551,0,1,247,1,
44463,1,4,1,3,
44471215,22,1,107,1,
4448525,1216,17,1217,15,
44491218,4,34,37,0,
445082,0,111,0,116,
44510,97,0,116,0,
4452105,0,111,0,110,
44530,67,0,111,0,
4454110,0,115,0,116,
44550,97,0,110,0,
4456116,0,1,-1,1,
44575,1219,20,1220,4,
445836,82,0,111,0,
4459116,0,97,0,116,
44600,105,0,111,0,
4461110,0,67,0,111,
44620,110,0,115,0,
4463116,0,97,0,110,
44640,116,0,95,0,
446549,0,1,232,1,
44663,1,10,1,9,
44671221,22,1,92,1,
446863,1222,17,1223,15,
44691224,4,38,37,0,
447084,0,121,0,112,
44710,101,0,99,0,
447297,0,115,0,116,
44730,69,0,120,0,
4474112,0,114,0,101,
44750,115,0,115,0,
4476105,0,111,0,110,
44770,1,-1,1,5,
44781225,20,1226,4,40,
447984,0,121,0,112,
44800,101,0,99,0, 51990,101,0,99,0,
448197,0,115,0,116, 5200114,0,101,0,109,
52010,101,0,110,0,
5202116,0,69,0,120,
52030,112,0,114,0,
5204101,0,115,0,115,
52050,105,0,111,0,
5206110,0,95,0,49,
52070,1,291,1,3,
52081,3,1,2,1333,
520922,1,127,1,305,
52101334,17,1335,15,1243,
52111,-1,1,5,1336,
521220,1337,4,36,66,
52130,105,0,110,0,
521497,0,114,0,121,
44820,69,0,120,0, 52150,69,0,120,0,
4483112,0,114,0,101, 5216112,0,114,0,101,
44840,115,0,115,0, 52170,115,0,115,0,
4485105,0,111,0,110, 5218105,0,111,0,110,
44860,95,0,50,0, 52190,95,0,51,0,
44871,269,1,3,1, 52201,302,1,3,1,
44885,1,4,1227,22, 52214,1,3,1338,22,
44891,129,1,66,1228, 52221,138,1,525,1339,
449017,1229,15,1224,1, 522317,1340,15,1341,4,
4491-1,1,5,1230,20, 522434,37,0,82,0,
44921231,4,40,84,0, 5225111,0,116,0,97,
52260,116,0,105,0,
5227111,0,110,0,67,
52280,111,0,110,0,
5229115,0,116,0,97,
52300,110,0,116,0,
52311,-1,1,5,1342,
523220,1343,4,36,82,
52330,111,0,116,0,
523497,0,116,0,105,
52350,111,0,110,0,
523667,0,111,0,110,
52370,115,0,116,0,
523897,0,110,0,116,
52390,95,0,49,0,
52401,287,1,3,1,
524110,1,9,1344,22,
52421,123,1,63,1345,
524317,1346,15,1347,4,
524438,37,0,84,0,
5245121,0,112,0,101,
52460,99,0,97,0,
5247115,0,116,0,69,
52480,120,0,112,0,
5249114,0,101,0,115,
52500,115,0,105,0,
5251111,0,110,0,1,
5252-1,1,5,1348,20,
52531349,4,40,84,0,
4493121,0,112,0,101, 5254121,0,112,0,101,
44940,99,0,97,0, 52550,99,0,97,0,
4495115,0,116,0,69, 5256115,0,116,0,69,
@@ -4497,12 +5258,12 @@ public yyLSLSyntax
4497114,0,101,0,115, 5258114,0,101,0,115,
44980,115,0,105,0, 52590,115,0,105,0,
4499111,0,110,0,95, 5260111,0,110,0,95,
45000,51,0,1,270, 52610,50,0,1,324,
45011,3,1,7,1, 52621,3,1,5,1,
45026,1232,22,1,130, 52634,1350,22,1,160,
45031,67,1233,17,1234, 52641,66,1351,17,1352,
450415,1224,1,-1,1, 526515,1347,1,-1,1,
45055,1235,20,1236,4, 52665,1353,20,1354,4,
450640,84,0,121,0, 526740,84,0,121,0,
4507112,0,101,0,99, 5268112,0,101,0,99,
45080,97,0,115,0, 52690,97,0,115,0,
@@ -4510,13 +5271,13 @@ public yyLSLSyntax
45100,112,0,114,0, 52710,112,0,114,0,
4511101,0,115,0,115, 5272101,0,115,0,115,
45120,105,0,111,0, 52730,105,0,111,0,
4513110,0,95,0,55, 5274110,0,95,0,51,
45140,1,274,1,3, 52750,1,325,1,3,
45151,8,1,7,1237, 52761,7,1,6,1355,
451622,1,134,1,68, 527722,1,161,1,67,
45171238,17,1239,15,1224, 52781356,17,1357,15,1347,
45181,-1,1,5,1240, 52791,-1,1,5,1358,
451920,1241,4,40,84, 528020,1359,4,40,84,
45200,121,0,112,0, 52810,121,0,112,0,
4521101,0,99,0,97, 5282101,0,99,0,97,
45220,115,0,116,0, 52830,115,0,116,0,
@@ -4524,12 +5285,12 @@ public yyLSLSyntax
45240,114,0,101,0, 52850,114,0,101,0,
4525115,0,115,0,105, 5286115,0,115,0,105,
45260,111,0,110,0, 52870,111,0,110,0,
452795,0,53,0,1, 528895,0,55,0,1,
4528272,1,3,1,8, 5289329,1,3,1,8,
45291,7,1242,22,1, 52901,7,1360,22,1,
4530132,1,69,1243,17, 5291165,1,68,1361,17,
45311244,15,1224,1,-1, 52921362,15,1347,1,-1,
45321,5,1245,20,1246, 52931,5,1363,20,1364,
45334,40,84,0,121, 52944,40,84,0,121,
45340,112,0,101,0, 52950,112,0,101,0,
453599,0,97,0,115, 529699,0,97,0,115,
@@ -4538,12 +5299,12 @@ public yyLSLSyntax
45380,101,0,115,0, 52990,101,0,115,0,
4539115,0,105,0,111, 5300115,0,105,0,111,
45400,110,0,95,0, 53010,110,0,95,0,
454154,0,1,273,1, 530253,0,1,327,1,
45423,1,6,1,5, 53033,1,8,1,7,
45431247,22,1,133,1, 53041365,22,1,163,1,
454470,1248,17,1249,15, 530569,1366,17,1367,15,
45451224,1,-1,1,5, 53061347,1,-1,1,5,
45461250,20,1251,4,40, 53071368,20,1369,4,40,
454784,0,121,0,112, 530884,0,121,0,112,
45480,101,0,99,0, 53090,101,0,99,0,
454997,0,115,0,116, 531097,0,115,0,116,
@@ -4551,13 +5312,13 @@ public yyLSLSyntax
4551112,0,114,0,101, 5312112,0,114,0,101,
45520,115,0,115,0, 53130,115,0,115,0,
4553105,0,111,0,110, 5314105,0,111,0,110,
45540,95,0,52,0, 53150,95,0,54,0,
45551,271,1,3,1, 53161,328,1,3,1,
45566,1,5,1252,22, 53176,1,5,1370,22,
45571,131,1,74,1253, 53181,164,1,70,1371,
455817,1254,15,1224,1, 531917,1372,15,1347,1,
4559-1,1,5,1255,20, 5320-1,1,5,1373,20,
45601256,4,40,84,0, 53211374,4,40,84,0,
4561121,0,112,0,101, 5322121,0,112,0,101,
45620,99,0,97,0, 53230,99,0,97,0,
4563115,0,116,0,69, 5324115,0,116,0,69,
@@ -4565,265 +5326,204 @@ public yyLSLSyntax
4565114,0,101,0,115, 5326114,0,101,0,115,
45660,115,0,105,0, 53270,115,0,105,0,
4567111,0,110,0,95, 5328111,0,110,0,95,
45680,57,0,1,276, 53290,52,0,1,326,
45691,3,1,7,1,
45706,1257,22,1,136,
45711,1013,1258,17,1259,
457215,1104,1,-1,1,
45735,1260,20,1261,4,
457446,80,0,97,0,
4575114,0,101,0,110,
45760,116,0,104,0,
4577101,0,115,0,105,
45780,115,0,69,0,
4579120,0,112,0,114,
45800,101,0,115,0,
4581115,0,105,0,111,
45820,110,0,95,0,
458349,0,1,266,1,
45843,1,4,1,3,
45851262,22,1,126,1,
45861332,1263,17,1264,15,
45871098,1,-1,1,5,
45881265,20,1266,4,38,
458983,0,105,0,109,
45900,112,0,108,0,
4591101,0,65,0,115,
45920,115,0,105,0,
4593103,0,110,0,109,
45940,101,0,110,0,
4595116,0,95,0,49,
45960,57,0,1,218,
45971,3,1,6,1, 53301,3,1,6,1,
45985,1267,22,1,78, 53315,1375,22,1,162,
45991,2337,1268,17,1142, 53321,74,1376,17,1377,
46001,0,1146,1,1585, 533315,1347,1,-1,1,
46011269,17,1270,15,1271, 53345,1378,20,1379,4,
46024,32,37,0,82, 533540,84,0,121,0,
46030,101,0,116,0, 5336112,0,101,0,99,
4604117,0,114,0,110, 53370,97,0,115,0,
46050,83,0,116,0, 5338116,0,69,0,120,
460697,0,116,0,101,
46070,109,0,101,0,
4608110,0,116,0,1,
4609-1,1,5,1272,20,
46101273,4,34,82,0,
4611101,0,116,0,117,
46120,114,0,110,0,
461383,0,116,0,97,
46140,116,0,101,0,
4615109,0,101,0,110,
46160,116,0,95,0,
461750,0,1,225,1,
46183,1,2,1,1,
46191274,22,1,85,1,
46202023,1275,17,1276,15,
46211137,1,-1,1,5,
46221277,20,1278,4,26,
462383,0,116,0,97,
46240,116,0,101,0,
462567,0,104,0,97,
46260,110,0,103,0,
4627101,0,95,0,50,
46280,1,183,1,3,
46291,3,1,2,1279,
463022,1,43,1,2136,
4631842,1,82,1280,17,
46321281,15,1282,4,32,
463337,0,85,0,110,
46340,97,0,114,0,
4635121,0,69,0,120,
46360,112,0,114,0, 53390,112,0,114,0,
4637101,0,115,0,115, 5340101,0,115,0,115,
46380,105,0,111,0, 53410,105,0,111,0,
4639110,0,1,-1,1, 5342110,0,95,0,57,
46405,1283,20,1284,4, 53430,1,331,1,3,
464134,85,0,110,0, 53441,7,1,6,1380,
464297,0,114,0,121, 534522,1,167,1,1013,
53461381,17,1382,15,1226,
53471,-1,1,5,1383,
534820,1384,4,46,80,
53490,97,0,114,0,
5350101,0,110,0,116,
53510,104,0,101,0,
5352115,0,105,0,115,
46430,69,0,120,0, 53530,69,0,120,0,
4644112,0,114,0,101, 5354112,0,114,0,101,
46450,115,0,115,0, 53550,115,0,115,0,
4646105,0,111,0,110, 5356105,0,111,0,110,
46470,95,0,51,0,
46481,265,1,3,1,
46493,1,2,1285,22,
46501,125,1,2026,1286,
465117,1287,15,1288,4,
465228,37,0,74,0,
4653117,0,109,0,112,
46540,83,0,116,0,
465597,0,116,0,101,
46560,109,0,101,0,
4657110,0,116,0,1,
4658-1,1,5,1289,20,
46591290,4,30,74,0,
4660117,0,109,0,112,
46610,83,0,116,0,
466297,0,116,0,101,
46630,109,0,101,0,
4664110,0,116,0,95,
46650,49,0,1,181,
46661,3,1,3,1,
46672,1291,22,1,41,
46681,1591,1292,17,1293,
466915,1271,1,-1,1,
46705,1294,20,1295,4,
467134,82,0,101,0,
4672116,0,117,0,114,
46730,110,0,83,0,
4674116,0,97,0,116,
46750,101,0,109,0,
4676101,0,110,0,116,
46770,95,0,49,0, 53570,95,0,49,0,
46781,224,1,3,1, 53581,321,1,3,1,
46793,1,2,1296,22, 53594,1,3,1385,22,
46801,84,1,1341,1297, 53601,157,1,1332,1386,
468117,1298,15,1098,1, 536117,1387,15,1220,1,
4682-1,1,5,1299,20, 5362-1,1,5,1388,20,
46831300,4,36,83,0, 53631389,4,38,83,0,
4684105,0,109,0,112, 5364105,0,109,0,112,
46850,108,0,101,0, 53650,108,0,101,0,
468665,0,115,0,115, 536665,0,115,0,115,
46870,105,0,103,0, 53670,105,0,103,0,
4688110,0,109,0,101, 5368110,0,109,0,101,
46890,110,0,116,0, 53690,110,0,116,0,
469095,0,54,0,1, 537095,0,49,0,57,
4691205,1,3,1,4, 53710,1,273,1,3,
46921,3,1301,22,1, 53721,6,1,5,1390,
469365,1,2030,731,1, 537322,1,109,1,2337,
4694328,1302,17,1303,15, 53741391,17,1264,1,0,
46951121,1,-1,1,5, 53751268,1,1585,1392,17,
46961304,20,1305,4,36, 53761393,15,1394,4,32,
469766,0,105,0,110, 537737,0,82,0,101,
46980,97,0,114,0, 53780,116,0,117,0,
4699121,0,69,0,120, 5379114,0,110,0,83,
47000,112,0,114,0, 53800,116,0,97,0,
4701101,0,115,0,115, 5381116,0,101,0,109,
47020,105,0,111,0, 53820,101,0,110,0,
4703110,0,95,0,50, 5383116,0,1,-1,1,
47040,1,246,1,3, 53845,1395,20,1396,4,
47051,4,1,3,1306, 538534,82,0,101,0,
470622,1,106,1,1303, 5386116,0,117,0,114,
47071307,17,1308,15,1098, 53870,110,0,83,0,
47081,-1,1,5,1309, 5388116,0,97,0,116,
470920,1310,4,36,83, 53890,101,0,109,0,
47100,105,0,109,0,
4711112,0,108,0,101,
47120,65,0,115,0,
4713115,0,105,0,103,
47140,110,0,109,0,
4715101,0,110,0,116,
47160,95,0,55,0,
47171,206,1,3,1,
47186,1,5,1311,22,
47191,66,1,1096,1312,
472017,1313,15,1314,4,
472126,37,0,70,0,
4722117,0,110,0,99,
47230,116,0,105,0,
4724111,0,110,0,67,
47250,97,0,108,0,
4726108,0,1,-1,1,
47275,1315,20,1316,4,
472828,70,0,117,0,
4729110,0,99,0,116,
47300,105,0,111,0,
4731110,0,67,0,97,
47320,108,0,108,0,
473395,0,49,0,1,
4734277,1,3,1,5,
47351,4,1317,22,1,
4736137,1,93,1318,17,
47371319,15,1282,1,-1,
47381,5,1320,20,1321,
47394,34,85,0,110,
47400,97,0,114,0,
4741121,0,69,0,120,
47420,112,0,114,0,
4743101,0,115,0,115,
47440,105,0,111,0,
4745110,0,95,0,50,
47460,1,264,1,3,
47471,3,1,2,1322,
474822,1,124,1,1550,
47491323,17,1324,15,1098,
47501,-1,1,5,1325,
475120,1326,4,38,83,
47520,105,0,109,0,
4753112,0,108,0,101,
47540,65,0,115,0,
4755115,0,105,0,103,
47560,110,0,109,0,
4757101,0,110,0,116, 5390101,0,110,0,116,
47580,95,0,49,0, 53910,95,0,50,0,
475951,0,1,212,1, 53921,280,1,3,1,
53932,1,1,1397,22,
53941,116,1,2023,1398,
539517,1399,15,1259,1,
5396-1,1,5,1400,20,
53971401,4,26,83,0,
5398116,0,97,0,116,
53990,101,0,67,0,
5400104,0,97,0,110,
54010,103,0,101,0,
540295,0,50,0,1,
5403238,1,3,1,3,
54041,2,1402,22,1,
540574,1,2136,965,1,
540682,1403,17,1404,15,
54071405,4,32,37,0,
540885,0,110,0,97,
54090,114,0,121,0,
541069,0,120,0,112,
54110,114,0,101,0,
5412115,0,115,0,105,
54130,111,0,110,0,
54141,-1,1,5,1406,
541520,1407,4,34,85,
54160,110,0,97,0,
5417114,0,121,0,69,
54180,120,0,112,0,
5419114,0,101,0,115,
54200,115,0,105,0,
5421111,0,110,0,95,
54220,51,0,1,320,
54231,3,1,3,1,
54242,1408,22,1,156,
54251,2026,1409,17,1410,
542615,1411,4,28,37,
54270,74,0,117,0,
5428109,0,112,0,83,
54290,116,0,97,0,
5430116,0,101,0,109,
54310,101,0,110,0,
5432116,0,1,-1,1,
54335,1412,20,1413,4,
543430,74,0,117,0,
5435109,0,112,0,83,
54360,116,0,97,0,
5437116,0,101,0,109,
54380,101,0,110,0,
5439116,0,95,0,49,
54400,1,236,1,3,
54411,3,1,2,1414,
544222,1,72,1,1591,
54431415,17,1416,15,1394,
54441,-1,1,5,1417,
544520,1418,4,34,82,
54460,101,0,116,0,
5447117,0,114,0,110,
54480,83,0,116,0,
544997,0,116,0,101,
54500,109,0,101,0,
5451110,0,116,0,95,
54520,49,0,1,279,
54531,3,1,3,1,
54542,1419,22,1,115,
54551,1341,1420,17,1421,
545615,1220,1,-1,1,
54575,1422,20,1423,4,
545836,83,0,105,0,
5459109,0,112,0,108,
54600,101,0,65,0,
5461115,0,115,0,105,
54620,103,0,110,0,
5463109,0,101,0,110,
54640,116,0,95,0,
546554,0,1,260,1,
47603,1,4,1,3, 54663,1,4,1,3,
47611327,22,1,72,1, 54671424,22,1,96,1,
47622040,1328,16,0,532, 54682030,853,1,328,1425,
47631,2106,1329,17,1142, 546917,1426,15,1243,1,
47641,0,1146,1,1555, 5470-1,1,5,1427,20,
47651330,16,0,599,1, 54711428,4,36,66,0,
4766827,1331,17,1332,15,
47671121,1,-1,1,5,
47681333,20,1334,4,38,
476966,0,105,0,110,
47700,97,0,114,0,
4771121,0,69,0,120,
47720,112,0,114,0,
4773101,0,115,0,115,
47740,105,0,111,0,
4775110,0,95,0,49,
47760,53,0,1,259,
47771,3,1,4,1,
47783,1335,22,1,119,
47791,1859,1336,16,0,
4780304,1,1860,821,1,
47811804,1337,17,1142,1,
47820,1146,1,107,1338,
478317,1339,15,1282,1,
4784-1,1,5,1340,20,
47851341,4,34,85,0,
4786110,0,97,0,114,
47870,121,0,69,0,
4788120,0,112,0,114,
47890,101,0,115,0,
4790115,0,105,0,111,
47910,110,0,95,0,
479249,0,1,263,1,
47933,1,3,1,2,
47941342,22,1,123,1,
47951114,1343,17,1185,1,
47963,1189,1,1048,1344,
479717,1345,15,1121,1,
4798-1,1,5,1346,20,
47991347,4,38,66,0,
4800105,0,110,0,97, 5472105,0,110,0,97,
48010,114,0,121,0, 54730,114,0,121,0,
480269,0,120,0,112, 547469,0,120,0,112,
48030,114,0,101,0, 54750,114,0,101,0,
4804115,0,115,0,105, 5476115,0,115,0,105,
48050,111,0,110,0, 54770,111,0,110,0,
480695,0,49,0,56, 547895,0,50,0,1,
48070,1,262,1,3, 5479301,1,3,1,4,
48081,4,1,3,1348, 54801,3,1429,22,1,
480922,1,122,1,352, 5481137,1,1303,1430,17,
48101349,17,1350,15,1121, 54821431,15,1220,1,-1,
48111,-1,1,5,1351, 54831,5,1432,20,1433,
481220,1352,4,36,66, 54844,36,83,0,105,
48130,105,0,110,0, 54850,109,0,112,0,
481497,0,114,0,121, 5486108,0,101,0,65,
48150,69,0,120,0,
4816112,0,114,0,101,
48170,115,0,115,0, 54870,115,0,115,0,
4818105,0,111,0,110, 5488105,0,103,0,110,
48190,95,0,49,0, 54890,109,0,101,0,
48201,245,1,3,1, 5490110,0,116,0,95,
48214,1,3,1353,22, 54910,55,0,1,261,
48221,105,1,1872,1354, 54921,3,1,6,1,
482316,0,314,1,1873, 54935,1434,22,1,97,
4824835,1,118,1355,17, 54941,2035,874,1,93,
48251356,15,1121,1,-1, 54951435,17,1436,15,1405,
48261,5,1357,20,1358, 54961,-1,1,5,1437,
549720,1438,4,34,85,
54980,110,0,97,0,
5499114,0,121,0,69,
55000,120,0,112,0,
5501114,0,101,0,115,
55020,115,0,105,0,
5503111,0,110,0,95,
55040,50,0,1,319,
55051,3,1,3,1,
55062,1439,22,1,155,
55071,1550,1440,17,1441,
550815,1220,1,-1,1,
55095,1442,20,1443,4,
551038,83,0,105,0,
5511109,0,112,0,108,
55120,101,0,65,0,
5513115,0,115,0,105,
55140,103,0,110,0,
5515109,0,101,0,110,
55160,116,0,95,0,
551749,0,51,0,1,
5518267,1,3,1,4,
55191,3,1444,22,1,
5520103,1,2040,1445,16,
55210,610,1,2106,1446,
552217,1264,1,0,1268,
55231,1555,1447,16,0,
5524707,1,827,1448,17,
55251449,15,1243,1,-1,
55261,5,1450,20,1451,
48274,38,66,0,105, 55274,38,66,0,105,
48280,110,0,97,0, 55280,110,0,97,0,
4829114,0,121,0,69, 5529114,0,121,0,69,
@@ -4831,36 +5531,85 @@ public yyLSLSyntax
4831114,0,101,0,115, 5531114,0,101,0,115,
48320,115,0,105,0, 55320,115,0,105,0,
4833111,0,110,0,95, 5533111,0,110,0,95,
48340,49,0,52,0, 55340,49,0,53,0,
48351,258,1,3,1, 55351,314,1,3,1,
48364,1,3,1359,22, 55364,1,3,1452,22,
48371,118,1,1123,1360, 55371,150,1,1859,1453,
483817,1361,15,1098,1, 553816,0,339,1,1860,
4839-1,1,5,1362,20, 5539943,1,1804,1454,17,
48401363,4,38,83,0, 55401264,1,0,1268,1,
4841105,0,109,0,112, 5541107,1455,17,1456,15,
48420,108,0,101,0, 55421405,1,-1,1,5,
484365,0,115,0,115, 55431457,20,1458,4,34,
48440,105,0,103,0, 554485,0,110,0,97,
4845110,0,109,0,101, 55450,114,0,121,0,
48460,110,0,116,0, 554669,0,120,0,112,
484795,0,49,0,50, 55470,114,0,101,0,
48480,1,211,1,3, 5548115,0,115,0,105,
48491,6,1,5,1364,
485022,1,71,1,371,
48511365,17,1366,15,1367,
48524,46,37,0,70,
48530,117,0,110,0,
485499,0,116,0,105,
48550,111,0,110,0, 55490,111,0,110,0,
485667,0,97,0,108, 555095,0,49,0,1,
48570,108,0,69,0, 5551318,1,3,1,3,
55521,2,1459,22,1,
5553154,1,2781,1460,16,
55540,278,1,1114,1461,
555517,1308,1,3,1312,
55561,1048,1462,17,1463,
555715,1243,1,-1,1,
55585,1464,20,1465,4,
555938,66,0,105,0,
5560110,0,97,0,114,
55610,121,0,69,0,
4858120,0,112,0,114, 5562120,0,112,0,114,
48590,101,0,115,0, 55630,101,0,115,0,
4860115,0,105,0,111, 5564115,0,105,0,111,
48610,110,0,1,-1, 55650,110,0,95,0,
48621,5,1368,20,1369, 556649,0,56,0,1,
48634,48,70,0,117, 5567317,1,3,1,4,
55681,3,1466,22,1,
5569153,1,352,1467,17,
55701468,15,1243,1,-1,
55711,5,1469,20,1470,
55724,36,66,0,105,
55730,110,0,97,0,
5574114,0,121,0,69,
55750,120,0,112,0,
5576114,0,101,0,115,
55770,115,0,105,0,
5578111,0,110,0,95,
55790,49,0,1,300,
55801,3,1,4,1,
55813,1471,22,1,136,
55821,1872,1472,16,0,
5583349,1,1873,958,1,
5584118,1473,17,1474,15,
55851243,1,-1,1,5,
55861475,20,1476,4,38,
558766,0,105,0,110,
55880,97,0,114,0,
5589121,0,69,0,120,
55900,112,0,114,0,
5591101,0,115,0,115,
55920,105,0,111,0,
5593110,0,95,0,49,
55940,52,0,1,313,
55951,3,1,4,1,
55963,1477,22,1,149,
55971,1123,1478,17,1479,
559815,1220,1,-1,1,
55995,1480,20,1481,4,
560038,83,0,105,0,
5601109,0,112,0,108,
56020,101,0,65,0,
5603115,0,115,0,105,
56040,103,0,110,0,
5605109,0,101,0,110,
56060,116,0,95,0,
560749,0,50,0,1,
5608266,1,3,1,6,
56091,5,1482,22,1,
5610102,1,371,1483,17,
56111484,15,1485,4,46,
561237,0,70,0,117,
48640,110,0,99,0, 56130,110,0,99,0,
4865116,0,105,0,111, 5614116,0,105,0,111,
48660,110,0,67,0, 56150,110,0,67,0,
@@ -4869,43 +5618,36 @@ public yyLSLSyntax
4869112,0,114,0,101, 5618112,0,114,0,101,
48700,115,0,115,0, 56190,115,0,115,0,
4871105,0,111,0,110, 5620105,0,111,0,110,
48720,95,0,49,0, 56210,1,-1,1,5,
48731,244,1,3,1, 56221486,20,1487,4,48,
48742,1,1,1370,22, 562370,0,117,0,110,
48751,104,1,1377,1371, 56240,99,0,116,0,
487617,1372,15,1098,1, 5625105,0,111,0,110,
4877-1,1,5,1373,20, 56260,67,0,97,0,
48781374,4,36,83,0, 5627108,0,108,0,69,
4879105,0,109,0,112, 56280,120,0,112,0,
48800,108,0,101,0, 5629114,0,101,0,115,
488165,0,115,0,115, 56300,115,0,105,0,
48820,105,0,103,0, 5631111,0,110,0,95,
4883110,0,109,0,101, 56320,49,0,1,299,
48840,110,0,116,0, 56331,3,1,2,1,
488595,0,53,0,1, 56341,1488,22,1,135,
4886204,1,3,1,4, 56351,1377,1489,17,1490,
48871,3,1375,22,1, 563615,1220,1,-1,1,
488864,1,375,1376,17, 56375,1491,20,1492,4,
48891377,15,1192,1,-1, 563836,83,0,105,0,
48901,5,1378,20,1379, 5639109,0,112,0,108,
48914,60,73,0,110, 56400,101,0,65,0,
48920,99,0,114,0, 5641115,0,115,0,105,
4893101,0,109,0,101, 56420,103,0,110,0,
48940,110,0,116,0,
489568,0,101,0,99,
48960,114,0,101,0,
4897109,0,101,0,110, 5643109,0,101,0,110,
48980,116,0,69,0, 56440,116,0,95,0,
4899120,0,112,0,114, 564553,0,1,259,1,
49000,101,0,115,0, 56463,1,4,1,3,
4901115,0,105,0,111, 56471493,22,1,95,1,
49020,110,0,95,0, 5648375,1494,17,1495,15,
490356,0,1,243,1, 56491315,1,-1,1,5,
49043,1,5,1,4, 56501496,20,1497,4,60,
49051380,22,1,103,1,
4906377,1381,17,1382,15,
49071192,1,-1,1,5,
49081383,20,1384,4,60,
490973,0,110,0,99, 565173,0,110,0,99,
49100,114,0,101,0, 56520,114,0,101,0,
4911109,0,101,0,110, 5653109,0,101,0,110,
@@ -4917,13 +5659,13 @@ public yyLSLSyntax
4917112,0,114,0,101, 5659112,0,114,0,101,
49180,115,0,115,0, 56600,115,0,115,0,
4919105,0,111,0,110, 5661105,0,111,0,110,
49200,95,0,53,0, 56620,95,0,56,0,
49211,240,1,3,1, 56631,298,1,3,1,
49223,1,2,1385,22, 56645,1,4,1498,22,
49231,100,1,379,1386, 56651,134,1,377,1499,
492417,1387,15,1192,1, 566617,1500,15,1315,1,
4925-1,1,5,1388,20, 5667-1,1,5,1501,20,
49261389,4,60,73,0, 56681502,4,60,73,0,
4927110,0,99,0,114, 5669110,0,99,0,114,
49280,101,0,109,0, 56700,101,0,109,0,
4929101,0,110,0,116, 5671101,0,110,0,116,
@@ -4935,81 +5677,51 @@ public yyLSLSyntax
4935114,0,101,0,115, 5677114,0,101,0,115,
49360,115,0,105,0, 56780,115,0,105,0,
4937111,0,110,0,95, 5679111,0,110,0,95,
49380,55,0,1,242, 56800,53,0,1,295,
49391,3,1,5,1, 56811,3,1,3,1,
49404,1390,22,1,102, 56822,1503,22,1,131,
49411,380,1391,17,1392, 56831,379,1504,17,1505,
494215,1393,4,38,37, 568415,1315,1,-1,1,
49430,67,0,111,0, 56855,1506,20,1507,4,
4944110,0,115,0,116, 568660,73,0,110,0,
49450,97,0,110,0, 568799,0,114,0,101,
4946116,0,69,0,120, 56880,109,0,101,0,
49470,112,0,114,0, 5689110,0,116,0,68,
4948101,0,115,0,115, 56900,101,0,99,0,
49490,105,0,111,0, 5691114,0,101,0,109,
4950110,0,1,-1,1, 56920,101,0,110,0,
49515,1394,20,1395,4,
495240,67,0,111,0,
4953110,0,115,0,116,
49540,97,0,110,0,
4955116,0,69,0,120, 5693116,0,69,0,120,
49560,112,0,114,0, 56940,112,0,114,0,
4957101,0,115,0,115, 5695101,0,115,0,115,
49580,105,0,111,0, 56960,105,0,111,0,
4959110,0,95,0,49, 5697110,0,95,0,55,
49600,1,233,1,3, 56980,1,297,1,3,
49611,2,1,1,1396, 56991,5,1,4,1508,
496222,1,93,1,883, 570022,1,133,1,380,
49631397,17,1398,15,1121, 57011509,17,1510,15,1511,
49641,-1,1,5,1399, 57024,38,37,0,67,
496520,1400,4,38,66, 57030,111,0,110,0,
49660,105,0,110,0, 5704115,0,116,0,97,
496797,0,114,0,121,
49680,69,0,120,0,
4969112,0,114,0,101,
49700,115,0,115,0,
4971105,0,111,0,110,
49720,95,0,49,0,
497354,0,1,260,1,
49743,1,4,1,3,
49751401,22,1,120,1,
49761628,1402,17,1403,15,
49771404,4,22,37,0,
497865,0,115,0,115,
49790,105,0,103,0,
4980110,0,109,0,101,
49810,110,0,116,0, 57050,110,0,116,0,
49821,-1,1,5,1405, 570669,0,120,0,112,
498320,1406,4,24,65, 57070,114,0,101,0,
49840,115,0,115,0, 5708115,0,115,0,105,
4985105,0,103,0,110, 57090,111,0,110,0,
49860,109,0,101,0, 57101,-1,1,5,1512,
4987110,0,116,0,95, 571120,1513,4,40,67,
49880,49,0,1,198, 57120,111,0,110,0,
49891,3,1,4,1, 5713115,0,116,0,97,
49903,1407,22,1,58,
49911,2075,1408,17,1142,
49921,0,1146,1,373,
49931409,17,1410,15,1192,
49941,-1,1,5,1411,
499520,1412,4,60,73,
49960,110,0,99,0,
4997114,0,101,0,109,
49980,101,0,110,0,
4999116,0,68,0,101,
50000,99,0,114,0,
5001101,0,109,0,101,
50020,110,0,116,0, 57140,110,0,116,0,
500369,0,120,0,112, 571569,0,120,0,112,
50040,114,0,101,0, 57160,114,0,101,0,
5005115,0,115,0,105, 5717115,0,115,0,105,
50060,111,0,110,0, 57180,111,0,110,0,
500795,0,54,0,1, 571995,0,49,0,1,
5008241,1,3,1,3, 5720288,1,3,1,2,
50091,2,1413,22,1, 57211,1,1514,22,1,
5010101,1,130,1414,17, 5722124,1,883,1515,17,
50111415,15,1121,1,-1, 57231516,15,1243,1,-1,
50121,5,1416,20,1417, 57241,5,1517,20,1518,
50134,38,66,0,105, 57254,38,66,0,105,
50140,110,0,97,0, 57260,110,0,97,0,
5015114,0,121,0,69, 5727114,0,121,0,69,
@@ -5017,71 +5729,47 @@ public yyLSLSyntax
5017114,0,101,0,115, 5729114,0,101,0,115,
50180,115,0,105,0, 57300,115,0,105,0,
5019111,0,110,0,95, 5731111,0,110,0,95,
50200,49,0,51,0, 57320,49,0,54,0,
50211,257,1,3,1, 57331,315,1,3,1,
50224,1,3,1418,22, 57344,1,3,1519,22,
50231,117,1,143,1419, 57351,151,1,1628,1520,
502417,1420,15,1121,1, 573617,1521,15,1522,4,
5025-1,1,5,1421,20, 573722,37,0,65,0,
50261422,4,38,66,0,
5027105,0,110,0,97,
50280,114,0,121,0,
502969,0,120,0,112,
50300,114,0,101,0,
5031115,0,115,0,105, 5738115,0,115,0,105,
50320,111,0,110,0, 57390,103,0,110,0,
503395,0,49,0,50, 5740109,0,101,0,110,
50340,1,256,1,3, 57410,116,0,1,-1,
50351,4,1,3,1423, 57421,5,1523,20,1524,
503622,1,116,1,1901, 57434,24,65,0,115,
50371424,17,1142,1,0, 57440,115,0,105,0,
50381146,1,2657,1425,16, 5745103,0,110,0,109,
50390,608,1,1152,1426, 57460,101,0,110,0,
504017,1427,15,1098,1, 5747116,0,95,0,49,
5041-1,1,5,1428,20, 57480,1,253,1,3,
50421429,4,38,83,0, 57491,4,1,3,1525,
5043105,0,109,0,112, 575022,1,89,1,2075,
50440,108,0,101,0, 57511526,17,1264,1,0,
504565,0,115,0,115, 57521268,1,373,1527,17,
50460,105,0,103,0, 57531528,15,1315,1,-1,
5047110,0,109,0,101, 57541,5,1529,20,1530,
57554,60,73,0,110,
57560,99,0,114,0,
5757101,0,109,0,101,
50480,110,0,116,0, 57580,110,0,116,0,
504995,0,50,0,52, 575968,0,101,0,99,
50500,1,223,1,3, 57600,114,0,101,0,
50511,6,1,5,1430, 5761109,0,101,0,110,
505222,1,83,1,1406, 57620,116,0,69,0,
50531431,17,1432,15,1098, 5763120,0,112,0,114,
50541,-1,1,5,1433, 57640,101,0,115,0,
505520,1434,4,38,83, 5765115,0,105,0,111,
50560,105,0,109,0, 57660,110,0,95,0,
5057112,0,108,0,101, 576754,0,1,296,1,
50580,65,0,115,0, 57683,1,3,1,2,
5059115,0,105,0,103, 57691531,22,1,132,1,
50600,110,0,109,0, 5770130,1532,17,1533,15,
5061101,0,110,0,116, 57711243,1,-1,1,5,
50620,95,0,49,0, 57721534,20,1535,4,38,
506355,0,1,216,1,
50643,1,4,1,3,
50651435,22,1,76,1,
50661659,1436,16,0,269,
50671,2413,1437,17,1142,
50681,0,1146,1,1159,
50691438,17,1439,15,1098,
50701,-1,1,5,1440,
507120,1441,4,38,83,
50720,105,0,109,0,
5073112,0,108,0,101,
50740,65,0,115,0,
5075115,0,105,0,103,
50760,110,0,109,0,
5077101,0,110,0,116,
50780,95,0,49,0,
507949,0,1,210,1,
50803,1,6,1,5,
50811442,22,1,70,1,
5082157,1443,17,1444,15,
50831121,1,-1,1,5,
50841445,20,1446,4,38,
508566,0,105,0,110, 577366,0,105,0,110,
50860,97,0,114,0, 57740,97,0,114,0,
5087121,0,69,0,120, 5775121,0,69,0,120,
@@ -5089,38 +5777,40 @@ public yyLSLSyntax
5089101,0,115,0,115, 5777101,0,115,0,115,
50900,105,0,111,0, 57780,105,0,111,0,
5091110,0,95,0,49, 5779110,0,95,0,49,
50920,49,0,1,255, 57800,51,0,1,312,
50931,3,1,4,1, 57811,3,1,4,1,
50943,1447,22,1,115, 57823,1536,22,1,148,
50951,1413,1448,17,1449, 57831,143,1537,17,1538,
509615,1098,1,-1,1, 578415,1243,1,-1,1,
50975,1450,20,1451,4, 57855,1539,20,1540,4,
509836,83,0,105,0, 578638,66,0,105,0,
5099109,0,112,0,108, 5787110,0,97,0,114,
51000,101,0,65,0, 57880,121,0,69,0,
5101115,0,115,0,105, 5789120,0,112,0,114,
51020,103,0,110,0, 57900,101,0,115,0,
5103109,0,101,0,110, 5791115,0,105,0,111,
51040,116,0,95,0, 57920,110,0,95,0,
510552,0,1,203,1, 579349,0,50,0,1,
51063,1,4,1,3, 5794311,1,3,1,4,
51071452,22,1,63,1, 57951,3,1541,22,1,
51081370,1453,17,1454,15, 5796147,1,1901,1542,17,
51091098,1,-1,1,5, 57971264,1,0,1268,1,
51101455,20,1456,4,38, 57981152,1543,17,1544,15,
57991220,1,-1,1,5,
58001545,20,1546,4,38,
511183,0,105,0,109, 580183,0,105,0,109,
51120,112,0,108,0, 58020,112,0,108,0,
5113101,0,65,0,115, 5803101,0,65,0,115,
51140,115,0,105,0, 58040,115,0,105,0,
5115103,0,110,0,109, 5805103,0,110,0,109,
51160,101,0,110,0, 58060,101,0,110,0,
5117116,0,95,0,49, 5807116,0,95,0,50,
51180,56,0,1,217, 58080,52,0,1,278,
51191,3,1,4,1, 58091,3,1,6,1,
51203,1457,22,1,77, 58105,1547,22,1,114,
51211,1478,1458,17,1459, 58111,1406,1548,17,1549,
512215,1098,1,-1,1, 581215,1220,1,-1,1,
51235,1460,20,1461,4, 58135,1550,20,1551,4,
512438,83,0,105,0, 581438,83,0,105,0,
5125109,0,112,0,108, 5815109,0,112,0,108,
51260,101,0,65,0, 58160,101,0,65,0,
@@ -5128,52 +5818,54 @@ public yyLSLSyntax
51280,103,0,110,0, 58180,103,0,110,0,
5129109,0,101,0,110, 5819109,0,101,0,110,
51300,116,0,95,0, 58200,116,0,95,0,
513149,0,53,0,1, 582149,0,55,0,1,
5132214,1,3,1,4, 5822271,1,3,1,4,
51331,3,1462,22,1, 58231,3,1552,22,1,
513474,1,1620,1463,17, 5824107,1,1659,1553,16,
51351464,15,1404,1,-1, 58250,297,1,2413,1554,
51361,5,1465,20,1466, 582617,1264,1,0,1268,
51374,24,65,0,115, 58271,1159,1555,17,1556,
51380,115,0,105,0, 582815,1220,1,-1,1,
5139103,0,110,0,109, 58295,1557,20,1558,4,
51400,101,0,110,0, 583038,83,0,105,0,
5141116,0,95,0,50, 5831109,0,112,0,108,
51420,1,199,1,3, 58320,101,0,65,0,
51431,2,1,1,1467,
514422,1,59,1,1621,
51451468,16,0,668,1,
51461574,799,1,172,1469,
514717,1470,15,1121,1,
5148-1,1,5,1471,20,
51491472,4,38,66,0,
5150105,0,110,0,97,
51510,114,0,121,0,
515269,0,120,0,112,
51530,114,0,101,0,
5154115,0,115,0,105, 5833115,0,115,0,105,
51550,111,0,110,0, 58340,103,0,110,0,
515695,0,49,0,48, 5835109,0,101,0,110,
51570,1,254,1,3, 58360,116,0,95,0,
51581,4,1,3,1473, 583749,0,49,0,1,
515922,1,114,1,1931, 5838265,1,3,1,6,
5160861,1,1665,1474,17, 58391,5,1559,22,1,
51611475,15,1156,1,-1, 5840101,1,157,1560,17,
51621,5,1476,20,1477, 58411561,15,1243,1,-1,
51634,36,70,0,111, 58421,5,1562,20,1563,
51640,114,0,76,0, 58434,38,66,0,105,
5165111,0,111,0,112, 58440,110,0,97,0,
51660,83,0,116,0, 5845114,0,121,0,69,
516797,0,116,0,101, 58460,120,0,112,0,
51680,109,0,101,0, 5847114,0,101,0,115,
5169110,0,116,0,95, 58480,115,0,105,0,
51700,49,0,1,194, 5849111,0,110,0,95,
51711,3,1,2,1, 58500,49,0,49,0,
51721,1478,22,1,54, 58511,310,1,3,1,
51731,2364,827,1,2105, 58524,1,3,1564,22,
5174814,1,1188,1479,17, 58531,146,1,1413,1565,
51751480,15,1098,1,-1, 585417,1566,15,1220,1,
51761,5,1481,20,1482, 5855-1,1,5,1567,20,
58561568,4,36,83,0,
5857105,0,109,0,112,
58580,108,0,101,0,
585965,0,115,0,115,
58600,105,0,103,0,
5861110,0,109,0,101,
58620,110,0,116,0,
586395,0,52,0,1,
5864258,1,3,1,4,
58651,3,1569,22,1,
586694,1,1370,1570,17,
58671571,15,1220,1,-1,
58681,5,1572,20,1573,
51774,38,83,0,105, 58694,38,83,0,105,
51780,109,0,112,0, 58700,109,0,112,0,
5179108,0,101,0,65, 5871108,0,101,0,65,
@@ -5181,27 +5873,38 @@ public yyLSLSyntax
5181105,0,103,0,110, 5873105,0,103,0,110,
51820,109,0,101,0, 58740,109,0,101,0,
5183110,0,116,0,95, 5875110,0,116,0,95,
51840,50,0,51,0, 58760,49,0,56,0,
51851,222,1,3,1, 58771,272,1,3,1,
51866,1,5,1483,22, 58784,1,3,1574,22,
51871,82,1,1442,1484, 58791,108,1,1478,1575,
518817,1485,15,1098,1, 588017,1576,15,1220,1,
5189-1,1,5,1486,20, 5881-1,1,5,1577,20,
51901487,4,38,83,0, 58821578,4,38,83,0,
5191105,0,109,0,112, 5883105,0,109,0,112,
51920,108,0,101,0, 58840,108,0,101,0,
519365,0,115,0,115, 588565,0,115,0,115,
51940,105,0,103,0, 58860,105,0,103,0,
5195110,0,109,0,101, 5887110,0,109,0,101,
51960,110,0,116,0, 58880,110,0,116,0,
519795,0,49,0,54, 588995,0,49,0,53,
51980,1,215,1,3, 58900,1,269,1,3,
51991,4,1,3,1488, 58911,4,1,3,1579,
520022,1,75,1,1694, 589222,1,105,1,1620,
52011489,16,0,190,1, 58931580,17,1581,15,1522,
5202942,1490,17,1491,15, 58941,-1,1,5,1582,
52031121,1,-1,1,5, 589520,1583,4,24,65,
52041492,20,1493,4,38, 58960,115,0,115,0,
5897105,0,103,0,110,
58980,109,0,101,0,
5899110,0,116,0,95,
59000,50,0,1,254,
59011,3,1,2,1,
59021,1584,22,1,90,
59031,1621,1585,16,0,
5904786,1,1574,921,1,
5905172,1586,17,1587,15,
59061243,1,-1,1,5,
59071588,20,1589,4,38,
520566,0,105,0,110, 590866,0,105,0,110,
52060,97,0,114,0, 59090,97,0,114,0,
5207121,0,69,0,120, 5910121,0,69,0,120,
@@ -5209,88 +5912,170 @@ public yyLSLSyntax
5209101,0,115,0,115, 5912101,0,115,0,115,
52100,105,0,111,0, 59130,105,0,111,0,
5211110,0,95,0,49, 5914110,0,95,0,49,
52120,55,0,1,261, 59150,48,0,1,309,
52131,3,1,4,1, 59161,3,1,4,1,
52143,1494,22,1,121, 59173,1590,22,1,145,
52151,2198,1495,17,1142, 59181,1931,983,1,1665,
52161,0,1146,1,1195, 59191591,17,1592,15,1278,
52171496,17,1497,15,1098, 59201,-1,1,5,1593,
52181,-1,1,5,1498, 592120,1594,4,36,70,
521920,1499,4,38,83, 59220,111,0,114,0,
592376,0,111,0,111,
59240,112,0,83,0,
5925116,0,97,0,116,
59260,101,0,109,0,
5927101,0,110,0,116,
59280,95,0,49,0,
59291,249,1,3,1,
59302,1,1,1595,22,
59311,85,1,2364,949,
59321,2105,936,1,1188,
59331596,17,1597,15,1220,
59341,-1,1,5,1598,
593520,1599,4,38,83,
52200,105,0,109,0, 59360,105,0,109,0,
5221112,0,108,0,101, 5937112,0,108,0,101,
52220,65,0,115,0, 59380,65,0,115,0,
5223115,0,105,0,103, 5939115,0,105,0,103,
52240,110,0,109,0, 59400,110,0,109,0,
5225101,0,110,0,116, 5941101,0,110,0,116,
52260,95,0,49,0, 59420,95,0,50,0,
522748,0,1,209,1, 594351,0,1,277,1,
52283,1,6,1,5, 59443,1,6,1,5,
52291500,22,1,69,1, 59451600,22,1,113,1,
52301449,1501,17,1502,15, 59461442,1601,17,1602,15,
52311098,1,-1,1,5, 59471220,1,-1,1,5,
52321503,20,1504,4,36, 59481603,20,1604,4,38,
523383,0,105,0,109, 594983,0,105,0,109,
52340,112,0,108,0, 59500,112,0,108,0,
5235101,0,65,0,115, 5951101,0,65,0,115,
52360,115,0,105,0, 59520,115,0,105,0,
5237103,0,110,0,109, 5953103,0,110,0,109,
52380,101,0,110,0, 59540,101,0,110,0,
5239116,0,95,0,51, 5955116,0,95,0,49,
52400,1,202,1,3, 59560,54,0,1,270,
52411,4,1,3,1505, 59571,3,1,4,1,
524222,1,62,1,1701, 59583,1605,22,1,106,
52431506,17,1507,15,1156, 59591,1694,1606,16,0,
52441,-1,1,5,1508, 5960218,1,942,1607,17,
524520,1509,4,36,70, 59611608,15,1243,1,-1,
52460,111,0,114,0, 59621,5,1609,20,1610,
524776,0,111,0,111, 59634,38,66,0,105,
52480,112,0,83,0, 59640,110,0,97,0,
5249116,0,97,0,116, 5965114,0,121,0,69,
52500,101,0,109,0, 59660,120,0,112,0,
5251101,0,110,0,116, 5967114,0,101,0,115,
52520,95,0,51,0, 59680,115,0,105,0,
52531,196,1,3,1, 5969111,0,110,0,95,
52544,1,3,1510,22, 59700,49,0,55,0,
52551,56,1,447,1511, 59711,316,1,3,1,
525617,1512,15,1513,4, 59724,1,3,1611,22,
525730,37,0,86,0, 59731,152,1,2198,1612,
5258101,0,99,0,116, 597417,1264,1,0,1268,
52590,111,0,114,0, 59751,1195,1613,17,1614,
526067,0,111,0,110, 597615,1220,1,-1,1,
52610,115,0,116,0, 59775,1615,20,1616,4,
526297,0,110,0,116, 597838,83,0,105,0,
52630,1,-1,1,5, 5979109,0,112,0,108,
52641514,20,1515,4,32, 59800,101,0,65,0,
5981115,0,115,0,105,
59820,103,0,110,0,
5983109,0,101,0,110,
59840,116,0,95,0,
598549,0,48,0,1,
5986264,1,3,1,6,
59871,5,1617,22,1,
5988100,1,1449,1618,17,
59891619,15,1220,1,-1,
59901,5,1620,20,1621,
59914,36,83,0,105,
59920,109,0,112,0,
5993108,0,101,0,65,
59940,115,0,115,0,
5995105,0,103,0,110,
59960,109,0,101,0,
5997110,0,116,0,95,
59980,51,0,1,257,
59991,3,1,4,1,
60003,1622,22,1,93,
60011,1701,1623,17,1624,
600215,1278,1,-1,1,
60035,1625,20,1626,4,
600436,70,0,111,0,
6005114,0,76,0,111,
60060,111,0,112,0,
600783,0,116,0,97,
60080,116,0,101,0,
6009109,0,101,0,110,
60100,116,0,95,0,
601151,0,1,251,1,
60123,1,4,1,3,
60131627,22,1,87,1,
6014447,1628,17,1629,15,
60151630,4,30,37,0,
526586,0,101,0,99, 601686,0,101,0,99,
52660,116,0,111,0, 60170,116,0,111,0,
5267114,0,67,0,111, 6018114,0,67,0,111,
52680,110,0,115,0, 60190,110,0,115,0,
5269116,0,97,0,110, 6020116,0,97,0,110,
52700,116,0,95,0, 60210,116,0,1,-1,
527149,0,1,231,1, 60221,5,1631,20,1632,
52723,1,8,1,7, 60234,32,86,0,101,
52731516,22,1,91,1, 60240,99,0,116,0,
52742458,876,1,2459,882, 6025111,0,114,0,67,
52751,1958,1517,17,1142, 60260,111,0,110,0,
52761,0,1146,1,188, 6027115,0,116,0,97,
52771518,17,1519,15,1121, 60280,110,0,116,0,
52781,-1,1,5,1520, 602995,0,49,0,1,
527920,1521,4,36,66, 6030286,1,3,1,8,
60311,7,1633,22,1,
6032122,1,2458,998,1,
60332459,1004,1,1958,1634,
603417,1264,1,0,1268,
60351,188,1635,17,1636,
603615,1243,1,-1,1,
60375,1637,20,1638,4,
603836,66,0,105,0,
6039110,0,97,0,114,
60400,121,0,69,0,
6041120,0,112,0,114,
60420,101,0,115,0,
6043115,0,105,0,111,
60440,110,0,95,0,
604557,0,1,308,1,
60463,1,4,1,3,
60471639,22,1,144,1,
60482462,1011,1,1657,1016,
60491,2464,1021,1,205,
60501640,17,1641,15,1243,
60511,-1,1,5,1642,
605220,1643,4,36,66,
52800,105,0,110,0, 60530,105,0,110,0,
528197,0,114,0,121, 605497,0,114,0,121,
52820,69,0,120,0, 60550,69,0,120,0,
5283112,0,114,0,101, 6056112,0,114,0,101,
52840,115,0,115,0, 60570,115,0,115,0,
5285105,0,111,0,110, 6058105,0,111,0,110,
52860,95,0,57,0, 60590,95,0,56,0,
52871,253,1,3,1, 60601,307,1,3,1,
52884,1,3,1522,22, 60614,1,3,1644,22,
52891,113,1,2462,889, 60621,143,1,2227,1030,
52901,1657,894,1,2464, 60631,1224,1645,17,1646,
5291899,1,205,1523,17, 606415,1220,1,-1,1,
52921524,15,1121,1,-1, 60655,1647,20,1648,4,
52931,5,1525,20,1526, 606638,83,0,105,0,
6067109,0,112,0,108,
60680,101,0,65,0,
6069115,0,115,0,105,
60700,103,0,110,0,
6071109,0,101,0,110,
60720,116,0,95,0,
607350,0,50,0,1,
6074276,1,3,1,6,
60751,5,1649,22,1,
6076112,1,223,1650,17,
60771651,15,1243,1,-1,
60781,5,1652,20,1653,
52944,36,66,0,105, 60794,36,66,0,105,
52950,110,0,97,0, 60800,110,0,97,0,
5296114,0,121,0,69, 6081114,0,121,0,69,
@@ -5298,131 +6083,120 @@ public yyLSLSyntax
5298114,0,101,0,115, 6083114,0,101,0,115,
52990,115,0,105,0, 60840,115,0,105,0,
5300111,0,110,0,95, 6085111,0,110,0,95,
53010,56,0,1,252, 60860,55,0,1,306,
53021,3,1,4,1, 60871,3,1,4,1,
53033,1527,22,1,112, 60883,1654,22,1,142,
53041,2227,908,1,1224, 60891,1730,1655,17,1656,
53051528,17,1529,15,1098, 609015,1278,1,-1,1,
53061,-1,1,5,1530, 60915,1657,20,1658,4,
530720,1531,4,38,83, 609236,70,0,111,0,
53080,105,0,109,0, 6093114,0,76,0,111,
5309112,0,108,0,101, 60940,111,0,112,0,
53100,65,0,115,0, 609583,0,116,0,97,
5311115,0,105,0,103, 60960,116,0,101,0,
53120,110,0,109,0, 6097109,0,101,0,110,
5313101,0,110,0,116, 60980,116,0,95,0,
53140,95,0,50,0, 609952,0,1,252,1,
531550,0,1,221,1, 61003,1,4,1,3,
53163,1,6,1,5, 61011659,22,1,88,1,
53171532,22,1,81,1, 6102476,1660,17,1661,15,
5318223,1533,17,1534,15, 61031662,4,18,37,0,
53191121,1,-1,1,5, 610467,0,111,0,110,
53201535,20,1536,4,36, 61050,115,0,116,0,
532166,0,105,0,110, 610697,0,110,0,116,
53220,97,0,114,0, 61070,1,-1,1,5,
5323121,0,69,0,120, 61081663,20,1664,4,20,
53240,112,0,114,0, 610967,0,111,0,110,
5325101,0,115,0,115, 61100,115,0,116,0,
53260,105,0,111,0, 611197,0,110,0,116,
5327110,0,95,0,55,
53280,1,251,1,3,
53291,4,1,3,1537,
533022,1,111,1,1730,
53311538,17,1539,15,1156,
53321,-1,1,5,1540,
533320,1541,4,36,70,
53340,111,0,114,0,
533576,0,111,0,111,
53360,112,0,83,0,
5337116,0,97,0,116,
53380,101,0,109,0,
5339101,0,110,0,116,
53400,95,0,52,0, 61120,95,0,52,0,
53411,197,1,3,1, 61131,284,1,3,1,
53424,1,3,1542,22, 61142,1,1,1665,22,
53431,57,1,476,1543, 61151,120,1,477,1666,
534417,1544,15,1545,4, 611617,1667,15,1662,1,
534518,37,0,67,0, 6117-1,1,5,1668,20,
5346111,0,110,0,115, 61181669,4,20,67,0,
53470,116,0,97,0,
5348110,0,116,0,1,
5349-1,1,5,1546,20,
53501547,4,20,67,0,
5351111,0,110,0,115, 6119111,0,110,0,115,
53520,116,0,97,0, 61200,116,0,97,0,
5353110,0,116,0,95, 6121110,0,116,0,95,
53540,52,0,1,229, 61220,51,0,1,283,
53551,3,1,2,1, 61231,3,1,2,1,
53561,1548,22,1,89, 61241,1670,22,1,119,
53571,477,1549,17,1550, 61251,1231,1671,17,1672,
535815,1545,1,-1,1, 612615,1220,1,-1,1,
53595,1551,20,1552,4, 61275,1673,20,1674,4,
536020,67,0,111,0, 612836,83,0,105,0,
6129109,0,112,0,108,
61300,101,0,65,0,
6131115,0,115,0,105,
61320,103,0,110,0,
6133109,0,101,0,110,
61340,116,0,95,0,
613557,0,1,263,1,
61363,1,6,1,5,
61371675,22,1,99,1,
6138479,1676,17,1677,15,
61391662,1,-1,1,5,
61401678,20,1679,4,20,
614167,0,111,0,110,
61420,115,0,116,0,
614397,0,110,0,116,
61440,95,0,49,0,
61451,281,1,3,1,
61462,1,1,1680,22,
61471,117,1,480,1681,
614817,1682,15,1683,4,
614926,37,0,76,0,
6150105,0,115,0,116,
61510,67,0,111,0,
5361110,0,115,0,116, 6152110,0,115,0,116,
53620,97,0,110,0, 61530,97,0,110,0,
5363116,0,95,0,51, 6154116,0,1,-1,1,
53640,1,228,1,3, 61555,1684,20,1685,4,
53651,2,1,1,1553, 615628,76,0,105,0,
536622,1,88,1,1231,
53671554,17,1555,15,1098,
53681,-1,1,5,1556,
536920,1557,4,36,83,
53700,105,0,109,0,
5371112,0,108,0,101,
53720,65,0,115,0,
5373115,0,105,0,103,
53740,110,0,109,0,
5375101,0,110,0,116,
53760,95,0,57,0,
53771,208,1,3,1,
53786,1,5,1558,22,
53791,68,1,479,1559,
538017,1560,15,1545,1,
5381-1,1,5,1561,20,
53821562,4,20,67,0,
5383111,0,110,0,115,
53840,116,0,97,0,
5385110,0,116,0,95,
53860,49,0,1,226,
53871,3,1,2,1,
53881,1563,22,1,86,
53891,480,1564,17,1565,
539015,1566,4,26,37,
53910,76,0,105,0,
5392115,0,116,0,67, 6157115,0,116,0,67,
53930,111,0,110,0, 61580,111,0,110,0,
5394115,0,116,0,97, 6159115,0,116,0,97,
53950,110,0,116,0, 61600,110,0,116,0,
53961,-1,1,5,1567, 616195,0,49,0,1,
539720,1568,4,28,76, 6162285,1,3,1,4,
53980,105,0,115,0, 61631,3,1686,22,1,
5399116,0,67,0,111, 6164121,1,1485,1687,17,
54000,110,0,115,0, 61651688,15,1220,1,-1,
5401116,0,97,0,110, 61661,5,1689,20,1690,
54020,116,0,95,0, 61674,36,83,0,105,
540349,0,1,230,1, 61680,109,0,112,0,
54043,1,4,1,3, 6169108,0,101,0,65,
54051569,22,1,90,1, 61700,115,0,115,0,
54061485,1570,17,1571,15, 6171105,0,103,0,110,
54071098,1,-1,1,5, 61720,109,0,101,0,
54081572,20,1573,4,36, 6173110,0,116,0,95,
540983,0,105,0,109, 61740,50,0,1,256,
54100,112,0,108,0, 61751,3,1,4,1,
5411101,0,65,0,115, 61763,1691,22,1,92,
54120,115,0,105,0, 61771,1737,1692,16,0,
5413103,0,110,0,109, 6178299,1,1989,1038,1,
54140,101,0,110,0, 61791990,1693,17,1264,1,
5415116,0,95,0,50, 61800,1268,1,1096,1694,
54160,1,201,1,3, 618117,1695,15,1696,4,
54171,4,1,3,1574, 618226,37,0,70,0,
541822,1,61,1,1737, 6183117,0,110,0,99,
54191575,16,0,271,1, 61840,116,0,105,0,
54201989,916,1,1990,1576, 6185111,0,110,0,67,
542117,1142,1,0,1146, 61860,97,0,108,0,
54221,2664,1577,16,0, 6187108,0,1,-1,1,
5423667,1,242,1578,17, 61885,1697,20,1698,4,
54241579,15,1121,1,-1, 618928,70,0,117,0,
54251,5,1580,20,1581, 6190110,0,99,0,116,
61910,105,0,111,0,
6192110,0,67,0,97,
61930,108,0,108,0,
619495,0,49,0,1,
6195332,1,3,1,5,
61961,4,1699,22,1,
6197168,1,242,1700,17,
61981701,15,1243,1,-1,
61991,5,1702,20,1703,
54264,36,66,0,105, 62004,36,66,0,105,
54270,110,0,97,0, 62010,110,0,97,0,
5428114,0,121,0,69, 6202114,0,121,0,69,
@@ -5430,22 +6204,22 @@ public yyLSLSyntax
5430114,0,101,0,115, 6204114,0,101,0,115,
54310,115,0,105,0, 62050,115,0,105,0,
5432111,0,110,0,95, 6206111,0,110,0,95,
54330,54,0,1,250, 62070,54,0,1,305,
54341,3,1,4,1, 62081,3,1,4,1,
54353,1582,22,1,110, 62093,1704,22,1,141,
54361,478,1583,17,1584, 62101,478,1705,17,1706,
543715,1545,1,-1,1, 621115,1662,1,-1,1,
54385,1585,20,1586,4, 62125,1707,20,1708,4,
543920,67,0,111,0, 621320,67,0,111,0,
5440110,0,115,0,116, 6214110,0,115,0,116,
54410,97,0,110,0, 62150,97,0,110,0,
5442116,0,95,0,50, 6216116,0,95,0,50,
54430,1,227,1,3, 62170,1,282,1,3,
54441,2,1,1,1587, 62181,2,1,1,1709,
544522,1,87,1,1001, 621922,1,118,1,1001,
54461588,17,1589,15,1224, 62201710,17,1711,15,1347,
54471,-1,1,5,1590, 62211,-1,1,5,1712,
544820,1591,4,40,84, 622220,1713,4,40,84,
54490,121,0,112,0, 62230,121,0,112,0,
5450101,0,99,0,97, 6224101,0,99,0,97,
54510,115,0,116,0, 62250,115,0,116,0,
@@ -5454,11 +6228,11 @@ public yyLSLSyntax
5454115,0,115,0,105, 6228115,0,115,0,105,
54550,111,0,110,0, 62290,111,0,110,0,
545695,0,56,0,1, 623095,0,56,0,1,
5457275,1,3,1,5, 6231330,1,3,1,5,
54581,4,1592,22,1, 62321,4,1714,22,1,
5459135,1,1002,1593,17, 6233166,1,1002,1715,17,
54601594,15,1224,1,-1, 62341716,15,1347,1,-1,
54611,5,1595,20,1596, 62351,5,1717,20,1718,
54624,40,84,0,121, 62364,40,84,0,121,
54630,112,0,101,0, 62370,112,0,101,0,
546499,0,97,0,115, 623899,0,97,0,115,
@@ -5467,154 +6241,607 @@ public yyLSLSyntax
54670,101,0,115,0, 62410,101,0,115,0,
5468115,0,105,0,111, 6242115,0,105,0,111,
54690,110,0,95,0, 62430,110,0,95,0,
547049,0,1,268,1, 624449,0,1,323,1,
54713,1,5,1,4, 62453,1,5,1,4,
54721597,22,1,128,1, 62461719,22,1,159,1,
547312,1598,19,157,1, 624712,1720,19,166,1,
547412,1599,5,43,1, 624812,1721,5,50,1,
54751901,1600,16,0,155, 62491901,1722,16,0,164,
54761,2075,1601,16,0, 62501,2075,1723,16,0,
5477155,1,1860,821,1, 6251164,1,1860,943,1,
54781803,787,1,1804,1602, 62521803,909,1,1804,1724,
547916,0,155,1,2517, 625316,0,164,1,2518,
54801603,16,0,155,1, 62541725,16,0,164,1,
54812413,1604,16,0,155, 62552413,1726,16,0,164,
54821,2198,1605,16,0, 62561,2198,1727,16,0,
5483155,1,1873,835,1, 6257164,1,1873,958,1,
54841657,894,1,1989,916, 62581657,1016,1,2136,965,
54851,1990,1606,16,0, 62591,2032,863,1,1989,
5486155,1,31,1607,16, 62601038,1,1990,1728,16,
54870,155,1,32,1608, 62610,164,1,31,1729,
548816,0,155,1,2105, 626216,0,164,1,32,
5489814,1,2106,1609,16, 62631730,16,0,164,1,
54900,155,1,2653,1610, 62642105,936,1,2106,1731,
549116,0,155,1,2227, 626516,0,164,1,2656,
5492908,1,2337,1611,16, 62661732,16,0,282,1,
54930,155,1,2560,1612, 62672548,1733,16,0,164,
549416,0,467,1,2021, 62681,2227,1030,1,2337,
5495718,1,2458,876,1, 62691734,16,0,164,1,
54962459,882,1,2462,889, 62702556,1735,16,0,164,
54971,2136,842,1,2464, 62711,2777,1736,16,0,
5498899,1,2029,725,1, 6272164,1,2564,1737,16,
54992030,731,1,2031,736, 62730,164,1,2021,840,
55001,2032,741,1,2469, 62741,2458,998,1,2459,
55011613,16,0,454,1, 62751004,1,2462,1011,1,
55022035,752,1,2364,827, 62762572,1738,16,0,164,
55031,2039,762,1,1931, 62771,2464,1021,1,2029,
5504861,1,2041,768,1, 6278847,1,2030,853,1,
55052043,774,1,2045,779, 62792031,858,1,2577,1739,
55061,1775,1614,16,0, 628016,0,164,1,2469,
5507155,1,2033,746,1, 62811740,16,0,520,1,
55082037,757,1,1574,799, 62822035,874,1,2364,949,
55091,1958,1615,16,0, 62831,2039,884,1,1931,
5510155,1,13,1616,19, 6284983,1,2041,890,1,
5511448,1,13,1617,5, 62852043,896,1,2045,901,
551234,1,1860,821,1, 62861,2592,1741,16,0,
55131803,787,1,2519,1618, 6287164,1,1775,1742,16,
551417,1619,15,1620,4, 62880,164,1,2033,868,
551522,37,0,83,0, 62891,2037,879,1,1574,
6290921,1,1958,1743,16,
62910,164,1,2533,1744,
629216,0,164,1,13,
62931745,19,508,1,13,
62941746,5,55,1,2643,
62951747,17,1748,15,1749,
62964,20,37,0,83,
62970,116,0,97,0,
6298116,0,101,0,66,
62990,111,0,100,0,
6300121,0,1,-1,1,
63015,1750,20,1751,4,
630222,83,0,116,0,
630397,0,116,0,101,
63040,66,0,111,0,
6305100,0,121,0,95,
63060,56,0,1,187,
63071,3,1,3,1,
63082,1752,22,1,22,
63091,2644,1753,17,1754,
631015,1749,1,-1,1,
63115,1755,20,1756,4,
631222,83,0,116,0,
631397,0,116,0,101,
63140,66,0,111,0,
6315100,0,121,0,95,
63160,54,0,1,185,
63171,3,1,3,1,
63182,1757,22,1,20,
63191,1860,943,1,1803,
6320909,1,2520,1758,17,
63211759,15,1760,4,46,
632237,0,75,0,101,
63230,121,0,73,0,
6324110,0,116,0,73,
63250,110,0,116,0,
632665,0,114,0,103,
63270,83,0,116,0,
632897,0,116,0,101,
63290,69,0,118,0,
6330101,0,110,0,116,
63310,1,-1,1,5,
63321761,20,1762,4,48,
633375,0,101,0,121,
63340,73,0,110,0,
6335116,0,73,0,110,
63360,116,0,65,0,
6337114,0,103,0,83,
63380,116,0,97,0,
6339116,0,101,0,69,
63400,118,0,101,0,
6341110,0,116,0,95,
63420,49,0,1,203,
63431,3,1,6,1,
63445,1763,22,1,38,
63451,2413,1764,16,0,
6346506,1,1873,958,1,
63471657,1016,1,2639,1765,
634817,1766,15,1749,1,
6349-1,1,5,1767,20,
63501768,4,24,83,0,
6351116,0,97,0,116,
63520,101,0,66,0,
6353111,0,100,0,121,
63540,95,0,49,0,
635554,0,1,195,1,
63563,1,3,1,2,
63571769,22,1,30,1,
63582640,1770,17,1771,15,
63591749,1,-1,1,5,
63601772,20,1773,4,24,
636183,0,116,0,97,
63620,116,0,101,0,
636366,0,111,0,100,
63640,121,0,95,0,
636549,0,52,0,1,
6366193,1,3,1,3,
63671,2,1774,22,1,
636828,1,2641,1775,17,
63691776,15,1749,1,-1,
63701,5,1777,20,1778,
63714,24,83,0,116,
63720,97,0,116,0,
6373101,0,66,0,111,
63740,100,0,121,0,
637595,0,49,0,50,
63760,1,191,1,3,
63771,3,1,2,1779,
637822,1,26,1,2642,
63791780,17,1781,15,1749,
63801,-1,1,5,1782,
638120,1783,4,24,83,
63820,116,0,97,0,
6383116,0,101,0,66,
63840,111,0,100,0,
6385121,0,95,0,49,
63860,48,0,1,189,
63871,3,1,3,1,
63882,1784,22,1,24,
63891,1989,1038,1,2535,
63901785,17,1786,15,1787,
63914,46,37,0,73,
63920,110,0,116,0,
639386,0,101,0,99,
63940,86,0,101,0,
639599,0,65,0,114,
63960,103,0,83,0,
5516116,0,97,0,116, 6397116,0,97,0,116,
55170,101,0,69,0, 63980,101,0,69,0,
5518118,0,101,0,110, 6399118,0,101,0,110,
55190,116,0,1,-1, 64000,116,0,1,-1,
55201,5,1621,20,1622, 64011,5,1788,20,1789,
55214,24,83,0,116, 64024,48,73,0,110,
55220,97,0,116,0, 64030,116,0,86,0,
5523101,0,69,0,118, 6404101,0,99,0,86,
55240,101,0,110,0, 64050,101,0,99,0,
5525116,0,95,0,49, 640665,0,114,0,103,
55260,1,158,1,3, 64070,83,0,116,0,
55271,6,1,5,1623, 640897,0,116,0,101,
552822,1,17,1,2521, 64090,69,0,118,0,
55291624,16,0,460,1, 6410101,0,110,0,116,
55302413,1625,16,0,446, 64110,95,0,49,0,
55311,1873,835,1,1657, 64121,202,1,3,1,
5532894,1,1989,916,1, 64136,1,5,1790,22,
553332,1626,16,0,449, 64141,37,1,2645,1791,
55341,2105,814,1,2364, 641517,1792,15,1749,1,
5535827,1,2227,908,1, 6416-1,1,5,1793,20,
55361574,799,1,2557,1627, 64171794,4,22,83,0,
553717,1628,15,1629,4,
553820,37,0,83,0,
5539116,0,97,0,116, 6418116,0,97,0,116,
55400,101,0,66,0, 64190,101,0,66,0,
5541111,0,100,0,121, 6420111,0,100,0,121,
55420,1,-1,1,5, 64210,95,0,52,0,
55431630,20,1631,4,22, 64221,183,1,3,1,
64233,1,2,1795,22,
64241,18,1,2646,1796,
642517,1797,15,1749,1,
6426-1,1,5,1798,20,
64271799,4,22,83,0,
6428116,0,97,0,116,
64290,101,0,66,0,
6430111,0,100,0,121,
64310,95,0,50,0,
64321,181,1,3,1,
64333,1,2,1800,22,
64341,16,1,2037,879,
64351,32,1801,16,0,
6436513,1,2649,1802,17,
64371803,15,1749,1,-1,
64381,5,1804,20,1805,
64394,24,83,0,116,
64400,97,0,116,0,
6441101,0,66,0,111,
64420,100,0,121,0,
644395,0,49,0,51,
64440,1,192,1,3,
64451,2,1,1,1806,
644622,1,27,1,2650,
64471807,17,1808,15,1749,
64481,-1,1,5,1809,
644920,1810,4,24,83,
64500,116,0,97,0,
6451116,0,101,0,66,
64520,111,0,100,0,
6453121,0,95,0,49,
64540,49,0,1,190,
64551,3,1,2,1,
64561,1811,22,1,25,
64571,2651,1812,17,1813,
645815,1749,1,-1,1,
64595,1814,20,1815,4,
646022,83,0,116,0,
646197,0,116,0,101,
64620,66,0,111,0,
6463100,0,121,0,95,
64640,57,0,1,188,
64651,3,1,2,1,
64661,1816,22,1,23,
64671,2652,1817,17,1818,
646815,1749,1,-1,1,
64695,1819,20,1820,4,
647022,83,0,116,0,
647197,0,116,0,101,
64720,66,0,111,0,
6473100,0,121,0,95,
64740,55,0,1,186,
64751,3,1,2,1,
64761,1821,22,1,21,
64771,2653,1822,17,1823,
647815,1749,1,-1,1,
64795,1824,20,1825,4,
648022,83,0,116,0,
648197,0,116,0,101,
64820,66,0,111,0,
6483100,0,121,0,95,
64840,53,0,1,184,
64851,3,1,2,1,
64861,1826,22,1,19,
64871,2654,1827,17,1828,
648815,1749,1,-1,1,
64895,1829,20,1830,4,
649022,83,0,116,0,
649197,0,116,0,101,
64920,66,0,111,0,
6493100,0,121,0,95,
64940,51,0,1,182,
64951,3,1,2,1,
64961,1831,22,1,17,
64971,2655,1832,17,1833,
649815,1749,1,-1,1,
64995,1834,20,1835,4,
650022,83,0,116,0,
650197,0,116,0,101,
65020,66,0,111,0,
6503100,0,121,0,95,
65040,49,0,1,180,
65051,3,1,2,1,
65061,1836,22,1,15,
65071,2574,1837,17,1838,
650815,1839,4,34,37,
65090,75,0,101,0,
6510121,0,65,0,114,
65110,103,0,83,0,
6512116,0,97,0,116,
65130,101,0,69,0,
6514118,0,101,0,110,
65150,116,0,1,-1,
65161,5,1840,20,1841,
65174,36,75,0,101,
65180,121,0,65,0,
6519114,0,103,0,83,
65200,116,0,97,0,
6521116,0,101,0,69,
65220,118,0,101,0,
6523110,0,116,0,95,
65240,49,0,1,198,
65251,3,1,6,1,
65265,1842,22,1,33,
65271,2550,1843,17,1844,
652815,1845,4,46,37,
65290,73,0,110,0,
6530116,0,82,0,111,
65310,116,0,82,0,
6532111,0,116,0,65,
65330,114,0,103,0,
554483,0,116,0,97, 653483,0,116,0,97,
55450,116,0,101,0, 65350,116,0,101,0,
554666,0,111,0,100, 653669,0,118,0,101,
55470,121,0,95,0, 65370,110,0,116,0,
554850,0,1,157,1, 65381,-1,1,5,1846,
55493,1,3,1,2, 653920,1847,4,48,73,
55501632,22,1,16,1, 65400,110,0,116,0,
55512559,1633,17,1634,15, 654182,0,111,0,116,
55521629,1,-1,1,5, 65420,82,0,111,0,
55531635,20,1636,4,22, 6543116,0,65,0,114,
65440,103,0,83,0,
6545116,0,97,0,116,
65460,101,0,69,0,
6547118,0,101,0,110,
65480,116,0,95,0,
654949,0,1,201,1,
65503,1,6,1,5,
65511848,22,1,36,1,
65522227,1030,1,1574,921,
65531,2558,1849,17,1850,
655415,1851,4,40,37,
65550,86,0,101,0,
655699,0,116,0,111,
65570,114,0,65,0,
6558114,0,103,0,83,
65590,116,0,97,0,
6560116,0,101,0,69,
65610,118,0,101,0,
6562110,0,116,0,1,
6563-1,1,5,1852,20,
65641853,4,42,86,0,
6565101,0,99,0,116,
65660,111,0,114,0,
656765,0,114,0,103,
65680,83,0,116,0,
656997,0,116,0,101,
65700,69,0,118,0,
6571101,0,110,0,116,
65720,95,0,49,0,
65731,200,1,3,1,
65746,1,5,1854,22,
65751,35,1,2566,1855,
657617,1856,15,1857,4,
657734,37,0,73,0,
6578110,0,116,0,65,
65790,114,0,103,0,
555483,0,116,0,97, 658083,0,116,0,97,
55550,116,0,101,0, 65810,116,0,101,0,
555666,0,111,0,100, 658269,0,118,0,101,
55570,121,0,95,0, 65830,110,0,116,0,
555849,0,1,156,1, 65841,-1,1,5,1858,
55593,1,2,1,1, 658520,1859,4,36,73,
55601637,22,1,15,1, 65860,110,0,116,0,
55612021,718,1,2458,876,
55621,2459,882,1,2462,
5563889,1,2136,842,1,
55642464,899,1,2029,725,
55651,2030,731,1,2031,
5566736,1,2032,741,1,
55672033,746,1,2035,752,
55681,2037,757,1,2039,
5569762,1,1931,861,1,
55702041,768,1,2043,774,
55711,2045,779,1,2597,
55721638,16,0,639,1,
557314,1639,19,144,1,
557414,1640,5,105,1,
55752515,1641,16,0,142,
55761,1011,1102,1,1514,
55771108,1,9,1113,1,
557810,1642,17,1643,15,
55791644,4,48,37,0,
558065,0,114,0,103, 658765,0,114,0,103,
55810,117,0,109,0, 65880,83,0,116,0,
658997,0,116,0,101,
65900,69,0,118,0,
5582101,0,110,0,116, 6591101,0,110,0,116,
65920,95,0,49,0,
65931,199,1,3,1,
65946,1,5,1860,22,
65951,34,1,2458,998,
65961,2459,1004,1,2462,
65971011,1,2136,965,1,
65982464,1021,1,2029,847,
65991,2030,853,1,2031,
6600858,1,2032,863,1,
66012033,868,1,2579,1861,
660217,1862,15,1863,4,
660336,37,0,86,0,
6604111,0,105,0,100,
66050,65,0,114,0,
6606103,0,83,0,116,
66070,97,0,116,0,
6608101,0,69,0,118,
66090,101,0,110,0,
6610116,0,1,-1,1,
66115,1864,20,1865,4,
661238,86,0,111,0,
6613105,0,100,0,65,
66140,114,0,103,0,
661583,0,116,0,97,
66160,116,0,101,0,
661769,0,118,0,101,
66180,110,0,116,0,
661995,0,49,0,1,
6620197,1,3,1,5,
66211,4,1866,22,1,
662232,1,2035,874,1,
66232364,949,1,2039,884,
66241,1931,983,1,2041,
6625890,1,2021,840,1,
66262043,896,1,2045,901,
66271,2700,1867,16,0,
6628769,1,2594,1868,17,
66291869,15,1870,4,22,
663037,0,83,0,116,
66310,97,0,116,0,
6632101,0,69,0,118,
66330,101,0,110,0,
6634116,0,1,-1,1,
66355,1871,20,1872,4,
663624,83,0,116,0,
663797,0,116,0,101,
66380,69,0,118,0,
6639101,0,110,0,116,
66400,95,0,49,0,
66411,196,1,3,1,
66426,1,5,1873,22,
66431,31,1,2596,1874,
664416,0,662,1,2648,
66451875,17,1876,15,1749,
66461,-1,1,5,1877,
664720,1878,4,24,83,
66480,116,0,97,0,
6649116,0,101,0,66,
66500,111,0,100,0,
6651121,0,95,0,49,
66520,53,0,1,194,
66531,3,1,2,1,
66541,1879,22,1,29,
66551,2105,936,1,14,
66561880,19,144,1,14,
66571881,5,115,1,2512,
66581882,17,1883,15,1884,
66594,30,37,0,73,
66600,110,0,116,0,
666168,0,101,0,99,
66620,108,0,97,0,
6663114,0,97,0,116,
66640,105,0,111,0,
6665110,0,1,-1,1,
66665,1885,20,1886,4,
666732,73,0,110,0,
6668116,0,68,0,101,
66690,99,0,108,0,
667097,0,114,0,97,
66710,116,0,105,0,
6672111,0,110,0,95,
66730,49,0,1,214,
66741,3,1,3,1,
66752,1887,22,1,50,
66761,2513,1888,16,0,
6677481,1,1260,1218,1,
66781011,1224,1,1514,1230,
66791,9,1235,1,10,
66801889,17,1890,15,1891,
66814,48,37,0,65,
66820,114,0,103,0,
6683117,0,109,0,101,
66840,110,0,116,0,
668568,0,101,0,99,
66860,108,0,97,0,
6687114,0,97,0,116,
66880,105,0,111,0,
6689110,0,76,0,105,
66900,115,0,116,0,
66911,-1,1,5,140,
66921,0,1,0,1892,
669322,1,39,1,262,
66941241,1,1267,1247,1,
66952524,1893,16,0,492,
66961,1521,1252,1,1773,
66971894,16,0,151,1,
66982527,1895,17,1896,15,
66991897,4,30,37,0,
670086,0,101,0,99,
55830,68,0,101,0, 67010,68,0,101,0,
558499,0,108,0,97, 670299,0,108,0,97,
55850,114,0,97,0, 67030,114,0,97,0,
5586116,0,105,0,111, 6704116,0,105,0,111,
55870,110,0,76,0, 67050,110,0,1,-1,
5588105,0,115,0,116, 67061,5,1898,20,1899,
55890,1,-1,1,5, 67074,32,86,0,101,
5590140,1,0,1,0, 67080,99,0,68,0,
55911645,22,1,18,1, 6709101,0,99,0,108,
5592262,1119,1,1267,1125, 67100,97,0,114,0,
55931,481,1646,17,1647, 671197,0,116,0,105,
559415,1648,4,26,37, 67120,111,0,110,0,
671395,0,49,0,1,
6714215,1,3,1,3,
67151,2,1900,22,1,
671651,1,2528,1901,16,
67170,498,1,19,1269,
67181,20,1902,16,0,
6719142,1,2281,1276,1,
6720525,1339,1,2539,1903,
672116,0,510,1,30,
67221904,17,1905,15,1891,
67231,-1,1,5,1906,
672420,1907,4,50,65,
67250,114,0,103,0,
6726117,0,109,0,101,
67270,110,0,116,0,
672868,0,101,0,99,
67290,108,0,97,0,
6730114,0,97,0,116,
67310,105,0,111,0,
6732110,0,76,0,105,
67330,115,0,116,0,
673495,0,50,0,1,
6735205,1,3,1,4,
67361,3,1908,22,1,
673741,1,1002,1715,1,
67382542,1909,17,1910,15,
67391911,4,30,37,0,
674082,0,111,0,116,
67410,68,0,101,0,
674299,0,108,0,97,
67430,114,0,97,0,
6744116,0,105,0,111,
67450,110,0,1,-1,
67461,5,1912,20,1913,
67474,32,82,0,111,
67480,116,0,68,0,
6749101,0,99,0,108,
67500,97,0,114,0,
675197,0,116,0,105,
67520,111,0,110,0,
675395,0,49,0,1,
6754216,1,3,1,3,
67551,2,1914,22,1,
675652,1,2543,1915,16,
67570,514,1,40,1300,
67581,41,1916,17,1917,
675915,1918,4,26,37,
55950,65,0,114,0, 67600,65,0,114,0,
5596103,0,117,0,109, 6761103,0,117,0,109,
55970,101,0,110,0, 67620,101,0,110,0,
5598116,0,76,0,105, 6763116,0,76,0,105,
55990,115,0,116,0, 67640,115,0,116,0,
56001,-1,1,5,1649, 67651,-1,1,5,709,
560120,1650,4,28,65, 67661,0,1,0,1919,
676722,1,169,1,42,
67681920,17,1921,15,1922,
67694,38,37,0,69,
67700,120,0,112,0,
6771114,0,101,0,115,
67720,115,0,105,0,
6773111,0,110,0,65,
56020,114,0,103,0, 67740,114,0,103,0,
5603117,0,109,0,101, 6775117,0,109,0,101,
56040,110,0,116,0, 67760,110,0,116,0,
560576,0,105,0,115, 67771,-1,1,5,1923,
56060,116,0,95,0, 677820,1924,4,40,69,
560749,0,1,278,1, 67790,120,0,112,0,
56083,1,2,1,1, 6780114,0,101,0,115,
56091651,22,1,139,1, 67810,115,0,105,0,
56101521,1130,1,1773,1652, 6782111,0,110,0,65,
561116,0,148,1,19, 67830,114,0,103,0,
56121147,1,20,1653,16, 6784117,0,109,0,101,
56130,142,1,2281,1154, 67850,110,0,116,0,
56141,525,1216,1,30, 678695,0,49,0,1,
56151654,17,1655,15,1644, 6787335,1,3,1,2,
56161,-1,1,5,1656, 67881,1,1925,22,1,
561720,1657,4,50,65, 6789172,1,44,1306,1,
679047,1307,1,48,1313,
67911,49,1319,1,50,
67921324,1,51,1329,1,
6793283,1295,1,305,1334,
67941,63,1345,1,66,
67951351,1,67,1356,1,
67961478,1575,1,69,1366,
67971,70,1371,1,2581,
67981926,17,1927,15,1891,
67991,-1,1,5,140,
68001,0,1,0,1892,
68011,68,1361,1,74,
68021376,1,1013,1381,1,
68032335,1928,16,0,151,
68041,1332,1386,1,1048,
68051462,1,2590,1929,16,
68060,142,1,82,1403,
68071,1296,1290,1,1341,
68081420,1,328,1425,1,
68091303,1430,1,1096,1694,
68101,93,1435,1,1550,
68111440,1,352,1467,1,
68122775,1930,16,0,142,
68131,107,1455,1,1114,
68141461,1,1370,1570,1,
6815118,1473,1,1123,1478,
68161,371,1483,1,1377,
68171489,1,375,1494,1,
6818377,1499,1,827,1448,
68191,380,1509,1,883,
68201515,1,373,1527,1,
6821130,1532,1,379,1504,
68221,143,1537,1,1152,
68231543,1,387,1931,16,
68240,643,1,1406,1548,
68251,1159,1555,1,157,
68261560,1,1413,1565,1,
68271665,1591,1,412,1932,
682816,0,680,1,1094,
68291933,16,0,711,1,
6830172,1586,1,2766,1934,
683117,1935,15,1891,1,
6832-1,1,5,140,1,
68330,1,0,1892,1,
68341188,1596,1,437,1936,
683516,0,755,1,1442,
68361601,1,1694,1937,16,
68370,151,1,942,1607,
68381,1195,1613,1,1449,
68391618,1,1701,1623,1,
6840447,1628,1,188,1635,
68411,205,1640,1,2467,
68421938,17,1939,15,1891,
68431,-1,1,5,1940,
684420,1941,4,50,65,
56180,114,0,103,0, 68450,114,0,103,0,
5619117,0,109,0,101, 6846117,0,109,0,101,
56200,110,0,116,0, 68470,110,0,116,0,
@@ -5624,2837 +6851,3037 @@ public yyLSLSyntax
56240,105,0,111,0, 68510,105,0,111,0,
5625110,0,76,0,105, 6852110,0,76,0,105,
56260,115,0,116,0, 68530,115,0,116,0,
562795,0,50,0,1, 685495,0,49,0,1,
5628160,1,3,1,4, 6855204,1,3,1,2,
56291,3,1658,22,1, 68561,1,1942,22,1,
563020,1,283,1172,1, 685740,1,461,1943,16,
563140,1177,1,41,1659, 68580,711,1,464,1944,
563217,1660,15,1648,1, 685917,1945,15,1918,1,
5633-1,1,5,601,1, 6860-1,1,5,1946,20,
56340,1,0,1661,22, 68611947,4,28,65,0,
56351,138,1,42,1662,
563617,1663,15,1664,4,
563738,37,0,69,0,
5638120,0,112,0,114,
56390,101,0,115,0,
5640115,0,105,0,111,
56410,110,0,65,0,
5642114,0,103,0,117,
56430,109,0,101,0,
5644110,0,116,0,1,
5645-1,1,5,1665,20,
56461666,4,40,69,0,
5647120,0,112,0,114,
56480,101,0,115,0,
5649115,0,105,0,111,
56500,110,0,65,0,
5651114,0,103,0,117, 6862114,0,103,0,117,
56520,109,0,101,0, 68630,109,0,101,0,
5653110,0,116,0,95, 6864110,0,116,0,76,
56540,49,0,1,280, 68650,105,0,115,0,
56551,3,1,2,1, 6866116,0,95,0,50,
56561,1667,22,1,141, 68670,1,334,1,3,
56571,44,1183,1,1260, 68681,4,1,3,1948,
56581096,1,47,1184,1, 686922,1,171,1,1224,
565948,1190,1,49,1196, 68701645,1,223,1650,1,
56601,50,1201,1,51, 68711730,1655,1,476,1660,
56611206,1,305,1211,1, 68721,477,1666,1,1231,
566263,1222,1,66,1228, 68731671,1,479,1676,1,
56631,67,1233,1,1478, 6874480,1681,1,1485,1687,
56641458,1,69,1243,1, 68751,459,1949,17,1950,
566570,1248,1,68,1238, 687615,1918,1,-1,1,
56661,74,1253,1,1013, 68775,709,1,0,1,
56671258,1,2335,1668,16, 68780,1919,1,242,1700,
56680,148,1,1332,1263, 68791,478,1705,1,481,
56691,1048,1344,1,82, 68801951,17,1952,15,1918,
56701280,1,1296,1167,1, 68811,-1,1,5,1953,
56711341,1297,1,328,1302, 688220,1954,4,28,65,
56721,1303,1307,1,1096, 68830,114,0,103,0,
56731312,1,93,1318,1, 6884117,0,109,0,101,
56741550,1323,1,352,1349, 68850,110,0,116,0,
56751,107,1338,1,1114, 688676,0,105,0,115,
56761343,1,1370,1453,1, 68870,116,0,95,0,
5677118,1355,1,1123,1360, 688849,0,1,333,1,
56781,371,1365,1,1377, 68893,1,2,1,1,
56791371,1,375,1376,1, 68901955,22,1,170,1,
5680377,1381,1,379,1386, 68911001,1710,1,2508,1956,
56811,380,1391,1,883, 689217,1957,15,1958,4,
56821397,1,2642,1669,17, 689330,37,0,75,0,
56831670,15,1644,1,-1, 6894101,0,121,0,68,
56841,5,140,1,0, 68950,101,0,99,0,
56851,0,1645,1,373, 6896108,0,97,0,114,
56861409,1,130,1414,1, 68970,97,0,116,0,
56872651,1671,16,0,142, 6898105,0,111,0,110,
56881,143,1419,1,1152, 68990,1,-1,1,5,
56891426,1,387,1672,16, 69001959,20,1960,4,32,
56900,555,1,1406,1431, 690175,0,101,0,121,
56911,1159,1438,1,157,
56921443,1,1413,1448,1,
56931665,1474,1,412,1673,
569416,0,576,1,1094,
56951674,16,0,603,1,
5696172,1469,1,827,1331,
56971,1188,1479,1,437,
56981675,16,0,650,1,
56991442,1484,1,1694,1676,
570016,0,148,1,942,
57011490,1,1195,1496,1,
57021449,1501,1,1701,1506,
57031,447,1511,1,188,
57041518,1,205,1523,1,
57052467,1677,17,1678,15,
57061644,1,-1,1,5,
57071679,20,1680,4,50,
570865,0,114,0,103,
57090,117,0,109,0,
5710101,0,110,0,116,
57110,68,0,101,0, 69020,68,0,101,0,
571299,0,108,0,97, 690399,0,108,0,97,
57130,114,0,97,0, 69040,114,0,97,0,
5714116,0,105,0,111, 6905116,0,105,0,111,
57150,110,0,76,0, 69060,110,0,95,0,
5716105,0,115,0,116, 690749,0,1,213,1,
57170,95,0,49,0, 69083,1,3,1,2,
57181,159,1,3,1, 69091961,22,1,49,1,
57192,1,1,1681,22, 69102509,1962,16,0,475,
57201,19,1,461,1682, 69111,15,1963,19,334,
572116,0,603,1,464, 69121,15,1964,5,6,
57221683,17,1684,15,1648, 69131,1114,1965,16,0,
57231,-1,1,5,1685, 6914332,1,1621,1966,16,
572420,1686,4,28,65, 69150,754,1,2781,1967,
691616,0,795,1,40,
69171968,16,0,639,1,
691819,1269,1,9,1235,
69191,16,1969,19,136,
69201,16,1970,5,146,
69211,2765,1971,16,0,
6922784,1,256,1972,16,
69230,206,1,1261,1973,
692416,0,206,1,509,
69251974,16,0,206,1,
69269,1975,16,0,134,
69271,2521,1976,16,0,
6928490,1,2021,840,1,
69291775,1977,16,0,206,
69301,2029,847,1,2030,
6931853,1,2031,858,1,
69322032,863,1,2033,868,
69331,277,1978,16,0,
6934206,1,2035,874,1,
69352037,879,1,2039,884,
69361,32,1979,16,0,
6937206,1,2041,890,1,
69382293,1980,16,0,206,
69391,2043,896,1,2045,
6940901,1,40,1981,16,
69410,185,1,41,1982,
694216,0,206,1,1297,
69431983,16,0,206,1,
694443,1984,16,0,206,
69451,44,1985,16,0,
6946185,1,1803,909,1,
69471804,1986,16,0,206,
69481,299,1987,16,0,
6949206,1,2480,1988,17,
69501989,15,1990,4,24,
695137,0,73,0,110,
69520,116,0,65,0,
6953114,0,103,0,69,
69540,118,0,101,0,
6955110,0,116,0,1,
6956-1,1,5,1991,20,
69571992,4,26,73,0,
6958110,0,116,0,65,
57250,114,0,103,0, 69590,114,0,103,0,
5726117,0,109,0,101, 696069,0,118,0,101,
57270,110,0,116,0, 69610,110,0,116,0,
572876,0,105,0,115, 696295,0,55,0,1,
57290,116,0,95,0, 6963367,1,3,1,2,
573050,0,1,279,1, 69641,1,1993,22,1,
57313,1,4,1,3, 6965204,1,52,1994,16,
57321687,22,1,140,1, 69660,206,1,2484,1995,
57331224,1528,1,223,1533, 696717,1996,15,1990,1,
57341,1730,1538,1,476, 6968-1,1,5,1997,20,
57351543,1,477,1549,1, 69691998,4,26,73,0,
57361231,1554,1,479,1559, 6970110,0,116,0,65,
57371,480,1564,1,1485, 69710,114,0,103,0,
57381570,1,459,1688,17, 697269,0,118,0,101,
57391689,15,1648,1,-1, 69730,110,0,116,0,
57401,5,601,1,0, 697495,0,51,0,1,
57411,0,1661,1,242, 6975363,1,3,1,2,
57421578,1,478,1583,1, 69761,1,1999,22,1,
57432506,1690,17,1691,15, 6977200,1,2567,2000,16,
57441644,1,-1,1,5, 69780,750,1,1515,2001,
5745140,1,0,1,0, 697916,0,206,1,2318,
57461645,1,1001,1588,1, 69802002,16,0,206,1,
57471002,1593,1,15,1692, 69812491,2003,17,2004,15,
574819,257,1,15,1693, 69822005,4,26,37,0,
57495,6,1,1114,1694, 698386,0,111,0,105,
575016,0,299,1,1621, 69840,100,0,65,0,
57511695,16,0,649,1, 6985114,0,103,0,69,
57522657,1696,16,0,255, 69860,118,0,101,0,
57531,40,1697,16,0, 6987110,0,116,0,1,
5754552,1,19,1147,1, 6988-1,1,5,2006,20,
57559,1113,1,16,1698, 69892007,4,28,86,0,
575619,136,1,16,1699, 6990111,0,105,0,100,
57575,139,1,256,1700, 69910,65,0,114,0,
575816,0,187,1,1261, 6992103,0,69,0,118,
57591701,16,0,187,1,
5760509,1702,16,0,187,
57611,9,1703,16,0,
5762134,1,2021,718,1,
57631775,1704,16,0,187,
57641,2029,725,1,2030,
5765731,1,2031,736,1,
57662032,741,1,2033,746,
57671,277,1705,16,0,
5768187,1,2035,752,1,
57692037,757,1,2039,762,
57701,32,1706,16,0,
5771187,1,2041,768,1,
57722293,1707,16,0,187,
57731,2043,774,1,2045,
5774779,1,40,1708,16,
57750,166,1,41,1709,
577616,0,187,1,1297,
57771710,16,0,187,1,
577843,1711,16,0,187,
57791,44,1712,16,0,
5780166,1,1803,787,1,
57811804,1713,16,0,187,
57821,299,1714,16,0,
5783187,1,2480,1715,17,
57841716,15,1717,4,12,
578537,0,69,0,118,
57860,101,0,110,0, 69930,101,0,110,0,
5787116,0,1,-1,1, 6994116,0,95,0,54,
57885,1718,20,1719,4, 69950,1,356,1,3,
578916,69,0,118,0, 69961,2,1,1,2008,
5790101,0,110,0,116, 699722,1,193,1,62,
57910,95,0,50,0, 69982009,16,0,228,1,
579253,0,1,312,1, 699963,2010,16,0,185,
57933,1,2,1,1, 70001,2495,2011,17,2012,
57941720,22,1,173,1, 700115,2005,1,-1,1,
579552,1721,16,0,187, 70025,2013,20,2014,4,
57961,2484,1722,17,1723, 700328,86,0,111,0,
579715,1717,1,-1,1, 7004105,0,100,0,65,
57985,1724,20,1725,4, 70050,114,0,103,0,
579916,69,0,118,0, 700669,0,118,0,101,
5800101,0,110,0,116, 70070,110,0,116,0,
58010,95,0,50,0, 700895,0,50,0,1,
580249,0,1,308,1, 7009352,1,3,1,2,
58033,1,2,1,1, 70101,1,2015,22,1,
58041726,22,1,169,1, 7011189,1,2575,2016,16,
58051515,1727,16,0,187, 70120,759,1,2075,2017,
58061,2318,1728,16,0, 701316,0,206,1,1574,
5807187,1,2491,1729,17, 7014921,1,1479,2018,16,
58081730,15,1717,1,-1, 70150,206,1,2580,2019,
58091,5,1731,20,1732, 701616,0,352,1,71,
58104,16,69,0,118, 70172020,16,0,206,1,
70181658,2021,16,0,790,
70191,1833,2022,16,0,
7020321,1,1834,2023,16,
70210,206,1,2337,2024,
702216,0,206,1,79,
70232025,16,0,206,1,
70241335,2026,16,0,206,
70251,322,2027,16,0,
7026206,1,76,2028,16,
70270,206,1,85,2029,
702816,0,206,1,89,
70292030,16,0,206,1,
7030346,2031,16,0,206,
70311,97,2032,16,0,
7032206,1,2106,2033,16,
70330,206,1,102,2034,
703416,0,206,1,1860,
7035943,1,2458,998,1,
70362364,949,1,2536,2035,
703716,0,633,1,2782,
70382036,16,0,206,1,
70391990,2037,16,0,206,
70401,112,2038,16,0,
7041206,1,1117,2039,16,
70420,206,1,1873,958,
70431,1875,2040,16,0,
7044436,1,1876,2041,16,
70450,206,1,2551,2042,
704616,0,642,1,124,
70472043,16,0,206,1,
70482478,2044,17,2045,15,
70491990,1,-1,1,5,
70502046,20,2047,4,26,
705173,0,110,0,116,
70520,65,0,114,0,
7053103,0,69,0,118,
58110,101,0,110,0, 70540,101,0,110,0,
5812116,0,95,0,49, 7055116,0,95,0,57,
58130,52,0,1,301, 70560,1,369,1,3,
58141,3,1,2,1, 70571,2,1,1,2048,
58151,1733,22,1,162, 705822,1,206,1,2136,
58161,62,1734,16,0, 7059965,1,2559,2049,16,
5817202,1,63,1735,16, 70600,536,1,525,2050,
58180,166,1,2495,1736, 706116,0,206,1,137,
581917,1737,15,1717,1, 70622051,16,0,206,1,
5820-1,1,5,1738,20, 7063381,2052,16,0,206,
58211739,4,16,69,0, 70641,1901,2053,16,0,
5822118,0,101,0,110, 7065206,1,1153,2054,16,
58230,116,0,95,0, 70660,206,1,151,2055,
582449,0,48,0,1, 706716,0,206,1,1407,
5825297,1,3,1,2, 70682056,16,0,206,1,
58261,1,1740,22,1, 70691659,2057,16,0,206,
5827158,1,2075,1741,16, 70701,2413,2058,16,0,
58280,187,1,1574,799, 7071206,1,406,2059,16,
58291,1479,1742,16,0, 70720,206,1,1371,2060,
5830187,1,71,1743,16, 707316,0,206,1,2105,
58310,187,1,1658,1744, 7074936,1,166,2061,16,
583216,0,672,1,1833, 70750,206,1,1622,2062,
58331745,16,0,288,1, 707616,0,206,1,1931,
58341834,1746,16,0,187, 7077983,1,1932,2063,16,
58351,2337,1747,16,0, 70780,525,1,1933,2064,
5836187,1,79,1748,16, 707916,0,206,1,431,
58370,187,1,1335,1749, 70802065,16,0,206,1,
583816,0,187,1,322, 70811585,2066,16,0,206,
58391750,16,0,187,1, 70821,182,2067,16,0,
584076,1751,16,0,187, 7083206,1,1189,2068,16,
58411,85,1752,16,0, 70840,206,1,1443,2069,
5842187,1,89,1753,16, 708516,0,206,1,1695,
58430,187,1,346,1754, 70862070,16,0,206,1,
584416,0,187,1,97, 70872198,2071,16,0,206,
58451755,16,0,187,1, 70881,447,2072,16,0,
58462106,1756,16,0,187, 7089206,1,199,2073,16,
58471,102,1757,16,0, 70900,206,1,2459,1004,
5848187,1,1860,821,1, 70911,1958,2074,16,0,
58492458,876,1,2364,827, 7092206,1,2462,1011,1,
58501,1990,1758,16,0, 70931657,1016,1,2464,1021,
5851187,1,112,1759,16, 70941,459,2075,16,0,
58520,187,1,1117,1760, 7095206,1,462,2076,16,
585316,0,187,1,1873, 70960,206,1,2471,2077,
5854835,1,1875,1761,16, 709717,2078,15,2079,4,
58550,400,1,1876,1762, 709836,37,0,75,0,
585616,0,187,1,124, 7099101,0,121,0,73,
58571763,16,0,187,1, 71000,110,0,116,0,
58582478,1764,17,1765,15, 710173,0,110,0,116,
58591717,1,-1,1,5, 71020,65,0,114,0,
58601766,20,1767,4,16, 7103103,0,69,0,118,
71040,101,0,110,0,
7105116,0,1,-1,1,
71065,2080,20,2081,4,
710738,75,0,101,0,
7108121,0,73,0,110,
71090,116,0,73,0,
7110110,0,116,0,65,
71110,114,0,103,0,
586169,0,118,0,101, 711269,0,118,0,101,
58620,110,0,116,0, 71130,110,0,116,0,
586395,0,50,0,55, 711495,0,49,0,1,
58640,1,314,1,3, 7115376,1,3,1,2,
58651,2,1,1,1768, 71161,1,2082,22,1,
586622,1,175,1,2136, 7117213,1,2472,2083,17,
5867842,1,381,1769,16, 71182084,15,2085,4,36,
58680,187,1,2641,1770, 711937,0,73,0,110,
586916,0,642,1,137, 71200,116,0,86,0,
58701771,16,0,187,1, 7121101,0,99,0,86,
58711901,1772,16,0,187, 71220,101,0,99,0,
58721,2658,1773,16,0, 712365,0,114,0,103,
5873187,1,1153,1774,16, 71240,69,0,118,0,
58740,187,1,151,1775, 7125101,0,110,0,116,
587516,0,187,1,1407, 71260,1,-1,1,5,
58761776,16,0,187,1, 71272086,20,2087,4,38,
58771659,1777,16,0,187, 712873,0,110,0,116,
58781,2413,1778,16,0, 71290,86,0,101,0,
5879187,1,406,1779,16, 713099,0,86,0,101,
58800,187,1,1371,1780, 71310,99,0,65,0,
588116,0,187,1,2105, 7132114,0,103,0,69,
5882814,1,166,1781,16,
58830,187,1,525,1782,
588416,0,187,1,1622,
58851783,16,0,187,1,
58861931,861,1,1932,1784,
588716,0,456,1,1933,
58881785,16,0,187,1,
5889431,1786,16,0,187,
58901,1585,1787,16,0,
5891187,1,182,1788,16,
58920,187,1,1189,1789,
589316,0,187,1,1443,
58941790,16,0,187,1,
58951695,1791,16,0,187,
58961,2198,1792,16,0,
5897187,1,447,1793,16,
58980,187,1,199,1794,
589916,0,187,1,2459,
5900882,1,1958,1795,16,
59010,187,1,2462,889,
59021,1657,894,1,2464,
5903899,1,459,1796,16,
59040,187,1,462,1797,
590516,0,187,1,2471,
59061798,17,1799,15,1717,
59071,-1,1,5,1800,
590820,1801,4,16,69,
59090,118,0,101,0, 71330,118,0,101,0,
5910110,0,116,0,95, 7134110,0,116,0,95,
59110,51,0,52,0, 71350,49,0,1,375,
59121,321,1,3,1,
59132,1,1,1802,22,
59141,182,1,2472,1803,
591517,1804,15,1717,1,
5916-1,1,5,1805,20,
59171806,4,16,69,0,
5918118,0,101,0,110,
59190,116,0,95,0,
592051,0,51,0,1,
5921320,1,3,1,2,
59221,1,1807,22,1,
5923181,1,2473,1808,17,
59241809,15,1717,1,-1,
59251,5,1810,20,1811,
59264,16,69,0,118,
59270,101,0,110,0,
5928116,0,95,0,51,
59290,50,0,1,319,
59301,3,1,2,1, 71361,3,1,2,1,
59311,1812,22,1,180, 71371,2088,22,1,212,
59321,2474,1813,17,1814, 71381,2473,2089,17,2090,
593315,1717,1,-1,1, 713915,2091,4,36,37,
59345,1815,20,1816,4, 71400,73,0,110,0,
593516,69,0,118,0, 7141116,0,82,0,111,
5936101,0,110,0,116, 71420,116,0,82,0,
59370,95,0,51,0, 7143111,0,116,0,65,
593849,0,1,318,1, 71440,114,0,103,0,
59393,1,2,1,1,
59401817,22,1,179,1,
59412475,1818,17,1819,15,
59421717,1,-1,1,5,
59431820,20,1821,4,16,
594469,0,118,0,101, 714569,0,118,0,101,
59450,110,0,116,0, 71460,110,0,116,0,
594695,0,51,0,48, 71471,-1,1,5,2092,
59470,1,317,1,3, 714820,2093,4,38,73,
59481,2,1,1,1822, 71490,110,0,116,0,
594922,1,178,1,2476, 715082,0,111,0,116,
59501823,17,1824,15,1717, 71510,82,0,111,0,
59511,-1,1,5,1825, 7152116,0,65,0,114,
595220,1826,4,16,69, 71530,103,0,69,0,
59530,118,0,101,0,
5954110,0,116,0,95,
59550,50,0,57,0,
59561,316,1,3,1,
59572,1,1,1827,22,
59581,177,1,2477,1828,
595917,1829,15,1717,1,
5960-1,1,5,1830,20,
59611831,4,16,69,0,
5962118,0,101,0,110, 7154118,0,101,0,110,
59630,116,0,95,0, 71550,116,0,95,0,
596450,0,56,0,1, 715649,0,1,374,1,
5965315,1,3,1,2, 71573,1,2,1,1,
59661,1,1832,22,1, 71582094,22,1,211,1,
5967176,1,2227,908,1, 71592474,2095,17,2096,15,
59682479,1833,17,1834,15, 71602097,4,30,37,0,
59691717,1,-1,1,5, 716186,0,101,0,99,
59701835,20,1836,4,16, 71620,116,0,111,0,
7163114,0,65,0,114,
71640,103,0,69,0,
7165118,0,101,0,110,
71660,116,0,1,-1,
71671,5,2098,20,2099,
71684,32,86,0,101,
71690,99,0,116,0,
7170111,0,114,0,65,
71710,114,0,103,0,
597169,0,118,0,101, 717269,0,118,0,101,
59720,110,0,116,0, 71730,110,0,116,0,
597395,0,50,0,54, 717495,0,51,0,1,
59740,1,313,1,3, 7175373,1,3,1,2,
59751,2,1,1,1837, 71761,1,2100,22,1,
597622,1,174,1,1225, 7177210,1,2475,2101,17,
59771838,16,0,187,1, 71782102,15,2097,1,-1,
59782481,1839,17,1840,15, 71791,5,2103,20,2104,
59791717,1,-1,1,5, 71804,32,86,0,101,
59801841,20,1842,4,16, 71810,99,0,116,0,
7182111,0,114,0,65,
71830,114,0,103,0,
598169,0,118,0,101, 718469,0,118,0,101,
59820,110,0,116,0, 71850,110,0,116,0,
598395,0,50,0,52, 718695,0,50,0,1,
59840,1,311,1,3, 7187372,1,3,1,2,
59851,2,1,1,1843, 71881,1,2105,22,1,
598622,1,172,1,2482, 7189209,1,2476,2106,17,
59871844,17,1845,15,1717, 71902107,15,2097,1,-1,
59881,-1,1,5,1846, 71911,5,2108,20,2109,
598920,1847,4,16,69, 71924,32,86,0,101,
71930,99,0,116,0,
7194111,0,114,0,65,
71950,114,0,103,0,
719669,0,118,0,101,
71970,110,0,116,0,
719895,0,49,0,1,
7199371,1,3,1,2,
72001,1,2110,22,1,
7201208,1,2477,2111,17,
72022112,15,1990,1,-1,
72031,5,2113,20,2114,
72044,28,73,0,110,
72050,116,0,65,0,
7206114,0,103,0,69,
59900,118,0,101,0, 72070,118,0,101,0,
5991110,0,116,0,95, 7208110,0,116,0,95,
59920,50,0,51,0, 72090,49,0,48,0,
59931,310,1,3,1, 72101,370,1,3,1,
59942,1,1,1848,22, 72112,1,1,2115,22,
59951,171,1,2483,1849, 72121,207,1,2227,1030,
599617,1850,15,1717,1, 72131,2479,2116,17,2117,
5997-1,1,5,1851,20, 721415,1990,1,-1,1,
59981852,4,16,69,0, 72155,2118,20,2119,4,
721626,73,0,110,0,
7217116,0,65,0,114,
72180,103,0,69,0,
5999118,0,101,0,110, 7219118,0,101,0,110,
60000,116,0,95,0, 72200,116,0,95,0,
600150,0,50,0,1, 722156,0,1,368,1,
6002309,1,3,1,2, 72223,1,2,1,1,
60031,1,1853,22,1, 72232120,22,1,205,1,
6004170,1,1731,1854,16, 72241225,2121,16,0,206,
60050,187,1,2485,1855, 72251,2481,2122,17,2123,
600617,1856,15,1717,1, 722615,1990,1,-1,1,
6007-1,1,5,1857,20, 72275,2124,20,2125,4,
60081858,4,16,69,0, 722826,73,0,110,0,
7229116,0,65,0,114,
72300,103,0,69,0,
6009118,0,101,0,110, 7231118,0,101,0,110,
60100,116,0,95,0, 72320,116,0,95,0,
601150,0,48,0,1, 723354,0,1,366,1,
6012307,1,3,1,2, 72343,1,2,1,1,
60131,1,1859,22,1, 72352126,22,1,203,1,
6014168,1,2486,1860,17, 72362482,2127,17,2128,15,
60151861,15,1717,1,-1, 72371990,1,-1,1,5,
60161,5,1862,20,1863, 72382129,20,2130,4,26,
60174,16,69,0,118, 723973,0,110,0,116,
72400,65,0,114,0,
7241103,0,69,0,118,
60180,101,0,110,0, 72420,101,0,110,0,
6019116,0,95,0,49, 7243116,0,95,0,53,
60200,57,0,1,306, 72440,1,365,1,3,
60211,3,1,2,1, 72451,2,1,1,2131,
60221,1864,22,1,167, 724622,1,202,1,2483,
60231,2487,1865,17,1866, 72472132,17,2133,15,1990,
602415,1717,1,-1,1, 72481,-1,1,5,2134,
60255,1867,20,1868,4, 724920,2135,4,26,73,
602616,69,0,118,0, 72500,110,0,116,0,
725165,0,114,0,103,
72520,69,0,118,0,
6027101,0,110,0,116, 7253101,0,110,0,116,
60280,95,0,49,0, 72540,95,0,52,0,
602956,0,1,305,1, 72551,364,1,3,1,
60303,1,2,1,1, 72562,1,1,2136,22,
60311869,22,1,166,1, 72571,201,1,1731,2137,
60322488,1870,17,1871,15, 725816,0,206,1,2485,
60331717,1,-1,1,5, 72592138,17,2139,15,1990,
60341872,20,1873,4,16, 72601,-1,1,5,2140,
726120,2141,4,26,73,
72620,110,0,116,0,
726365,0,114,0,103,
72640,69,0,118,0,
7265101,0,110,0,116,
72660,95,0,50,0,
72671,362,1,3,1,
72682,1,1,2142,22,
72691,199,1,2486,2143,
727017,2144,15,1990,1,
7271-1,1,5,2145,20,
72722146,4,26,73,0,
7273110,0,116,0,65,
72740,114,0,103,0,
603569,0,118,0,101, 727569,0,118,0,101,
60360,110,0,116,0, 72760,110,0,116,0,
603795,0,49,0,55, 727795,0,49,0,1,
60380,1,304,1,3, 7278361,1,3,1,2,
60391,2,1,1,1874, 72791,1,2147,22,1,
604022,1,165,1,2489, 7280198,1,2487,2148,17,
60411875,17,1876,15,1717, 72812149,15,2150,4,24,
60421,-1,1,5,1877, 728237,0,75,0,101,
604320,1878,4,16,69, 72830,121,0,65,0,
7284114,0,103,0,69,
72850,118,0,101,0,
7286110,0,116,0,1,
7287-1,1,5,2151,20,
72882152,4,26,75,0,
7289101,0,121,0,65,
72900,114,0,103,0,
729169,0,118,0,101,
72920,110,0,116,0,
729395,0,50,0,1,
7294360,1,3,1,2,
72951,1,2153,22,1,
7296197,1,2488,2154,17,
72972155,15,2150,1,-1,
72981,5,2156,20,2157,
72994,26,75,0,101,
73000,121,0,65,0,
7301114,0,103,0,69,
60440,118,0,101,0, 73020,118,0,101,0,
6045110,0,116,0,95, 7303110,0,116,0,95,
60460,49,0,54,0, 73040,49,0,1,359,
60471,303,1,3,1, 73051,3,1,2,1,
60482,1,1,1879,22, 73061,2158,22,1,196,
60491,164,1,2490,1880, 73071,2489,2159,17,2160,
605017,1881,15,1717,1, 730815,2005,1,-1,1,
6051-1,1,5,1882,20, 73095,2161,20,2162,4,
60521883,4,16,69,0, 731028,86,0,111,0,
6053118,0,101,0,110, 7311105,0,100,0,65,
60540,116,0,95,0, 73120,114,0,103,0,
605549,0,53,0,1,
6056302,1,3,1,2,
60571,1,1884,22,1,
6058163,1,1989,916,1,
60592492,1885,17,1886,15,
60601717,1,-1,1,5,
60611887,20,1888,4,16,
606269,0,118,0,101, 731369,0,118,0,101,
60630,110,0,116,0, 73140,110,0,116,0,
606495,0,49,0,51, 731595,0,56,0,1,
60650,1,300,1,3, 7316358,1,3,1,2,
60661,2,1,1,1889, 73171,1,2163,22,1,
606722,1,161,1,2493, 7318195,1,2490,2164,17,
60681890,17,1891,15,1717, 73192165,15,2005,1,-1,
60691,-1,1,5,1892, 73201,5,2166,20,2167,
607020,1893,4,16,69, 73214,28,86,0,111,
73220,105,0,100,0,
732365,0,114,0,103,
73240,69,0,118,0,
7325101,0,110,0,116,
73260,95,0,55,0,
73271,357,1,3,1,
73282,1,1,2168,22,
73291,194,1,1989,1038,
73301,2492,2169,17,2170,
733115,2005,1,-1,1,
73325,2171,20,2172,4,
733328,86,0,111,0,
7334105,0,100,0,65,
73350,114,0,103,0,
733669,0,118,0,101,
73370,110,0,116,0,
733895,0,53,0,1,
7339355,1,3,1,2,
73401,1,2173,22,1,
7341192,1,2493,2174,17,
73422175,15,2005,1,-1,
73431,5,2176,20,2177,
73444,28,86,0,111,
73450,105,0,100,0,
734665,0,114,0,103,
73470,69,0,118,0,
7348101,0,110,0,116,
73490,95,0,52,0,
73501,354,1,3,1,
73512,1,1,2178,22,
73521,191,1,2494,2179,
735317,2180,15,2005,1,
7354-1,1,5,2181,20,
73552182,4,28,86,0,
7356111,0,105,0,100,
73570,65,0,114,0,
7358103,0,69,0,118,
73590,101,0,110,0,
7360116,0,95,0,51,
73610,1,353,1,3,
73621,2,1,1,2183,
736322,1,190,1,236,
73642184,16,0,206,1,
73652496,2185,17,2186,15,
73662005,1,-1,1,5,
73672187,20,2188,4,28,
736886,0,111,0,105,
73690,100,0,65,0,
7370114,0,103,0,69,
60710,118,0,101,0, 73710,118,0,101,0,
6072110,0,116,0,95, 7372110,0,116,0,95,
60730,49,0,50,0, 73730,49,0,1,351,
60741,299,1,3,1, 73741,3,1,2,1,
60752,1,1,1894,22, 73751,2189,22,1,188,
60761,160,1,2494,1895, 73761,2497,2190,17,2191,
607717,1896,15,1717,1, 737715,2192,4,12,37,
6078-1,1,5,1897,20, 73780,69,0,118,0,
60791898,4,16,69,0, 7379101,0,110,0,116,
6080118,0,101,0,110, 73800,1,-1,1,5,
60810,116,0,95,0, 73812193,20,2194,4,14,
608249,0,49,0,1,
6083298,1,3,1,2,
60841,1,1899,22,1,
6085159,1,236,1900,16,
60860,187,1,2496,1901,
608717,1902,15,1717,1,
6088-1,1,5,1903,20,
60891904,4,14,69,0,
6090118,0,101,0,110,
60910,116,0,95,0,
609257,0,1,296,1,
60933,1,2,1,1,
60941905,22,1,157,1,
60952497,1906,17,1907,15,
60961717,1,-1,1,5,
60971908,20,1909,4,14,
609869,0,118,0,101, 738269,0,118,0,101,
60990,110,0,116,0, 73830,110,0,116,0,
610095,0,56,0,1, 738495,0,56,0,1,
6101295,1,3,1,2, 7385350,1,3,1,2,
61021,1,1910,22,1, 73861,1,2195,22,1,
6103156,1,2498,1911,17, 7387187,1,2498,2196,17,
61041912,15,1717,1,-1, 73882197,15,2192,1,-1,
61051,5,1913,20,1914, 73891,5,2198,20,2199,
61064,14,69,0,118, 73904,14,69,0,118,
61070,101,0,110,0, 73910,101,0,110,0,
6108116,0,95,0,55, 7392116,0,95,0,55,
61090,1,294,1,3, 73930,1,349,1,3,
61101,2,1,1,1915, 73941,2,1,1,2200,
611122,1,155,1,2499, 739522,1,186,1,2499,
61121916,17,1917,15,1717, 73962201,17,2202,15,2192,
61131,-1,1,5,1918, 73971,-1,1,5,2203,
611420,1919,4,14,69, 739820,2204,4,14,69,
61150,118,0,101,0, 73990,118,0,101,0,
6116110,0,116,0,95, 7400110,0,116,0,95,
61170,54,0,1,293, 74010,54,0,1,348,
61181,3,1,2,1, 74021,3,1,2,1,
61191,1920,22,1,154, 74031,2205,22,1,185,
61201,2500,1921,17,1922, 74041,2500,2206,17,2207,
612115,1717,1,-1,1, 740515,2192,1,-1,1,
61225,1923,20,1924,4, 74065,2208,20,2209,4,
612314,69,0,118,0, 740714,69,0,118,0,
6124101,0,110,0,116, 7408101,0,110,0,116,
61250,95,0,53,0, 74090,95,0,53,0,
61261,292,1,3,1, 74101,347,1,3,1,
61272,1,1,1925,22, 74112,1,1,2210,22,
61281,153,1,2501,1926, 74121,184,1,2501,2211,
612917,1927,15,1717,1, 741317,2212,15,2192,1,
6130-1,1,5,1928,20, 7414-1,1,5,2213,20,
61311929,4,14,69,0, 74152214,4,14,69,0,
6132118,0,101,0,110, 7416118,0,101,0,110,
61330,116,0,95,0, 74170,116,0,95,0,
613452,0,1,291,1, 741852,0,1,346,1,
61353,1,2,1,1, 74193,1,2,1,1,
61361930,22,1,152,1, 74202215,22,1,183,1,
61372502,1931,17,1932,15, 74212502,2216,17,2217,15,
61381717,1,-1,1,5, 74222192,1,-1,1,5,
61391933,20,1934,4,14, 74232218,20,2219,4,14,
614069,0,118,0,101, 742469,0,118,0,101,
61410,110,0,116,0, 74250,110,0,116,0,
614295,0,51,0,1, 742695,0,51,0,1,
6143290,1,3,1,2, 7427345,1,3,1,2,
61441,1,1935,22,1, 74281,1,2220,22,1,
6145151,1,2503,1936,17, 7429182,1,2503,2221,17,
61461937,15,1717,1,-1, 74302222,15,2192,1,-1,
61471,5,1938,20,1939, 74311,5,2223,20,2224,
61484,14,69,0,118, 74324,14,69,0,118,
61490,101,0,110,0, 74330,101,0,110,0,
6150116,0,95,0,50, 7434116,0,95,0,50,
61510,1,289,1,3, 74350,1,344,1,3,
61521,2,1,1,1940, 74361,2,1,1,2225,
615322,1,150,1,2504, 743722,1,181,1,2504,
61541941,17,1942,15,1717, 74382226,17,2227,15,2192,
61551,-1,1,5,1943, 74391,-1,1,5,2228,
615620,1944,4,14,69, 744020,2229,4,14,69,
61570,118,0,101,0, 74410,118,0,101,0,
6158110,0,116,0,95, 7442110,0,116,0,95,
61590,49,0,1,288, 74430,49,0,1,343,
61601,3,1,2,1, 74441,3,1,2,1,
61611,1945,22,1,149, 74451,2230,22,1,180,
61621,2505,1946,16,0, 74461,2505,2231,16,0,
6163433,1,217,1947,16, 7447469,1,217,2232,16,
61640,187,1,1756,1948, 74480,206,1,1756,2233,
616516,0,187,1,17, 744916,0,206,1,17,
61661949,19,154,1,17, 74502234,19,163,1,17,
61671950,5,117,1,1, 74512235,5,134,1,1,
61681951,17,1952,15,1953, 74522236,17,2237,15,2238,
61694,18,37,0,84, 74534,18,37,0,84,
61700,121,0,112,0, 74540,121,0,112,0,
6171101,0,110,0,97, 7455101,0,110,0,97,
61720,109,0,101,0, 74560,109,0,101,0,
61731,-1,1,5,1954, 74571,-1,1,5,2239,
617420,1955,4,20,84, 745820,2240,4,20,84,
61750,121,0,112,0, 74590,121,0,112,0,
6176101,0,110,0,97, 7460101,0,110,0,97,
61770,109,0,101,0, 74610,109,0,101,0,
617895,0,55,0,1, 746295,0,55,0,1,
6179287,1,3,1,2, 7463342,1,3,1,2,
61801,1,1956,22,1, 74641,1,2241,22,1,
6181148,1,2,1957,17, 7465179,1,2,2242,17,
61821958,15,1953,1,-1, 74662243,15,2238,1,-1,
61831,5,1959,20,1960, 74671,5,2244,20,2245,
61844,20,84,0,121, 74684,20,84,0,121,
61850,112,0,101,0, 74690,112,0,101,0,
6186110,0,97,0,109, 7470110,0,97,0,109,
61870,101,0,95,0, 74710,101,0,95,0,
618854,0,1,286,1, 747254,0,1,341,1,
61893,1,2,1,1, 74733,1,2,1,1,
61901961,22,1,147,1, 74742246,22,1,178,1,
61913,1962,17,1963,15, 74753,2247,17,2248,15,
61921953,1,-1,1,5, 74762238,1,-1,1,5,
61931964,20,1965,4,20, 74772249,20,2250,4,20,
619484,0,121,0,112, 747884,0,121,0,112,
61950,101,0,110,0, 74790,101,0,110,0,
619697,0,109,0,101, 748097,0,109,0,101,
61970,95,0,53,0, 74810,95,0,53,0,
61981,285,1,3,1, 74821,340,1,3,1,
61992,1,1,1966,22, 74832,1,1,2251,22,
62001,146,1,4,1967, 74841,177,1,4,2252,
620117,1968,15,1953,1, 748517,2253,15,2238,1,
6202-1,1,5,1969,20, 7486-1,1,5,2254,20,
62031970,4,20,84,0, 74872255,4,20,84,0,
6204121,0,112,0,101, 7488121,0,112,0,101,
62050,110,0,97,0, 74890,110,0,97,0,
6206109,0,101,0,95, 7490109,0,101,0,95,
62070,52,0,1,284, 74910,52,0,1,339,
62081,3,1,2,1, 74921,3,1,2,1,
62091,1971,22,1,145, 74931,2256,22,1,176,
62101,5,1972,17,1973, 74941,5,2257,17,2258,
621115,1953,1,-1,1, 749515,2238,1,-1,1,
62125,1974,20,1975,4, 74965,2259,20,2260,4,
621320,84,0,121,0, 749720,84,0,121,0,
6214112,0,101,0,110, 7498112,0,101,0,110,
62150,97,0,109,0, 74990,97,0,109,0,
6216101,0,95,0,51, 7500101,0,95,0,51,
62170,1,283,1,3, 75010,1,338,1,3,
62181,2,1,1,1976, 75021,2,1,1,2261,
621922,1,144,1,6, 750322,1,175,1,6,
62201977,17,1978,15,1953, 75042262,17,2263,15,2238,
62211,-1,1,5,1979, 75051,-1,1,5,2264,
622220,1980,4,20,84, 750620,2265,4,20,84,
62230,121,0,112,0, 75070,121,0,112,0,
6224101,0,110,0,97, 7508101,0,110,0,97,
62250,109,0,101,0, 75090,109,0,101,0,
622695,0,50,0,1, 751095,0,50,0,1,
6227282,1,3,1,2, 7511337,1,3,1,2,
62281,1,1981,22,1, 75121,1,2266,22,1,
6229143,1,7,1982,17, 7513174,1,7,2267,17,
62301983,15,1953,1,-1, 75142268,15,2238,1,-1,
62311,5,1984,20,1985, 75151,5,2269,20,2270,
62324,20,84,0,121, 75164,20,84,0,121,
62330,112,0,101,0, 75170,112,0,101,0,
6234110,0,97,0,109, 7518110,0,97,0,109,
62350,101,0,95,0, 75190,101,0,95,0,
623649,0,1,281,1, 752049,0,1,336,1,
62373,1,2,1,1, 75213,1,2,1,1,
62381986,22,1,142,1, 75222271,22,1,173,1,
62391514,1108,1,9,1113, 75231514,1230,1,9,1235,
62401,10,1642,1,262, 75241,10,1889,1,262,
62411119,1,1267,1125,1, 75251241,1,1267,1247,1,
6242481,1646,1,1521,1130, 75262775,2272,16,0,792,
62431,1773,1987,16,0, 75271,1521,1252,1,1773,
6244234,1,19,1147,1, 75282273,16,0,264,1,
624520,1988,16,0,152, 75292527,1895,1,19,1269,
62461,2281,1154,1,525, 75301,20,2274,16,0,
62471216,1,30,1654,1, 7531161,1,2531,2275,17,
6248283,1172,1,1010,1989, 75322276,15,2277,4,66,
624916,0,593,1,40, 753337,0,73,0,110,
62501177,1,41,1659,1, 75340,116,0,86,0,
625142,1662,1,44,1183, 7535101,0,99,0,86,
62521,1260,1096,1,47, 75360,101,0,99,0,
62531184,1,1303,1307,1, 753765,0,114,0,103,
625449,1196,1,50,1201, 75380,117,0,109,0,
62551,48,1190,1,305, 7539101,0,110,0,116,
62561211,1,51,1206,1,
625761,1990,16,0,194,
62581,63,1222,1,66,
62591228,1,67,1233,1,
62601478,1458,1,69,1243,
62611,70,1248,1,68,
62621238,1,73,1991,16,
62630,204,1,74,1253,
62641,1013,1258,1,2335,
62651992,16,0,239,1,
6266328,1302,1,1048,1344,
62671,82,1280,1,1840,
62681993,16,0,303,1,
62692515,1994,16,0,436,
62701,1341,1297,1,1094,
62711995,16,0,666,1,
62721096,1312,1,93,1318,
62731,1550,1323,1,352,
62741349,1,1011,1102,1,
6275107,1338,1,1114,1343,
62761,1871,1996,16,0,
6277313,1,1370,1453,1,
6278118,1355,1,1123,1360,
62791,1332,1263,1,1377,
62801371,1,375,1376,1,
62811882,1997,16,0,327,
62821,377,1381,1,827,
62831331,1,380,1391,1,
6284130,1414,1,2074,1998,
628516,0,554,1,371,
62861365,1,373,1409,1,
62871012,1999,16,0,595,
62881,379,1386,1,143,
62891419,1,1152,1426,1,
62901406,1431,1,1159,1438,
62911,157,1443,1,1413,
62921448,1,883,1397,1,
62931296,1167,1,172,1469,
62941,1665,1474,1,1939,
62952000,16,0,435,1,
62961188,1479,1,1442,1484,
62971,188,1518,1,942,
62981490,1,1195,1496,1,
62991449,1501,1,1701,1506,
63001,447,1511,1,205,
63011523,1,2467,1677,1,
6302464,1683,1,2642,1669,
63031,2197,2001,16,0,
6304662,1,1224,1528,1,
6305223,1533,1,1730,1538,
63061,2651,2002,16,0,
6307570,1,477,1549,1,
63081231,1554,1,479,1559,
63091,480,1564,1,1485,
63101570,1,459,1688,1,
6311476,1543,1,242,1578,
63121,478,1583,1,2506,
63131690,1,1001,1588,1,
63141002,1593,1,18,2003,
631519,490,1,18,2004,
63165,84,1,1011,1102,
63171,1012,2005,16,0,
6318488,1,1013,1258,1,
6319262,1119,1,1267,2006,
632016,0,488,1,515,
63212007,16,0,488,1,
63221521,2008,16,0,488,
63231,525,1216,1,283,
63241172,1,2299,2009,16,
63250,488,1,42,2010,
632616,0,488,1,40,
63271177,1,44,1183,1,
632847,1184,1,1303,2011,
632916,0,488,1,1555,
63302012,16,0,488,1,
633150,1201,1,48,1190,
63321,49,1196,1,51,
63331206,1,63,1222,1,
6334305,1211,1,66,1228,
63351,67,1233,1,68,
63361238,1,69,1243,1,
633770,1248,1,73,2013,
633816,0,488,1,74,
63391253,1,328,1302,1,
63401048,2014,16,0,488,
63411,82,2015,16,0,
6342488,1,1840,2016,16,
63430,488,1,1591,2017,
634416,0,488,1,1341,
63452018,16,0,488,1,
63461096,1312,1,93,1318,
63471,352,1349,1,107,
63482019,16,0,488,1,
63491114,1343,1,118,2020,
635016,0,488,1,1123,
63512021,16,0,488,1,
6352371,1365,1,1628,2022,
635316,0,488,1,375,
63541376,1,1882,2023,16,
63550,488,1,377,1381,
63561,379,1386,1,380,
63571391,1,883,2024,16,
63580,488,1,373,1409,
63591,130,2025,16,0,
6360488,1,143,2026,16,
63610,488,1,387,2027,
636216,0,488,1,2664,
63632028,16,0,488,1,
63641159,2029,16,0,488,
63651,157,2030,16,0,
6366488,1,1413,2031,16,
63670,488,1,1665,2032,
636816,0,488,1,412,
63692033,16,0,488,1,
63701377,2034,16,0,488,
63711,172,2035,16,0,
6372488,1,1939,2036,16,
63730,488,1,437,2037,
637416,0,488,1,188,
63752038,16,0,488,1,
6376942,2039,16,0,488,
63771,1195,2040,16,0,
6378488,1,1449,2041,16,
63790,488,1,1701,2042,
638016,0,488,1,447,
63811511,1,205,2043,16,
63820,488,1,827,2044,
638316,0,488,1,223,
63842045,16,0,488,1,
6385476,1543,1,477,1549,
63861,1231,2046,16,0,
6387488,1,479,1559,1,
6388480,1564,1,1485,2047,
638916,0,488,1,1737,
63902048,16,0,488,1,
6391242,2049,16,0,488,
63921,478,1583,1,1001,
63931588,1,1002,1593,1,
639419,2050,19,225,1,
639519,2051,5,176,1,
6396256,2052,16,0,223,
63971,1261,2053,16,0,
6398223,1,1011,1102,1,
63991012,2054,16,0,455,
64001,2458,876,1,262,
64011119,1,1267,2055,16,
64020,455,1,2021,718,
64031,1521,2056,16,0,
6404455,1,1775,2057,16,
64050,223,1,2029,725,
64061,2030,731,1,2031,
6407736,1,2032,741,1,
64082033,746,1,277,2058,
640916,0,223,1,2035,
6410752,1,2037,757,1,
64112039,762,1,32,2059,
641216,0,223,1,2464,
6413899,1,2293,2060,16,
64140,223,1,2043,774,
64151,2045,779,1,2299,
64162061,16,0,455,1,
641741,2062,16,0,223,
64181,42,2063,16,0,
6419455,1,40,1177,1,
642044,1183,1,43,2064,
642116,0,223,1,1804,
64222065,16,0,223,1,
642348,1190,1,49,1196,
64241,47,1184,1,51,
64251206,1,52,2066,16,
64260,223,1,50,1201,
64271,305,1211,1,1096,
64281312,1,1515,2067,16,
64290,223,1,2318,2068,
643016,0,223,1,283,
64311172,1,63,1222,1,
643266,1228,1,67,1233,
64331,68,1238,1,69,
64341243,1,70,1248,1,
643571,2069,16,0,223,
64361,73,2070,16,0,
6437455,1,74,1253,1,
64381013,1258,1,76,2071,
643916,0,223,1,1834,
64402072,16,0,223,1,
64412337,2073,16,0,223,
64421,79,2074,16,0,
6443223,1,1335,2075,16,
64440,223,1,299,2076,
644516,0,223,1,82,
64462077,16,0,455,1,
64471840,2078,16,0,455,
64481,1297,2079,16,0,
6449223,1,85,2080,16,
64500,223,1,1341,2081,
645116,0,455,1,89,
64522082,16,0,223,1,
64531303,2083,16,0,455,
64541,509,2084,16,0,
6455223,1,93,1318,1,
6456322,2085,16,0,223,
64571,97,2086,16,0,
6458223,1,2041,768,1,
64591555,2087,16,0,455,
64601,827,2088,16,0,
6461455,1,102,2089,16,
64620,223,1,1860,821,
64631,1803,787,1,2364,
6464827,1,107,2090,16,
64650,455,1,1114,1343,
64661,112,2091,16,0,
6467223,1,1117,2092,16,
64680,223,1,352,1349,
64691,1873,835,1,118,
64702093,16,0,455,1,
64711123,2094,16,0,455,
64721,371,1365,1,515,
64732095,16,0,455,1,
64741377,2096,16,0,455,
64751,124,2097,16,0,
6476223,1,1882,2098,16,
64770,455,1,377,1381,
64781,379,1386,1,380,
64791391,1,130,2099,16,
64800,455,1,346,2100,
648116,0,223,1,2075,
64822101,16,0,223,1,
6483373,1409,1,387,2102,
648416,0,455,1,137,
64852103,16,0,223,1,
6486143,2104,16,0,455,
64871,1901,2105,16,0,
6488223,1,1048,2106,16,
64890,455,1,2658,2107,
649016,0,223,1,1153,
64912108,16,0,223,1,
6492375,1376,1,151,2109,
649316,0,223,1,1407,
64942110,16,0,223,1,
64951659,2111,16,0,223,
64961,2413,2112,16,0,
6497223,1,1159,2113,16,
64980,455,1,381,2114,
649916,0,223,1,157,
65002115,16,0,455,1,
65011413,2116,16,0,455,
65021,883,2117,16,0,
6503455,1,1371,2118,16,
65040,223,1,328,1302,
65051,2105,814,1,2106,
65062119,16,0,223,1,
6507166,2120,16,0,223,
65081,525,2121,16,0,
6509223,1,1622,2122,16,
65100,223,1,406,2123,
651116,0,223,1,1574,
6512799,1,172,2124,16,
65130,455,1,1931,861,
65141,412,2125,16,0,
6515455,1,1933,2126,16,
65160,223,1,1876,2127,
651716,0,223,1,431,
65182128,16,0,223,1,
65191585,2129,16,0,223,
65201,182,2130,16,0,
6521223,1,1628,2131,16,
65220,455,1,1189,2132,
652316,0,223,1,437,
65242133,16,0,455,1,
65251591,2134,16,0,455,
65261,188,2135,16,0,
6527455,1,1695,2136,16,
65280,223,1,2198,2137,
652916,0,223,1,1195,
65302138,16,0,455,1,
65311449,2139,16,0,455,
65321,1701,2140,16,0,
6533455,1,447,2141,16,
65340,223,1,199,2142,
653516,0,223,1,2459,
6536882,1,1958,2143,16,
65370,223,1,2462,889,
65381,1657,894,1,205,
65392144,16,0,455,1,
6540459,2145,16,0,223,
65411,462,2146,16,0,
6542223,1,1665,2147,16,
65430,455,1,217,2148,
654416,0,223,1,2227,
6545908,1,942,2149,16,
65460,455,1,1225,2150,
654716,0,223,1,223,
65482151,16,0,455,1,
65491479,2152,16,0,223,
65501,1731,2153,16,0,
6551223,1,477,1549,1,
65521231,2154,16,0,455,
65531,479,1559,1,480,
65541564,1,1485,2155,16,
65550,455,1,1737,2156,
655616,0,455,1,1989,
6557916,1,1990,2157,16,
65580,223,1,1443,2158,
655916,0,223,1,236,
65602159,16,0,223,1,
65612136,842,1,2664,2160,
656216,0,455,1,476,
65631543,1,242,2161,16,
65640,455,1,478,1583,
65651,1939,2162,16,0,
6566455,1,1001,1588,1,
65671002,1593,1,1756,2163,
656816,0,223,1,20,
65692164,19,442,1,20,
65702165,5,84,1,1011,
65711102,1,1012,2166,16,
65720,440,1,1013,1258,
65731,262,1119,1,1267,
65742167,16,0,440,1,
6575515,2168,16,0,440,
65761,1521,2169,16,0,
6577440,1,525,1216,1,
6578283,1172,1,2299,2170,
657916,0,440,1,42,
65802171,16,0,440,1,
658140,1177,1,44,1183,
65821,47,1184,1,1303,
65832172,16,0,440,1,
65841555,2173,16,0,440,
65851,50,1201,1,48,
65861190,1,49,1196,1,
658751,1206,1,63,1222,
65881,305,1211,1,66,
65891228,1,67,1233,1,
659068,1238,1,69,1243,
65911,70,1248,1,73,
65922174,16,0,440,1,
659374,1253,1,328,2175,
659416,0,440,1,1048,
65952176,16,0,440,1,
659682,2177,16,0,440,
65971,1840,2178,16,0,
6598440,1,1591,2179,16,
65990,440,1,1341,2180,
660016,0,440,1,1096,
66011312,1,93,1318,1,
6602352,2181,16,0,440,
66031,107,2182,16,0,
6604440,1,1114,1343,1,
6605118,2183,16,0,440,
66061,1123,2184,16,0,
6607440,1,371,1365,1,
66081628,2185,16,0,440,
66091,375,1376,1,1882,
66102186,16,0,440,1,
6611377,1381,1,379,1386,
66121,380,1391,1,883,
66132187,16,0,440,1,
6614373,1409,1,130,2188,
661516,0,440,1,143,
66162189,16,0,440,1,
6617387,2190,16,0,440,
66181,2664,2191,16,0,
6619440,1,1159,2192,16,
66200,440,1,157,2193,
662116,0,440,1,1413,
66222194,16,0,440,1,
66231665,2195,16,0,440,
66241,412,2196,16,0,
6625440,1,1377,2197,16,
66260,440,1,172,2198,
662716,0,440,1,1939,
66282199,16,0,440,1,
6629437,2200,16,0,440,
66301,188,2201,16,0,
6631440,1,942,2202,16,
66320,440,1,1195,2203,
663316,0,440,1,1449,
66342204,16,0,440,1,
66351701,2205,16,0,440,
66361,447,1511,1,205,
66372206,16,0,440,1,
6638827,2207,16,0,440,
66391,223,2208,16,0,
6640440,1,476,1543,1,
6641477,1549,1,1231,2209,
664216,0,440,1,479,
66431559,1,480,1564,1,
66441485,2210,16,0,440,
66451,1737,2211,16,0,
6646440,1,242,2212,16,
66470,440,1,478,1583,
66481,1001,1588,1,1002,
66491593,1,21,2213,19,
6650432,1,21,2214,5,
665184,1,1011,1102,1,
66521012,2215,16,0,430,
66531,1013,1258,1,262,
66541119,1,1267,2216,16,
66550,430,1,515,2217,
665616,0,430,1,1521,
66572218,16,0,430,1,
6658525,1216,1,283,1172,
66591,2299,2219,16,0,
6660430,1,42,2220,16,
66610,430,1,40,1177,
66621,44,1183,1,47,
66631184,1,1303,2221,16,
66640,430,1,1555,2222,
666516,0,430,1,50,
66661201,1,48,1190,1,
666749,1196,1,51,1206,
66681,63,1222,1,305,
66691211,1,66,1228,1,
667067,1233,1,68,1238,
66711,69,1243,1,70,
66721248,1,73,2223,16,
66730,430,1,74,1253,
66741,328,2224,16,0,
6675430,1,1048,2225,16,
66760,430,1,82,2226,
667716,0,430,1,1840,
66782227,16,0,430,1,
66791591,2228,16,0,430,
66801,1341,2229,16,0,
6681430,1,1096,1312,1,
668293,1318,1,352,2230,
668316,0,430,1,107,
66842231,16,0,430,1,
66851114,1343,1,118,2232,
668616,0,430,1,1123,
66872233,16,0,430,1,
6688371,1365,1,1628,2234,
668916,0,430,1,375,
66901376,1,1882,2235,16,
66910,430,1,377,1381,
66921,379,1386,1,380,
66931391,1,883,2236,16,
66940,430,1,373,1409,
66951,130,2237,16,0,
6696430,1,143,2238,16,
66970,430,1,387,2239,
669816,0,430,1,2664,
66992240,16,0,430,1,
67001159,2241,16,0,430,
67011,157,2242,16,0,
6702430,1,1413,2243,16,
67030,430,1,1665,2244,
670416,0,430,1,412,
67052245,16,0,430,1,
67061377,2246,16,0,430,
67071,172,2247,16,0,
6708430,1,1939,2248,16,
67090,430,1,437,2249,
671016,0,430,1,188,
67112250,16,0,430,1,
6712942,2251,16,0,430,
67131,1195,2252,16,0,
6714430,1,1449,2253,16,
67150,430,1,1701,2254,
671616,0,430,1,447,
67171511,1,205,2255,16,
67180,430,1,827,2256,
671916,0,430,1,223,
67202257,16,0,430,1,
6721476,1543,1,477,1549,
67221,1231,2258,16,0,
6723430,1,479,1559,1,
6724480,1564,1,1485,2259,
672516,0,430,1,1737,
67262260,16,0,430,1,
6727242,2261,16,0,430,
67281,478,1583,1,1001,
67291588,1,1002,1593,1,
673022,2262,19,383,1,
673122,2263,5,84,1,
67321011,1102,1,1012,2264,
673316,0,381,1,1013,
67341258,1,262,1119,1,
67351267,2265,16,0,381,
67361,515,2266,16,0,
6737381,1,1521,2267,16,
67380,381,1,525,1216,
67391,283,1172,1,2299,
67402268,16,0,381,1,
674142,2269,16,0,381,
67421,40,1177,1,44,
67431183,1,47,1184,1,
67441303,2270,16,0,381,
67451,1555,2271,16,0,
6746381,1,50,1201,1,
674748,1190,1,49,1196,
67481,51,1206,1,63,
67491222,1,305,1211,1,
675066,1228,1,67,1233,
67511,68,1238,1,69,
67521243,1,70,1248,1,
675373,2272,16,0,381,
67541,74,1253,1,328,
67552273,16,0,381,1,
67561048,2274,16,0,381,
67571,82,2275,16,0,
6758381,1,1840,2276,16,
67590,381,1,1591,2277,
676016,0,381,1,1341,
67612278,16,0,381,1,
67621096,1312,1,93,1318,
67631,352,2279,16,0,
6764381,1,107,2280,16,
67650,381,1,1114,1343,
67661,118,2281,16,0,
6767381,1,1123,2282,16,
67680,381,1,371,1365,
67691,1628,2283,16,0,
6770381,1,375,1376,1,
67711882,2284,16,0,381,
67721,377,1381,1,379,
67731386,1,380,1391,1,
6774883,2285,16,0,381,
67751,373,1409,1,130,
67762286,16,0,381,1,
6777143,2287,16,0,381,
67781,387,2288,16,0,
6779381,1,2664,2289,16,
67800,381,1,1159,2290,
678116,0,381,1,157,
67822291,16,0,381,1,
67831413,2292,16,0,381,
67841,1665,2293,16,0,
6785381,1,412,2294,16,
67860,381,1,1377,2295,
678716,0,381,1,172,
67882296,16,0,381,1,
67891939,2297,16,0,381,
67901,437,2298,16,0,
6791381,1,188,2299,16,
67920,381,1,942,2300,
679316,0,381,1,1195,
67942301,16,0,381,1,
67951449,2302,16,0,381,
67961,1701,2303,16,0,
6797381,1,447,1511,1,
6798205,2304,16,0,381,
67991,827,2305,16,0,
6800381,1,223,2306,16,
68010,381,1,476,1543,
68021,477,1549,1,1231,
68032307,16,0,381,1,
6804479,1559,1,480,1564,
68051,1485,2308,16,0,
6806381,1,1737,2309,16,
68070,381,1,242,2310,
680816,0,381,1,478,
68091583,1,1001,1588,1,
68101002,1593,1,23,2311,
681119,504,1,23,2312,
68125,38,1,1901,2313,
681316,0,502,1,2075,
68142314,16,0,502,1,
68151860,821,1,1803,787,
68161,1804,2315,16,0,
6817502,1,2413,2316,16,
68180,502,1,2198,2317,
681916,0,502,1,1873,
6820835,1,1657,894,1,
68211989,916,1,1990,2318,
682216,0,502,1,1775,
68232319,16,0,502,1,
682432,2320,16,0,502,
68251,2105,814,1,2106,
68262321,16,0,502,1,
68272364,827,1,2227,908,
68281,2337,2322,16,0,
6829502,1,2021,718,1,
68302458,876,1,2459,882,
68311,2462,889,1,2136,
6832842,1,2464,899,1,
68332029,725,1,2030,731,
68341,2031,736,1,2032,
6835741,1,2033,746,1,
68362035,752,1,2037,757,
68371,2039,762,1,1931,
6838861,1,2041,768,1,
68392043,774,1,2045,779,
68401,1574,799,1,1958,
68412323,16,0,502,1,
684224,2324,19,177,1,
684324,2325,5,5,1,
684444,2326,16,0,175,
68451,377,2327,16,0,
6846540,1,40,2328,16,
68470,674,1,63,2329,
684816,0,196,1,373,
68492330,16,0,536,1,
685025,2331,19,291,1,
685125,2332,5,177,1,
6852256,2333,16,0,545,
68531,1261,2334,16,0,
6854545,1,1011,1102,1,
68551012,2335,16,0,289,
68561,2458,876,1,262,
68571119,1,1267,2336,16,
68580,289,1,2021,718,
68591,1521,2337,16,0,
6860289,1,1775,2338,16,
68610,545,1,2029,725,
68621,2030,731,1,2031,
6863736,1,2032,741,1,
68642033,746,1,277,2339,
686516,0,545,1,2035,
6866752,1,2037,757,1,
68672039,762,1,32,2340,
686816,0,545,1,2464,
6869899,1,2293,2341,16,
68700,545,1,2043,774,
68711,2045,779,1,2299,
68722342,16,0,289,1,
687341,2343,16,0,545,
68741,42,2344,16,0,
6875289,1,40,1177,1,
687644,1183,1,43,2345,
687716,0,545,1,1804,
68782346,16,0,545,1,
687948,1190,1,49,1196,
68801,47,1184,1,51,
68811206,1,52,2347,16,
68820,545,1,50,1201,
68831,305,1211,1,1096,
68841312,1,1515,2348,16,
68850,545,1,2318,2349,
688616,0,545,1,62,
68872350,16,0,545,1,
688863,1222,1,66,1228,
68891,67,1233,1,68,
68901238,1,69,1243,1,
689170,1248,1,71,2351,
689216,0,545,1,283,
68931172,1,73,2352,16,
68940,289,1,74,1253,
68951,1013,1258,1,76,
68962353,16,0,545,1,
68971834,2354,16,0,545,
68981,2337,2355,16,0,
6899545,1,79,2356,16,
69000,545,1,1335,2357,
690116,0,545,1,299,
69022358,16,0,545,1,
690382,2359,16,0,289,
69041,1840,2360,16,0,
6905289,1,1297,2361,16,
69060,545,1,85,2362,
690716,0,545,1,1341,
69082363,16,0,289,1,
690989,2364,16,0,545,
69101,1303,2365,16,0,
6911289,1,509,2366,16,
69120,545,1,93,1318,
69131,322,2367,16,0,
6914545,1,97,2368,16,
69150,545,1,2041,768,
69161,1555,2369,16,0,
6917289,1,827,2370,16,
69180,289,1,102,2371,
691916,0,545,1,1860,
6920821,1,1803,787,1,
69212364,827,1,107,2372,
692216,0,289,1,1114,
69231343,1,112,2373,16,
69240,545,1,1117,2374,
692516,0,545,1,352,
69261349,1,1873,835,1,
6927118,1355,1,1123,2375,
692816,0,289,1,371,
69291365,1,515,2376,16,
69300,289,1,1377,2377,
693116,0,289,1,124,
69322378,16,0,545,1,
69331882,2379,16,0,289,
69341,377,1381,1,379,
69351386,1,380,1391,1,
6936130,1414,1,346,2380,
693716,0,545,1,2075,
69382381,16,0,545,1,
6939373,1409,1,387,2382,
694016,0,289,1,137,
69412383,16,0,545,1,
6942143,2384,16,0,289,
69431,1901,2385,16,0,
6944545,1,1048,1344,1,
69452658,2386,16,0,545,
69461,1153,2387,16,0,
6947545,1,375,1376,1,
6948151,2388,16,0,545,
69491,1407,2389,16,0,
6950545,1,1659,2390,16,
69510,545,1,2413,2391,
695216,0,545,1,1159,
69532392,16,0,289,1,
6954381,2393,16,0,545,
69551,157,2394,16,0,
6956289,1,1413,2395,16,
69570,289,1,883,2396,
695816,0,289,1,1371,
69592397,16,0,545,1,
6960328,1302,1,2105,814,
69611,2106,2398,16,0,
6962545,1,166,2399,16,
69630,545,1,525,2400,
696416,0,545,1,1622,
69652401,16,0,545,1,
6966406,2402,16,0,545,
69671,1574,799,1,172,
69681469,1,1931,861,1,
6969412,2403,16,0,289,
69701,1933,2404,16,0,
6971545,1,1876,2405,16,
69720,545,1,431,2406,
697316,0,545,1,1585,
69742407,16,0,545,1,
6975182,2408,16,0,545,
69761,1628,2409,16,0,
6977289,1,1189,2410,16,
69780,545,1,437,2411,
697916,0,289,1,1591,
69802412,16,0,289,1,
6981188,1518,1,1695,2413,
698216,0,545,1,2198,
69832414,16,0,545,1,
69841195,2415,16,0,289,
69851,1449,2416,16,0,
6986289,1,1701,2417,16,
69870,289,1,447,2418,
698816,0,545,1,199,
69892419,16,0,545,1,
69902459,882,1,1958,2420,
699116,0,545,1,2462,
6992889,1,1657,894,1,
6993205,2421,16,0,289,
69941,459,2422,16,0,
6995545,1,462,2423,16,
69960,545,1,1665,2424,
699716,0,289,1,217,
69982425,16,0,545,1,
69992227,908,1,942,1490,
70001,1225,2426,16,0,
7001545,1,223,2427,16,
70020,289,1,1479,2428,
700316,0,545,1,1731,
70042429,16,0,545,1,
7005477,1549,1,1231,2430,
700616,0,289,1,479,
70071559,1,480,1564,1,
70081485,2431,16,0,289,
70091,1737,2432,16,0,
7010289,1,1989,916,1,
70111990,2433,16,0,545,
70121,1443,2434,16,0,
7013545,1,236,2435,16,
70140,545,1,2136,842,
70151,2664,2436,16,0,
7016289,1,476,1543,1,
7017242,2437,16,0,289,
70181,478,1583,1,1939,
70192438,16,0,289,1,
70201001,1588,1,1002,1593,
70211,1756,2439,16,0,
7022545,1,26,2440,19,
7023308,1,26,2441,5,
702484,1,1011,1102,1,
70251012,2442,16,0,306,
70261,1013,1258,1,262,
70271119,1,1267,2443,16,
70280,306,1,515,2444,
702916,0,660,1,1521,
70302445,16,0,306,1,
7031525,1216,1,283,1172,
70321,2299,2446,16,0,
7033306,1,42,2447,16,
70340,306,1,40,1177,
70351,44,1183,1,47,
70361184,1,1303,2448,16,
70370,306,1,1555,2449,
703816,0,306,1,50,
70391201,1,48,1190,1,
704049,1196,1,51,1206,
70411,63,1222,1,305,
70421211,1,66,1228,1,
704367,1233,1,68,1238,
70441,69,1243,1,70,
70451248,1,73,2450,16,
70460,306,1,74,1253,
70471,328,1302,1,1048,
70481344,1,82,2451,16,
70490,306,1,1840,2452,
705016,0,306,1,1591,
70512453,16,0,306,1,
70521341,2454,16,0,306,
70531,1096,1312,1,93,
70541318,1,352,1349,1,
7055107,2455,16,0,306,
70561,1114,1343,1,118,
70571355,1,1123,2456,16,
70580,306,1,371,1365,
70591,1628,2457,16,0,
7060306,1,375,1376,1,
70611882,2458,16,0,306,
70621,377,1381,1,379,
70631386,1,380,1391,1,
7064883,2459,16,0,306,
70651,373,1409,1,130,
70661414,1,143,2460,16,
70670,306,1,387,2461,
706816,0,306,1,2664,
70692462,16,0,306,1,
70701159,2463,16,0,306,
70711,157,2464,16,0,
7072306,1,1413,2465,16,
70730,306,1,1665,2466,
707416,0,306,1,412,
70752467,16,0,306,1,
70761377,2468,16,0,306,
70771,172,1469,1,1939,
70782469,16,0,306,1,
7079437,2470,16,0,588,
70801,188,1518,1,942,
70811490,1,1195,2471,16,
70820,306,1,1449,2472,
708316,0,306,1,1701,
70842473,16,0,306,1,
7085447,1511,1,205,2474,
708616,0,306,1,827,
70872475,16,0,306,1,
7088223,2476,16,0,306,
70891,476,1543,1,477,
70901549,1,1231,2477,16,
70910,306,1,479,1559,
70921,480,1564,1,1485,
70932478,16,0,306,1,
70941737,2479,16,0,306,
70951,242,2480,16,0,
7096306,1,478,1583,1,
70971001,1588,1,1002,1593,
70981,27,2481,19,598,
70991,27,2482,5,95,
71001,256,2483,16,0,
7101596,1,1261,2484,16,
71020,596,1,509,2485,
710316,0,596,1,1515,
71042486,16,0,596,1,
71052021,718,1,1775,2487,
710616,0,596,1,2029,
7107725,1,2030,731,1,
71082031,736,1,2032,741,
71091,2033,746,1,277,
71102488,16,0,596,1,
71112035,752,1,2037,757,
71121,2039,762,1,32,
71132489,16,0,596,1,
71142041,768,1,2293,2490,
711516,0,596,1,2043,
7116774,1,2045,779,1,
711741,2491,16,0,596,
71181,1297,2492,16,0,
7119596,1,43,2493,16,
71200,596,1,1803,787,
71211,1804,2494,16,0,
7122596,1,299,2495,16,
71230,596,1,52,2496,
712416,0,596,1,2318,
71252497,16,0,596,1,
712662,2498,16,0,596,
71271,2075,2499,16,0,
7128596,1,1574,799,1,
712971,2500,16,0,596,
71301,76,2501,16,0,
7131596,1,1834,2502,16,
71320,596,1,2337,2503,
713316,0,596,1,79,
71342504,16,0,596,1,
71351335,2505,16,0,596,
71361,322,2506,16,0,
7137596,1,85,2507,16,
71380,596,1,89,2508,
713916,0,596,1,346,
71402509,16,0,596,1,
71412105,814,1,2106,2510,
714216,0,596,1,97,
71432511,16,0,596,1,
71441860,821,1,2364,827,
71451,102,2512,16,0,
7146596,1,112,2513,16,
71470,596,1,1117,2514,
714816,0,596,1,1873,
7149835,1,1876,2515,16,
71500,596,1,124,2516,
715116,0,596,1,2136,
7152842,1,381,2517,16,
71530,596,1,525,2518,
715416,0,596,1,137,
71552519,16,0,596,1,
71561901,2520,16,0,596,
71571,2658,2521,16,0,
7158596,1,1153,2522,16,
71590,596,1,151,2523,
716016,0,596,1,1407,
71612524,16,0,596,1,
71621659,2525,16,0,596,
71631,2413,2526,16,0,
7164596,1,406,2527,16,
71650,596,1,1371,2528,
716616,0,596,1,166,
71672529,16,0,596,1,
71681622,2530,16,0,596,
71691,1931,861,1,1933,
71702531,16,0,596,1,
7171431,2532,16,0,596,
71721,1585,2533,16,0,
7173596,1,182,2534,16,
71740,596,1,1189,2535,
717516,0,596,1,1443,
71762536,16,0,596,1,
71771695,2537,16,0,596,
71781,2198,2538,16,0,
7179596,1,447,2539,16,
71800,596,1,2458,876,
71811,2459,882,1,1958,
71822540,16,0,596,1,
71832462,889,1,1657,894,
71841,2464,899,1,199,
71852541,16,0,596,1,
7186459,2542,16,0,596,
71871,462,2543,16,0,
7188596,1,217,2544,16,
71890,596,1,2227,908,
71901,1225,2545,16,0,
7191596,1,1479,2546,16,
71920,596,1,1731,2547,
719316,0,596,1,1989,
7194916,1,1990,2548,16,
71950,596,1,236,2549,
719616,0,596,1,1756,
71972550,16,0,596,1,
719828,2551,19,629,1,
719928,2552,5,60,1,
7200328,1302,1,223,1533,
72011,1096,1312,1,118,
72021355,1,883,1397,1,
7203525,1216,1,1001,1588,
72041,130,1414,1,459,
72051688,1,1114,1343,1,
7206352,1349,1,447,1511,
72071,464,1683,1,1011,
72081102,1,1013,1258,1,
7209242,1578,1,143,1419,
72101,40,1177,1,41,
72111659,1,42,1662,1,
7212479,1559,1,44,1183,
72131,481,1646,1,373,
72141409,1,47,1184,1,
7215157,1443,1,49,1196,
72161,50,1201,1,48,
72171190,1,379,1386,1,
7218380,1391,1,51,1206,
72191,476,1543,1,371,
72201365,1,478,1583,1,
72211048,1344,1,375,1376,
72221,172,1469,1,262,
72231119,1,283,1172,1,
722463,1222,1,67,1233,
72251,68,1238,1,69,
72261243,1,66,1228,1,
7227461,2553,16,0,627,
72281,74,1253,1,377,
72291381,1,1002,1593,1,
723070,1248,1,188,1518,
72311,82,1280,1,305,
72321211,1,477,1549,1,
7233827,1331,1,93,1318,
72341,480,1564,1,205,
72351523,1,942,1490,1,
7236107,1338,1,29,2554,
723719,280,1,29,2555,
72385,84,1,1011,1102,
72391,1012,2556,16,0,
7240278,1,1013,1258,1,
7241262,1119,1,1267,2557,
724216,0,278,1,515,
72432558,16,0,278,1,
72441521,2559,16,0,278,
72451,525,1216,1,283,
72461172,1,2299,2560,16,
72470,278,1,42,2561,
724816,0,278,1,40,
72491177,1,44,1183,1,
725047,1184,1,1303,2562,
725116,0,278,1,1555,
72522563,16,0,278,1,
725350,1201,1,48,1190,
72541,49,1196,1,51,
72551206,1,63,1222,1,
7256305,1211,1,66,1228,
72571,67,1233,1,68,
72581238,1,69,1243,1,
725970,1248,1,73,2564,
726016,0,278,1,74,
72611253,1,328,1302,1,
72621048,1344,1,82,2565,
726316,0,278,1,1840,
72642566,16,0,278,1,
72651591,2567,16,0,278,
72661,1341,2568,16,0,
7267278,1,1096,1312,1,
726893,1318,1,352,1349,
72691,107,2569,16,0,
7270278,1,1114,1343,1,
7271118,1355,1,1123,2570,
727216,0,278,1,371,
72731365,1,1628,2571,16,
72740,278,1,375,1376,
72751,1882,2572,16,0,
7276278,1,377,1381,1,
7277379,1386,1,380,1391,
72781,883,2573,16,0,
7279278,1,373,1409,1,
7280130,1414,1,143,1419,
72811,387,2574,16,0,
7282278,1,2664,2575,16,
72830,278,1,1159,2576,
728416,0,278,1,157,
72851443,1,1413,2577,16,
72860,278,1,1665,2578,
728716,0,278,1,412,
72882579,16,0,278,1,
72891377,2580,16,0,278,
72901,172,1469,1,1939,
72912581,16,0,278,1,
7292437,2582,16,0,278,
72931,188,1518,1,942,
72941490,1,1195,2583,16,
72950,278,1,1449,2584,
729616,0,278,1,1701,
72972585,16,0,278,1,
7298447,1511,1,205,2586,
729916,0,278,1,827,
73002587,16,0,278,1,
7301223,2588,16,0,278,
73021,476,1543,1,477,
73031549,1,1231,2589,16,
73040,278,1,479,1559,
73051,480,1564,1,1485,
73062590,16,0,278,1,
73071737,2591,16,0,278,
73081,242,2592,16,0,
7309278,1,478,1583,1,
73101001,1588,1,1002,1593,
73111,30,2593,19,268,
73121,30,2594,5,84,
73131,1011,1102,1,1012,
73142595,16,0,266,1,
73151013,1258,1,262,1119,
73161,1267,2596,16,0,
7317266,1,515,2597,16,
73180,266,1,1521,2598,
731916,0,266,1,525,
73201216,1,283,1172,1,
73212299,2599,16,0,266,
73221,42,2600,16,0,
7323266,1,40,1177,1,
732444,1183,1,47,1184,
73251,1303,2601,16,0,
7326266,1,1555,2602,16,
73270,266,1,50,1201,
73281,48,1190,1,49,
73291196,1,51,1206,1,
733063,1222,1,305,1211,
73311,66,1228,1,67,
73321233,1,68,1238,1,
733369,1243,1,70,1248,
73341,73,2603,16,0,
7335266,1,74,1253,1,
7336328,1302,1,1048,1344,
73371,82,2604,16,0,
7338266,1,1840,2605,16,
73390,266,1,1591,2606,
734016,0,266,1,1341,
73412607,16,0,266,1,
73421096,1312,1,93,1318,
73431,352,1349,1,107,
73442608,16,0,266,1,
73451114,1343,1,118,1355,
73461,1123,2609,16,0,
7347266,1,371,1365,1,
73481628,2610,16,0,266,
73491,375,1376,1,1882,
73502611,16,0,266,1,
7351377,1381,1,379,1386,
73521,380,1391,1,883,
73532612,16,0,266,1,
7354373,1409,1,130,1414,
73551,143,1419,1,387,
73562613,16,0,266,1,
73572664,2614,16,0,266,
73581,1159,2615,16,0,
7359266,1,157,1443,1,
73601413,2616,16,0,266,
73611,1665,2617,16,0,
7362266,1,412,2618,16,
73630,266,1,1377,2619,
736416,0,266,1,172,
73651469,1,1939,2620,16,
73660,266,1,437,2621,
736716,0,266,1,188,
73681518,1,942,1490,1,
73691195,2622,16,0,266,
73701,1449,2623,16,0,
7371266,1,1701,2624,16,
73720,266,1,447,1511,
73731,205,2625,16,0,
7374266,1,827,2626,16,
73750,266,1,223,2627,
737616,0,266,1,476,
73771543,1,477,1549,1,
73781231,2628,16,0,266,
73791,479,1559,1,480,
73801564,1,1485,2629,16,
73810,266,1,1737,2630,
738216,0,266,1,242,
73832631,16,0,266,1,
7384478,1583,1,1001,1588,
73851,1002,1593,1,31,
73862632,19,253,1,31,
73872633,5,84,1,1011,
73881102,1,1012,2634,16,
73890,251,1,1013,1258,
73901,262,1119,1,1267,
73912635,16,0,251,1,
7392515,2636,16,0,251,
73931,1521,2637,16,0,
7394251,1,525,1216,1,
7395283,1172,1,2299,2638,
739616,0,251,1,42,
73972639,16,0,251,1,
739840,1177,1,44,1183,
73991,47,1184,1,1303,
74002640,16,0,251,1,
74011555,2641,16,0,251,
74021,50,1201,1,48,
74031190,1,49,1196,1,
740451,1206,1,63,1222,
74051,305,1211,1,66,
74061228,1,67,1233,1,
740768,1238,1,69,1243,
74081,70,1248,1,73,
74092642,16,0,251,1,
741074,1253,1,328,1302,
74111,1048,1344,1,82,
74122643,16,0,251,1,
74131840,2644,16,0,251,
74141,1591,2645,16,0,
7415251,1,1341,2646,16,
74160,251,1,1096,1312,
74171,93,1318,1,352,
74181349,1,107,2647,16,
74190,251,1,1114,1343,
74201,118,1355,1,1123,
74212648,16,0,251,1,
7422371,1365,1,1628,2649,
742316,0,251,1,375,
74241376,1,1882,2650,16,
74250,251,1,377,1381,
74261,379,1386,1,380,
74271391,1,883,2651,16,
74280,251,1,373,1409,
74291,130,1414,1,143,
74302652,16,0,251,1,
7431387,2653,16,0,251,
74321,2664,2654,16,0,
7433251,1,1159,2655,16,
74340,251,1,157,2656,
743516,0,251,1,1413,
74362657,16,0,251,1,
74371665,2658,16,0,251,
74381,412,2659,16,0,
7439251,1,1377,2660,16,
74400,251,1,172,1469,
74411,1939,2661,16,0,
7442251,1,437,2662,16,
74430,251,1,188,1518,
74441,942,1490,1,1195,
74452663,16,0,251,1,
74461449,2664,16,0,251,
74471,1701,2665,16,0,
7448251,1,447,1511,1,
7449205,2666,16,0,251,
74501,827,2667,16,0,
7451251,1,223,2668,16,
74520,251,1,476,1543,
74531,477,1549,1,1231,
74542669,16,0,251,1,
7455479,1559,1,480,1564,
74561,1485,2670,16,0,
7457251,1,1737,2671,16,
74580,251,1,242,2672,
745916,0,251,1,478,
74601583,1,1001,1588,1,
74611002,1593,1,32,2673,
746219,246,1,32,2674,
74635,84,1,1011,1102,
74641,1012,2675,16,0,
7465244,1,1013,1258,1,
7466262,1119,1,1267,2676,
746716,0,244,1,515,
74682677,16,0,244,1,
74691521,2678,16,0,244,
74701,525,1216,1,283,
74711172,1,2299,2679,16,
74720,244,1,42,2680,
747316,0,244,1,40,
74741177,1,44,1183,1,
747547,1184,1,1303,2681,
747616,0,244,1,1555,
74772682,16,0,244,1,
747850,1201,1,48,1190,
74791,49,1196,1,51,
74801206,1,63,1222,1,
7481305,1211,1,66,1228,
74821,67,1233,1,68,
74831238,1,69,1243,1,
748470,1248,1,73,2683,
748516,0,244,1,74,
74861253,1,328,1302,1,
74871048,1344,1,82,2684,
748816,0,244,1,1840,
74892685,16,0,244,1,
74901591,2686,16,0,244,
74911,1341,2687,16,0,
7492244,1,1096,1312,1,
749393,1318,1,352,1349,
74941,107,2688,16,0,
7495244,1,1114,1343,1,
7496118,1355,1,1123,2689,
749716,0,244,1,371,
74981365,1,1628,2690,16,
74990,244,1,375,1376,
75001,1882,2691,16,0,
7501244,1,377,1381,1,
7502379,1386,1,380,1391,
75031,883,2692,16,0,
7504244,1,373,1409,1,
7505130,1414,1,143,2693,
750616,0,244,1,387,
75072694,16,0,244,1,
75082664,2695,16,0,244,
75091,1159,2696,16,0,
7510244,1,157,2697,16,
75110,244,1,1413,2698,
751216,0,244,1,1665,
75132699,16,0,244,1,
7514412,2700,16,0,244,
75151,1377,2701,16,0,
7516244,1,172,1469,1,
75171939,2702,16,0,244,
75181,437,2703,16,0,
7519244,1,188,1518,1,
7520942,1490,1,1195,2704,
752116,0,244,1,1449,
75222705,16,0,244,1,
75231701,2706,16,0,244,
75241,447,1511,1,205,
75252707,16,0,244,1,
7526827,2708,16,0,244,
75271,223,2709,16,0,
7528244,1,476,1543,1,
7529477,1549,1,1231,2710,
753016,0,244,1,479,
75311559,1,480,1564,1,
75321485,2711,16,0,244,
75331,1737,2712,16,0,
7534244,1,242,2713,16,
75350,244,1,478,1583,
75361,1001,1588,1,1002,
75371593,1,33,2714,19,
7538332,1,33,2715,5,
753984,1,1011,1102,1,
75401012,2716,16,0,330,
75411,1013,1258,1,262,
75421119,1,1267,2717,16,
75430,330,1,515,2718,
754416,0,330,1,1521,
75452719,16,0,330,1,
7546525,1216,1,283,1172,
75471,2299,2720,16,0,
7548330,1,42,2721,16,
75490,330,1,40,1177,
75501,44,1183,1,47,
75511184,1,1303,2722,16,
75520,330,1,1555,2723,
755316,0,330,1,50,
75541201,1,48,1190,1,
755549,1196,1,51,1206,
75561,63,1222,1,305,
75571211,1,66,1228,1,
755867,1233,1,68,1238,
75591,69,1243,1,70,
75601248,1,73,2724,16,
75610,330,1,74,1253,
75621,328,1302,1,1048,
75631344,1,82,2725,16,
75640,330,1,1840,2726,
756516,0,330,1,1591,
75662727,16,0,330,1,
75671341,2728,16,0,330,
75681,1096,1312,1,93,
75691318,1,352,1349,1,
7570107,2729,16,0,330,
75711,1114,1343,1,118,
75721355,1,1123,2730,16,
75730,330,1,371,1365,
75741,1628,2731,16,0,
7575330,1,375,1376,1,
75761882,2732,16,0,330,
75771,377,1381,1,379,
75781386,1,380,1391,1,
7579883,2733,16,0,330,
75801,373,1409,1,130,
75811414,1,143,1419,1,
7582387,2734,16,0,330,
75831,2664,2735,16,0,
7584330,1,1159,2736,16,
75850,330,1,157,1443,
75861,1413,2737,16,0,
7587330,1,1665,2738,16,
75880,330,1,412,2739,
758916,0,330,1,1377,
75902740,16,0,330,1,
7591172,1469,1,1939,2741,
759216,0,330,1,437,
75932742,16,0,330,1,
7594188,1518,1,942,1490,
75951,1195,2743,16,0,
7596330,1,1449,2744,16,
75970,330,1,1701,2745,
759816,0,330,1,447,
75991511,1,205,2746,16,
76000,330,1,827,2747,
760116,0,330,1,223,
76022748,16,0,330,1,
7603476,1543,1,477,1549,
76041,1231,2749,16,0,
7605330,1,479,1559,1,
7606480,1564,1,1485,2750,
760716,0,330,1,1737,
76082751,16,0,330,1,
7609242,1578,1,478,1583,
76101,1001,1588,1,1002,
76111593,1,34,2752,19,
7612322,1,34,2753,5,
761384,1,1011,1102,1,
76141012,2754,16,0,320,
76151,1013,1258,1,262,
76161119,1,1267,2755,16,
76170,320,1,515,2756,
761816,0,320,1,1521,
76192757,16,0,320,1,
7620525,1216,1,283,1172,
76211,2299,2758,16,0,
7622320,1,42,2759,16,
76230,320,1,40,1177,
76241,44,1183,1,47,
76251184,1,1303,2760,16,
76260,320,1,1555,2761,
762716,0,320,1,50,
76281201,1,48,1190,1,
762949,1196,1,51,1206,
76301,63,1222,1,305,
76311211,1,66,1228,1,
763267,1233,1,68,1238,
76331,69,1243,1,70,
76341248,1,73,2762,16,
76350,320,1,74,1253,
76361,328,1302,1,1048,
76371344,1,82,2763,16,
76380,320,1,1840,2764,
763916,0,320,1,1591,
76402765,16,0,320,1,
76411341,2766,16,0,320,
76421,1096,1312,1,93,
76431318,1,352,1349,1,
7644107,2767,16,0,320,
76451,1114,1343,1,118,
76461355,1,1123,2768,16,
76470,320,1,371,1365,
76481,1628,2769,16,0,
7649320,1,375,1376,1,
76501882,2770,16,0,320,
76511,377,1381,1,379,
76521386,1,380,1391,1,
7653883,2771,16,0,320,
76541,373,1409,1,130,
76551414,1,143,1419,1,
7656387,2772,16,0,320,
76571,2664,2773,16,0,
7658320,1,1159,2774,16,
76590,320,1,157,1443,
76601,1413,2775,16,0,
7661320,1,1665,2776,16,
76620,320,1,412,2777,
766316,0,320,1,1377,
76642778,16,0,320,1,
7665172,1469,1,1939,2779,
766616,0,320,1,437,
76672780,16,0,320,1,
7668188,1518,1,942,1490,
76691,1195,2781,16,0,
7670320,1,1449,2782,16,
76710,320,1,1701,2783,
767216,0,320,1,447,
76731511,1,205,1523,1,
7674827,2784,16,0,320,
76751,223,1533,1,476,
76761543,1,477,1549,1,
76771231,2785,16,0,320,
76781,479,1559,1,480,
76791564,1,1485,2786,16,
76800,320,1,1737,2787,
768116,0,320,1,242,
76821578,1,478,1583,1,
76831001,1588,1,1002,1593,
76841,35,2788,19,311,
76851,35,2789,5,84,
76861,1011,1102,1,1012,
76872790,16,0,309,1,
76881013,1258,1,262,1119,
76891,1267,2791,16,0,
7690309,1,515,2792,16,
76910,309,1,1521,2793,
769216,0,309,1,525,
76931216,1,283,1172,1,
76942299,2794,16,0,309,
76951,42,2795,16,0,
7696309,1,40,1177,1,
769744,1183,1,47,1184,
76981,1303,2796,16,0,
7699309,1,1555,2797,16,
77000,309,1,50,1201,
77011,48,1190,1,49,
77021196,1,51,1206,1,
770363,1222,1,305,1211,
77041,66,1228,1,67,
77051233,1,68,1238,1,
770669,1243,1,70,1248,
77071,73,2798,16,0,
7708309,1,74,1253,1,
7709328,1302,1,1048,1344,
77101,82,2799,16,0,
7711309,1,1840,2800,16,
77120,309,1,1591,2801,
771316,0,309,1,1341,
77142802,16,0,309,1,
77151096,1312,1,93,1318,
77161,352,1349,1,107,
77172803,16,0,309,1,
77181114,1343,1,118,1355,
77191,1123,2804,16,0,
7720309,1,371,1365,1,
77211628,2805,16,0,309,
77221,375,1376,1,1882,
77232806,16,0,309,1,
7724377,1381,1,379,1386,
77251,380,1391,1,883,
77262807,16,0,309,1,
7727373,1409,1,130,1414,
77281,143,1419,1,387,
77292808,16,0,309,1,
77302664,2809,16,0,309,
77311,1159,2810,16,0,
7732309,1,157,1443,1,
77331413,2811,16,0,309,
77341,1665,2812,16,0,
7735309,1,412,2813,16,
77360,309,1,1377,2814,
773716,0,309,1,172,
77381469,1,1939,2815,16,
77390,309,1,437,2816,
774016,0,309,1,188,
77411518,1,942,1490,1,
77421195,2817,16,0,309,
77431,1449,2818,16,0,
7744309,1,1701,2819,16,
77450,309,1,447,1511,
77461,205,1523,1,827,
77472820,16,0,309,1,
7748223,2821,16,0,309,
77491,476,1543,1,477,
77501549,1,1231,2822,16,
77510,309,1,479,1559,
77521,480,1564,1,1485,
77532823,16,0,309,1,
77541737,2824,16,0,309,
77551,242,1578,1,478,
77561583,1,1001,1588,1,
77571002,1593,1,36,2825,
775819,216,1,36,2826,
77595,94,1,256,2827,
776016,0,214,1,1261,
77612828,16,0,214,1,
7762509,2829,16,0,214,
77631,1515,2830,16,0,
7764214,1,2021,718,1,
77651775,2831,16,0,214,
77661,2029,725,1,2030,
7767731,1,2031,736,1,
77682032,741,1,2033,746,
77691,277,2832,16,0,
7770214,1,2035,752,1,
77712037,757,1,2039,762,
77721,32,2833,16,0,
7773214,1,2041,768,1,
77742293,2834,16,0,214,
77751,2043,774,1,2045,
7776779,1,41,2835,16,
77770,214,1,1297,2836,
777816,0,214,1,43,
77792837,16,0,214,1,
77801803,787,1,1804,2838,
778116,0,214,1,299,
77822839,16,0,214,1,
778352,2840,16,0,214,
77841,2318,2841,16,0,
7785214,1,2075,2842,16,
77860,214,1,1574,799,
77871,71,2843,16,0,
7788214,1,76,2844,16,
77890,214,1,1834,2845,
779016,0,214,1,2337,
77912846,16,0,214,1,
779279,2847,16,0,214,
77931,1335,2848,16,0,
7794214,1,322,2849,16,
77950,214,1,85,2850,
779616,0,214,1,89,
77972851,16,0,214,1,
7798346,2852,16,0,214,
77991,2105,814,1,2106,
78002853,16,0,214,1,
780197,2854,16,0,214,
78021,1860,821,1,2364,
7803827,1,102,2855,16,
78040,214,1,112,2856,
780516,0,214,1,1117,
78062857,16,0,214,1,
78071873,835,1,1876,2858,
780816,0,214,1,124,
78092859,16,0,214,1,
78102136,842,1,381,2860,
781116,0,214,1,525,
78122861,16,0,214,1,
7813137,2862,16,0,214,
78141,1901,2863,16,0,
7815214,1,2658,2864,16,
78160,214,1,1153,2865,
781716,0,214,1,151,
78182866,16,0,214,1,
78191407,2867,16,0,214,
78201,1659,2868,16,0,
7821214,1,2413,2869,16,
78220,214,1,406,2870,
782316,0,214,1,1371,
78242871,16,0,214,1,
7825166,2872,16,0,214,
78261,1622,2873,16,0,
7827214,1,1931,861,1,
78281933,2874,16,0,214,
78291,431,2875,16,0,
7830214,1,1585,2876,16,
78310,214,1,182,2877,
783216,0,214,1,1189,
78332878,16,0,214,1,
78341443,2879,16,0,214,
78351,1695,2880,16,0,
7836214,1,2198,2881,16,
78370,214,1,447,2882,
783816,0,214,1,2458,
7839876,1,2459,882,1,
78401958,2883,16,0,214,
78411,2462,889,1,1657,
7842894,1,2464,899,1,
7843199,2884,16,0,214,
78441,459,2885,16,0,
7845214,1,462,2886,16,
78460,214,1,217,2887,
784716,0,214,1,2227,
7848908,1,1225,2888,16,
78490,214,1,1479,2889,
785016,0,214,1,1731,
78512890,16,0,214,1,
78521989,916,1,1990,2891,
785316,0,214,1,236,
78542892,16,0,214,1,
78551756,2893,16,0,214,
78561,37,2894,19,233,
78571,37,2895,5,94,
78581,256,2896,16,0,
7859231,1,1261,2897,16,
78600,231,1,509,2898,
786116,0,231,1,1515,
78622899,16,0,231,1,
78632021,718,1,1775,2900,
786416,0,231,1,2029,
7865725,1,2030,731,1,
78662031,736,1,2032,741,
78671,2033,746,1,277,
78682901,16,0,231,1,
78692035,752,1,2037,757,
78701,2039,762,1,32,
78712902,16,0,231,1,
78722041,768,1,2293,2903,
787316,0,231,1,2043,
7874774,1,2045,779,1,
787541,2904,16,0,231,
78761,1297,2905,16,0,
7877231,1,43,2906,16,
78780,231,1,1803,787,
78791,1804,2907,16,0,
7880231,1,299,2908,16,
78810,231,1,52,2909,
788216,0,231,1,2318,
78832910,16,0,231,1,
78842075,2911,16,0,231,
78851,1574,799,1,71,
78862912,16,0,231,1,
788776,2913,16,0,231,
78881,1834,2914,16,0,
7889231,1,2337,2915,16,
78900,231,1,79,2916,
789116,0,231,1,1335,
78922917,16,0,231,1,
7893322,2918,16,0,231,
78941,85,2919,16,0,
7895231,1,89,2920,16,
78960,231,1,346,2921,
789716,0,231,1,2105,
7898814,1,2106,2922,16,
78990,231,1,97,2923,
790016,0,231,1,1860,
7901821,1,2364,827,1,
7902102,2924,16,0,231,
79031,112,2925,16,0,
7904231,1,1117,2926,16,
79050,231,1,1873,835,
79061,1876,2927,16,0,
7907231,1,124,2928,16,
79080,231,1,2136,842,
79091,381,2929,16,0,
7910231,1,525,2930,16,
79110,231,1,137,2931,
791216,0,231,1,1901,
79132932,16,0,231,1,
79142658,2933,16,0,231,
79151,1153,2934,16,0,
7916231,1,151,2935,16,
79170,231,1,1407,2936,
791816,0,231,1,1659,
79192937,16,0,231,1,
79202413,2938,16,0,231,
79211,406,2939,16,0,
7922231,1,1371,2940,16,
79230,231,1,166,2941,
792416,0,231,1,1622,
79252942,16,0,231,1,
79261931,861,1,1933,2943,
792716,0,231,1,431,
79282944,16,0,231,1,
79291585,2945,16,0,231,
79301,182,2946,16,0,
7931231,1,1189,2947,16,
79320,231,1,1443,2948,
793316,0,231,1,1695,
79342949,16,0,231,1,
79352198,2950,16,0,231,
79361,447,2951,16,0,
7937231,1,2458,876,1,
79382459,882,1,1958,2952,
793916,0,231,1,2462,
7940889,1,1657,894,1,
79412464,899,1,199,2953,
794216,0,231,1,459,
79432954,16,0,231,1,
7944462,2955,16,0,231,
79451,217,2956,16,0,
7946231,1,2227,908,1,
79471225,2957,16,0,231,
79481,1479,2958,16,0,
7949231,1,1731,2959,16,
79500,231,1,1989,916,
79511,1990,2960,16,0,
7952231,1,236,2961,16,
79530,231,1,1756,2962,
795416,0,231,1,38,
79552963,19,230,1,38,
79562964,5,84,1,1011,
79571102,1,1012,2965,16,
79580,228,1,1013,1258,
79591,262,1119,1,1267,
79602966,16,0,228,1,
7961515,2967,16,0,228,
79621,1521,2968,16,0,
7963228,1,525,1216,1,
7964283,1172,1,2299,2969,
796516,0,228,1,42,
79662970,16,0,228,1,
796740,1177,1,44,1183,
79681,47,1184,1,1303,
79692971,16,0,228,1,
79701555,2972,16,0,228,
79711,50,1201,1,48,
79721190,1,49,1196,1,
797351,1206,1,63,1222,
79741,305,1211,1,66,
79751228,1,67,1233,1,
797668,1238,1,69,1243,
79771,70,1248,1,73,
79782973,16,0,228,1,
797974,1253,1,328,1302,
79801,1048,1344,1,82,
79812974,16,0,228,1,
79821840,2975,16,0,228,
79831,1591,2976,16,0,
7984228,1,1341,2977,16,
79850,228,1,1096,1312,
79861,93,1318,1,352,
79871349,1,107,2978,16,
79880,228,1,1114,1343,
79891,118,1355,1,1123,
79902979,16,0,228,1,
7991371,1365,1,1628,2980,
799216,0,228,1,375,
79931376,1,1882,2981,16,
79940,228,1,377,1381,
79951,379,1386,1,380,
79961391,1,883,1397,1,
7997373,1409,1,130,1414,
79981,143,1419,1,387,
79992982,16,0,228,1,
80002664,2983,16,0,228,
80011,1159,2984,16,0,
8002228,1,157,1443,1,
80031413,2985,16,0,228,
80041,1665,2986,16,0,
8005228,1,412,2987,16,
80060,228,1,1377,2988,
800716,0,228,1,172,
80081469,1,1939,2989,16,
80090,228,1,437,2990,
801016,0,228,1,188,
80111518,1,942,1490,1,
80121195,2991,16,0,228,
80131,1449,2992,16,0,
8014228,1,1701,2993,16,
80150,228,1,447,1511,
80161,205,1523,1,827,
80171331,1,223,1533,1,
8018476,1543,1,477,1549,
80191,1231,2994,16,0,
8020228,1,479,1559,1,
8021480,1564,1,1485,2995,
802216,0,228,1,1737,
80232996,16,0,228,1,
8024242,1578,1,478,1583,
80251,1001,1588,1,1002,
80261593,1,39,2997,19,
8027222,1,39,2998,5,
802884,1,1011,1102,1,
80291012,2999,16,0,220,
80301,1013,1258,1,262,
80311119,1,1267,3000,16,
80320,220,1,515,3001,
803316,0,220,1,1521,
80343002,16,0,220,1,
8035525,1216,1,283,1172,
80361,2299,3003,16,0,
8037220,1,42,3004,16,
80380,220,1,40,1177,
80391,44,1183,1,47,
80401184,1,1303,3005,16,
80410,220,1,1555,3006,
804216,0,220,1,50,
80431201,1,48,1190,1,
804449,1196,1,51,1206,
80451,63,1222,1,305,
80461211,1,66,1228,1,
804767,1233,1,68,1238,
80481,69,1243,1,70,
80491248,1,73,3007,16,
80500,220,1,74,1253,
80511,328,1302,1,1048,
80521344,1,82,3008,16,
80530,220,1,1840,3009,
805416,0,220,1,1591,
80553010,16,0,220,1,
80561341,3011,16,0,220,
80571,1096,1312,1,93,
80581318,1,352,1349,1,
8059107,3012,16,0,220,
80601,1114,1343,1,118,
80611355,1,1123,3013,16,
80620,220,1,371,1365,
80631,1628,3014,16,0,
8064220,1,375,1376,1,
80651882,3015,16,0,220,
80661,377,1381,1,379,
80671386,1,380,1391,1,
8068883,1397,1,373,1409,
80691,130,1414,1,143,
80701419,1,387,3016,16,
80710,220,1,2664,3017,
807216,0,220,1,1159,
80733018,16,0,220,1,
8074157,1443,1,1413,3019,
807516,0,220,1,1665,
80763020,16,0,220,1,
8077412,3021,16,0,220,
80781,1377,3022,16,0,
8079220,1,172,1469,1,
80801939,3023,16,0,220,
80811,437,3024,16,0,
8082220,1,188,1518,1,
8083942,1490,1,1195,3025,
808416,0,220,1,1449,
80853026,16,0,220,1,
80861701,3027,16,0,220,
80871,447,1511,1,205,
80881523,1,827,1331,1,
8089223,1533,1,476,1543,
80901,477,1549,1,1231,
80913028,16,0,220,1,
8092479,1559,1,480,1564,
80931,1485,3029,16,0,
8094220,1,1737,3030,16,
80950,220,1,242,1578,
80961,478,1583,1,1001,
80971588,1,1002,1593,1,
809840,3031,19,210,1,
809940,3032,5,84,1,
81001011,1102,1,1012,3033,
810116,0,208,1,1013,
81021258,1,262,1119,1,
81031267,3034,16,0,208,
81041,515,3035,16,0,
8105208,1,1521,3036,16,
81060,208,1,525,1216,
81071,283,1172,1,2299,
81083037,16,0,208,1,
810942,3038,16,0,208,
81101,40,1177,1,44,
81111183,1,47,1184,1,
81121303,3039,16,0,208,
81131,1555,3040,16,0,
8114208,1,50,1201,1,
811548,1190,1,49,1196,
81161,51,1206,1,63,
81171222,1,305,1211,1,
811866,1228,1,67,1233,
81191,68,1238,1,69,
81201243,1,70,1248,1,
812173,3041,16,0,208,
81221,74,1253,1,328,
81231302,1,1048,1344,1,
812482,3042,16,0,208,
81251,1840,3043,16,0,
8126208,1,1591,3044,16,
81270,208,1,1341,3045,
812816,0,208,1,1096,
81291312,1,93,1318,1,
8130352,1349,1,107,3046,
813116,0,208,1,1114,
81321343,1,118,3047,16,
81330,208,1,1123,3048,
813416,0,208,1,371,
81351365,1,1628,3049,16,
81360,208,1,375,1376,
81371,1882,3050,16,0,
8138208,1,377,1381,1,
8139379,1386,1,380,1391,
81401,883,3051,16,0,
8141208,1,373,1409,1,
8142130,3052,16,0,208,
81431,143,3053,16,0,
8144208,1,387,3054,16,
81450,208,1,2664,3055,
814616,0,208,1,1159,
81473056,16,0,208,1,
8148157,3057,16,0,208,
81491,1413,3058,16,0,
8150208,1,1665,3059,16,
81510,208,1,412,3060,
815216,0,208,1,1377,
81533061,16,0,208,1,
8154172,3062,16,0,208,
81551,1939,3063,16,0,
8156208,1,437,3064,16,
81570,208,1,188,3065,
815816,0,208,1,942,
81591490,1,1195,3066,16,
81600,208,1,1449,3067,
816116,0,208,1,1701,
81623068,16,0,208,1,
8163447,1511,1,205,3069,
816416,0,208,1,827,
81653070,16,0,208,1,
8166223,3071,16,0,208,
81671,476,1543,1,477,
81681549,1,1231,3072,16,
81690,208,1,479,1559,
81701,480,1564,1,1485,
81713073,16,0,208,1,
81721737,3074,16,0,208,
81731,242,3075,16,0,
8174208,1,478,1583,1,
81751001,1588,1,1002,1593,
81761,41,3076,19,172,
81771,41,3077,5,84,
81781,1011,1102,1,1012,
81793078,16,0,170,1,
81801013,1258,1,262,1119,
81811,1267,3079,16,0,
8182170,1,515,3080,16,
81830,170,1,1521,3081,
818416,0,170,1,525,
81851216,1,283,1172,1,
81862299,3082,16,0,170,
81871,42,3083,16,0,
8188170,1,40,1177,1,
818944,1183,1,47,1184,
81901,1303,3084,16,0,
8191170,1,1555,3085,16,
81920,170,1,50,1201,
81931,48,1190,1,49,
81941196,1,51,1206,1,
819563,1222,1,305,1211,
81961,66,1228,1,67,
81971233,1,68,1238,1,
819869,1243,1,70,1248,
81991,73,3086,16,0,
8200170,1,74,1253,1,
8201328,1302,1,1048,1344,
82021,82,3087,16,0,
8203170,1,1840,3088,16,
82040,170,1,1591,3089,
820516,0,170,1,1341,
82063090,16,0,170,1,
82071096,1312,1,93,1318,
82081,352,1349,1,107,
82093091,16,0,170,1,
82101114,1343,1,118,3092,
821116,0,170,1,1123,
82123093,16,0,170,1,
8213371,1365,1,1628,3094,
821416,0,170,1,375,
82151376,1,1882,3095,16,
82160,170,1,377,1381,
82171,379,1386,1,380,
82181391,1,883,3096,16,
82190,170,1,373,1409,
82201,130,3097,16,0,
8221170,1,143,3098,16,
82220,170,1,387,3099,
822316,0,170,1,2664,
82243100,16,0,170,1,
82251159,3101,16,0,170,
82261,157,3102,16,0,
8227170,1,1413,3103,16,
82280,170,1,1665,3104,
822916,0,170,1,412,
82303105,16,0,170,1,
82311377,3106,16,0,170,
82321,172,3107,16,0,
8233170,1,1939,3108,16,
82340,170,1,437,3109,
823516,0,170,1,188,
82363110,16,0,170,1,
8237942,1490,1,1195,3111,
823816,0,170,1,1449,
82393112,16,0,170,1,
82401701,3113,16,0,170,
82411,447,1511,1,205,
82423114,16,0,170,1,
8243827,3115,16,0,170,
82441,223,3116,16,0,
8245170,1,476,1543,1,
8246477,1549,1,1231,3117,
824716,0,170,1,479,
82481559,1,480,1564,1,
82491485,3118,16,0,170,
82501,1737,3119,16,0,
8251170,1,242,3120,16,
82520,170,1,478,1583,
82531,1001,1588,1,1002,
82541593,1,42,3121,19,
8255394,1,42,3122,5,
825638,1,1901,3123,16,
82570,392,1,2075,3124,
825816,0,392,1,1860,
8259821,1,1803,787,1,
82601804,3125,16,0,392,
82611,2413,3126,16,0,
8262392,1,2198,3127,16,
82630,392,1,1873,835,
82641,1657,894,1,1989,
8265916,1,1990,3128,16,
82660,392,1,1775,3129,
826716,0,392,1,32,
82683130,16,0,392,1,
82692105,814,1,2106,3131,
827016,0,392,1,2364,
8271827,1,2227,908,1,
82722337,3132,16,0,392,
82731,2021,718,1,2458,
8274876,1,2459,882,1,
82752462,889,1,2136,842,
82761,2464,899,1,2029,
8277725,1,2030,731,1,
82782031,736,1,2032,741,
82791,2033,746,1,2035,
8280752,1,2037,757,1,
82812039,762,1,1931,861,
82821,2041,768,1,2043,
8283774,1,2045,779,1,
82841574,799,1,1958,3133,
828516,0,392,1,43,
82863134,19,453,1,43,
82873135,5,25,1,2035,
8288752,1,2037,757,1,
82892039,762,1,2041,768,
82901,2227,908,1,2043,
8291774,1,1657,894,1,
82921860,821,1,2136,842,
82931,2021,718,1,2459,
8294882,1,1574,799,1,
82952105,3136,16,0,578,
82961,1931,861,1,1873,
8297835,1,2031,736,1,
82981803,787,1,1989,3137,
829916,0,451,1,2464,
8300899,1,2029,725,1,
83012030,731,1,2364,827,
83021,2032,741,1,2033,
8303746,1,2045,779,1,
830444,3138,19,264,1,
830544,3139,5,38,1,
83061901,3140,16,0,262,
83071,2075,3141,16,0,
8308262,1,1860,821,1,
83091803,787,1,1804,3142,
831016,0,262,1,2413,
83113143,16,0,262,1,
83122198,3144,16,0,262,
83131,1873,835,1,1657,
8314894,1,1989,916,1,
83151990,3145,16,0,262,
83161,1775,3146,16,0,
8317262,1,32,3147,16,
83180,262,1,2105,814,
83191,2106,3148,16,0,
8320262,1,2364,827,1,
83212227,908,1,2337,3149,
832216,0,262,1,2021,
8323718,1,2458,876,1,
83242459,882,1,2462,889,
83251,2136,842,1,2464,
8326899,1,2029,725,1,
83272030,731,1,2031,736,
83281,2032,741,1,2033,
8329746,1,2035,752,1,
83302037,757,1,2039,762,
83311,1931,861,1,2041,
8332768,1,2043,774,1,
83332045,779,1,1574,799,
83341,1958,3150,16,0,
8335262,1,45,3151,19,
8336287,1,45,3152,5,
833739,1,1901,3153,16,
83380,315,1,2075,3154,
833916,0,315,1,1860,
8340821,1,1803,787,1,
83411804,3155,16,0,315,
83421,2413,3156,16,0,
8343315,1,2198,3157,16,
83440,315,1,1873,835,
83451,1657,894,1,1989,
8346916,1,1990,3158,16,
83470,315,1,1775,3159,
834816,0,315,1,32,
83493160,16,0,315,1,
83502105,814,1,2106,3161,
835116,0,315,1,2364,
8352827,1,2227,908,1,
83532337,3162,16,0,315,
83541,2021,718,1,2458,
8355876,1,2459,882,1,
83562462,889,1,2136,842,
83571,2464,899,1,2029,
8358725,1,2030,731,1,
83592031,736,1,2032,741,
83601,2033,746,1,2035,
8361752,1,2037,757,1,
83622039,762,1,1931,861,
83631,2041,768,1,2043,
8364774,1,2045,779,1,
83651832,3163,16,0,285,
83661,1574,799,1,1958,
83673164,16,0,315,1,
836846,3165,19,671,1,
836946,3166,5,38,1,
83701901,3167,16,0,669,
83711,2075,3168,16,0,
8372669,1,1860,821,1,
83731803,787,1,1804,3169,
837416,0,669,1,2413,
83753170,16,0,669,1,
83762198,3171,16,0,669,
83771,1873,835,1,1657,
8378894,1,1989,916,1,
83791990,3172,16,0,669,
83801,1775,3173,16,0,
8381669,1,32,3174,16,
83820,669,1,2105,814,
83831,2106,3175,16,0,
8384669,1,2364,827,1,
83852227,908,1,2337,3176,
838616,0,669,1,2021,
8387718,1,2458,876,1,
83882459,882,1,2462,889,
83891,2136,842,1,2464,
8390899,1,2029,725,1,
83912030,731,1,2031,736,
83921,2032,741,1,2033,
8393746,1,2035,752,1,
83942037,757,1,2039,762,
83951,1931,861,1,2041,
8396768,1,2043,774,1,
83972045,779,1,1574,799,
83981,1958,3177,16,0,
8399669,1,47,3178,19,
8400466,1,47,3179,5,
840119,1,0,3180,16,
84020,464,1,2706,3181,
840316,0,464,1,2634,
8404691,1,2636,3182,16,
84050,464,1,2639,707,
84061,2714,3183,17,3184,
840715,3185,4,36,37,
84080,71,0,108,0,
8409111,0,98,0,97,
84100,108,0,68,0,
8411101,0,102,0,105,
84120,110,0,105,0,
8413116,0,105,0,111,
84140,110,0,115,0,
84151,-1,1,5,3186,
841620,3187,4,38,71,
84170,108,0,111,0,
841898,0,97,0,108,
84190,68,0,101,0, 75400,68,0,101,0,
8420102,0,105,0,110, 754199,0,108,0,97,
84210,105,0,116,0, 75420,114,0,97,0,
7543116,0,105,0,111,
75440,110,0,76,0,
7545105,0,115,0,116,
75460,1,-1,1,5,
75472278,20,2279,4,68,
754873,0,110,0,116,
75490,86,0,101,0,
755099,0,86,0,101,
75510,99,0,65,0,
7552114,0,103,0,117,
75530,109,0,101,0,
7554110,0,116,0,68,
75550,101,0,99,0,
7556108,0,97,0,114,
75570,97,0,116,0,
8422105,0,111,0,110, 7558105,0,111,0,110,
84230,115,0,95,0, 75590,76,0,105,0,
842450,0,1,145,1, 7560115,0,116,0,95,
84253,1,3,1,2, 75610,49,0,1,210,
84263188,22,1,4,1, 75621,3,1,6,1,
84272558,697,1,2716,3189, 75635,2280,22,1,46,
842817,3190,15,3185,1, 75641,2281,1276,1,525,
8429-1,1,5,3191,20, 75651339,1,30,1904,1,
84303192,4,38,71,0, 75661002,1715,1,283,1295,
8431108,0,111,0,98, 75671,2546,2281,17,2282,
84320,97,0,108,0, 756815,2283,4,66,37,
843368,0,101,0,102, 75690,73,0,110,0,
84340,105,0,110,0, 7570116,0,82,0,111,
8435105,0,116,0,105, 75710,116,0,82,0,
7572111,0,116,0,65,
75730,114,0,103,0,
7574117,0,109,0,101,
75750,110,0,116,0,
757668,0,101,0,99,
75770,108,0,97,0,
7578114,0,97,0,116,
75790,105,0,111,0,
7580110,0,76,0,105,
75810,115,0,116,0,
75821,-1,1,5,2284,
758320,2285,4,68,73,
75840,110,0,116,0,
758582,0,111,0,116,
75860,82,0,111,0,
7587116,0,65,0,114,
75880,103,0,117,0,
7589109,0,101,0,110,
75900,116,0,68,0,
7591101,0,99,0,108,
75920,97,0,114,0,
759397,0,116,0,105,
84360,111,0,110,0, 75940,111,0,110,0,
8437115,0,95,0,49, 759576,0,105,0,115,
84380,1,144,1,3, 75960,116,0,95,0,
84391,2,1,1,3193, 759749,0,1,209,1,
844022,1,3,1,2022, 75983,1,6,1,5,
84413194,16,0,567,1, 75992286,22,1,45,1,
84422459,882,1,2715,3195, 76002547,2287,16,0,519,
844317,3196,15,3185,1, 76011,1010,2288,16,0,
8444-1,1,5,3197,20, 7602701,1,40,1300,1,
84453198,4,38,71,0, 760341,1916,1,42,1920,
8446108,0,111,0,98, 76041,44,1306,1,2555,
84470,97,0,108,0, 76052289,16,0,645,1,
844868,0,101,0,102, 76061260,1218,1,47,1307,
84490,105,0,110,0, 76071,48,1313,1,49,
8450105,0,116,0,105, 76081319,1,50,1324,1,
760951,1329,1,2562,2290,
761017,2291,15,2292,4,
761154,37,0,73,0,
7612110,0,116,0,65,
76130,114,0,103,0,
7614117,0,109,0,101,
76150,110,0,116,0,
761668,0,101,0,99,
76170,108,0,97,0,
7618114,0,97,0,116,
76190,105,0,111,0,
7620110,0,76,0,105,
76210,115,0,116,0,
76221,-1,1,5,2293,
762320,2294,4,56,73,
76240,110,0,116,0,
762565,0,114,0,103,
76260,117,0,109,0,
7627101,0,110,0,116,
76280,68,0,101,0,
762999,0,108,0,97,
76300,114,0,97,0,
7631116,0,105,0,111,
76320,110,0,76,0,
7633105,0,115,0,116,
76340,95,0,49,0,
76351,207,1,3,1,
76362,1,1,2295,22,
76371,43,1,2563,2296,
763816,0,661,1,305,
76391334,1,2576,2297,16,
76400,571,1,2570,2298,
764117,2299,15,2300,4,
764254,37,0,75,0,
7643101,0,121,0,65,
76440,114,0,103,0,
7645117,0,109,0,101,
76460,110,0,116,0,
764768,0,101,0,99,
76480,108,0,97,0,
7649114,0,97,0,116,
76500,105,0,111,0,
7651110,0,76,0,105,
76520,115,0,116,0,
76531,-1,1,5,2301,
765420,2302,4,56,75,
76550,101,0,121,0,
765665,0,114,0,103,
76570,117,0,109,0,
7658101,0,110,0,116,
76590,68,0,101,0,
766099,0,108,0,97,
76610,114,0,97,0,
7662116,0,105,0,111,
76630,110,0,76,0,
7664105,0,115,0,116,
76650,95,0,49,0,
76661,206,1,3,1,
76672,1,1,2303,22,
76681,42,1,61,2304,
766916,0,220,1,63,
76701345,1,66,1351,1,
767167,1356,1,68,1361,
76721,69,1366,1,70,
76731371,1,2581,1926,1,
767473,2305,16,0,230,
76751,74,1376,1,1013,
76761381,1,2335,2306,16,
76770,266,1,1332,1386,
76781,1048,1462,1,2590,
76792307,16,0,774,1,
768082,1403,1,1840,2308,
768116,0,338,1,2516,
76822309,17,2310,15,2311,
76834,66,37,0,75,
76840,101,0,121,0,
768573,0,110,0,116,
76860,73,0,110,0,
7687116,0,65,0,114,
76880,103,0,117,0,
7689109,0,101,0,110,
76900,116,0,68,0,
7691101,0,99,0,108,
76920,97,0,114,0,
769397,0,116,0,105,
84510,111,0,110,0, 76940,111,0,110,0,
8452115,0,95,0,51, 769576,0,105,0,115,
84530,1,146,1,3, 76960,116,0,1,-1,
84541,2,1,1,3199, 76971,5,2312,20,2313,
845522,1,5,1,2464, 76984,68,75,0,101,
8456899,1,2466,3200,17, 76990,121,0,73,0,
84573201,15,3202,4,50, 7700110,0,116,0,73,
77010,110,0,116,0,
770265,0,114,0,103,
77030,117,0,109,0,
7704101,0,110,0,116,
77050,68,0,101,0,
770699,0,108,0,97,
77070,114,0,97,0,
7708116,0,105,0,111,
77090,110,0,76,0,
7710105,0,115,0,116,
77110,95,0,49,0,
77121,211,1,3,1,
77136,1,5,2314,22,
77141,47,1,2517,2315,
771516,0,487,1,328,
77161425,1,1303,1430,1,
77171096,1694,1,93,1435,
77181,1550,1440,1,827,
77191448,1,2532,2316,16,
77200,628,1,1011,1224,
77211,107,1455,1,1114,
77221461,1,2542,1909,1,
77231871,2317,16,0,348,
77241,1370,1570,1,1478,
77251575,1,118,1473,1,
77261123,1478,1,371,1483,
77271,1377,1489,1,375,
77281494,1,1882,2318,16,
77290,363,1,377,1499,
77301,352,1467,1,379,
77311504,1,1341,1420,1,
7732130,1532,1,2074,2319,
773316,0,641,1,373,
77341527,1,1012,2320,16,
77350,703,1,380,1509,
77361,143,1537,1,1152,
77371543,1,1406,1548,1,
77381159,1555,1,157,1560,
77391,1413,1565,1,883,
77401515,1,2512,1882,1,
77411296,1290,1,172,1586,
77421,1665,1591,1,2766,
77431934,1,1939,2321,16,
77440,482,1,1188,1596,
77451,1442,1601,1,188,
77461635,1,942,1607,1,
77471195,1613,1,1449,1618,
77481,1701,1623,1,447,
77491628,1,1094,2322,16,
77500,785,1,205,1640,
77511,2554,2323,17,2324,
775215,2325,4,60,37,
77530,86,0,101,0,
775499,0,116,0,111,
77550,114,0,65,0,
7756114,0,103,0,117,
77570,109,0,101,0,
7758110,0,116,0,68,
77590,101,0,99,0,
7760108,0,97,0,114,
77610,97,0,116,0,
7762105,0,111,0,110,
77630,76,0,105,0,
7764115,0,116,0,1,
7765-1,1,5,2326,20,
77662327,4,62,86,0,
7767101,0,99,0,116,
77680,111,0,114,0,
776965,0,114,0,103,
77700,117,0,109,0,
7771101,0,110,0,116,
77720,68,0,101,0,
777399,0,108,0,97,
77740,114,0,97,0,
7775116,0,105,0,111,
77760,110,0,76,0,
7777105,0,115,0,116,
77780,95,0,49,0,
77791,208,1,3,1,
77802,1,1,2328,22,
77811,44,1,2467,1938,
77821,464,1944,1,2197,
77832329,16,0,772,1,
77841224,1645,1,223,1650,
77851,1730,1655,1,2571,
77862330,16,0,673,1,
7787477,1666,1,1231,1671,
77881,479,1676,1,480,
77891681,1,1485,1687,1,
7790459,1949,1,476,1660,
77911,242,1700,1,478,
77921705,1,481,1951,1,
77931001,1710,1,2508,1956,
77941,18,2331,19,564,
77951,18,2332,5,84,
77961,1011,1224,1,1012,
77972333,16,0,562,1,
77981013,1381,1,262,1241,
77991,1267,2334,16,0,
7800562,1,515,2335,16,
78010,562,1,1521,2336,
780216,0,562,1,525,
78031339,1,2788,2337,16,
78040,562,1,283,1295,
78051,2299,2338,16,0,
7806562,1,42,2339,16,
78070,562,1,40,1300,
78081,44,1306,1,47,
78091307,1,1303,2340,16,
78100,562,1,1555,2341,
781116,0,562,1,50,
78121324,1,48,1313,1,
781349,1319,1,51,1329,
78141,63,1345,1,305,
78151334,1,66,1351,1,
781667,1356,1,68,1361,
78171,69,1366,1,70,
78181371,1,73,2342,16,
78190,562,1,74,1376,
78201,328,1425,1,1048,
78212343,16,0,562,1,
782282,2344,16,0,562,
78231,1840,2345,16,0,
7824562,1,1591,2346,16,
78250,562,1,1341,2347,
782616,0,562,1,1096,
78271694,1,93,1435,1,
7828352,1467,1,107,2348,
782916,0,562,1,1114,
78301461,1,118,2349,16,
78310,562,1,1123,2350,
783216,0,562,1,371,
78331483,1,1628,2351,16,
78340,562,1,375,1494,
78351,1882,2352,16,0,
7836562,1,377,1499,1,
7837379,1504,1,380,1509,
78381,883,2353,16,0,
7839562,1,373,1527,1,
7840130,2354,16,0,562,
78411,143,2355,16,0,
7842562,1,387,2356,16,
78430,562,1,1159,2357,
784416,0,562,1,157,
78452358,16,0,562,1,
78461413,2359,16,0,562,
78471,1665,2360,16,0,
7848562,1,412,2361,16,
78490,562,1,1377,2362,
785016,0,562,1,172,
78512363,16,0,562,1,
78521939,2364,16,0,562,
78531,437,2365,16,0,
7854562,1,188,2366,16,
78550,562,1,942,2367,
785616,0,562,1,1195,
78572368,16,0,562,1,
78581449,2369,16,0,562,
78591,1701,2370,16,0,
7860562,1,447,1628,1,
7861205,2371,16,0,562,
78621,827,2372,16,0,
7863562,1,223,2373,16,
78640,562,1,476,1660,
78651,477,1666,1,1231,
78662374,16,0,562,1,
7867479,1676,1,480,1681,
78681,1485,2375,16,0,
7869562,1,1737,2376,16,
78700,562,1,242,2377,
787116,0,562,1,478,
78721705,1,1001,1710,1,
78731002,1715,1,19,2378,
787419,254,1,19,2379,
78755,176,1,256,2380,
787616,0,252,1,1261,
78772381,16,0,252,1,
78781011,1224,1,1012,2382,
787916,0,521,1,2458,
7880998,1,262,1241,1,
78811267,2383,16,0,521,
78821,2021,840,1,1521,
78832384,16,0,521,1,
78841775,2385,16,0,252,
78851,2029,847,1,2030,
7886853,1,2031,858,1,
78872032,863,1,2033,868,
78881,277,2386,16,0,
7889252,1,2788,2387,16,
78900,521,1,2037,879,
78911,2039,884,1,32,
78922388,16,0,252,1,
78932464,1021,1,2293,2389,
789416,0,252,1,2043,
7895896,1,2045,901,1,
78962299,2390,16,0,521,
78971,41,2391,16,0,
7898252,1,42,2392,16,
78990,521,1,40,1300,
79001,44,1306,1,43,
79012393,16,0,252,1,
79021804,2394,16,0,252,
79031,48,1313,1,49,
79041319,1,47,1307,1,
790551,1329,1,52,2395,
790616,0,252,1,50,
79071324,1,305,1334,1,
79081096,1694,1,1515,2396,
790916,0,252,1,2318,
79102397,16,0,252,1,
7911283,1295,1,63,1345,
79121,66,1351,1,67,
79131356,1,68,1361,1,
791469,1366,1,70,1371,
79151,71,2398,16,0,
7916252,1,73,2399,16,
79170,521,1,74,1376,
79181,1013,1381,1,76,
79192400,16,0,252,1,
79201834,2401,16,0,252,
79211,2337,2402,16,0,
7922252,1,79,2403,16,
79230,252,1,1335,2404,
792416,0,252,1,299,
79252405,16,0,252,1,
792682,2406,16,0,521,
79271,1840,2407,16,0,
7928521,1,1297,2408,16,
79290,252,1,85,2409,
793016,0,252,1,1341,
79312410,16,0,521,1,
793289,2411,16,0,252,
79331,1303,2412,16,0,
7934521,1,2035,874,1,
793593,1435,1,322,2413,
793616,0,252,1,97,
79372414,16,0,252,1,
79382041,890,1,1555,2415,
793916,0,521,1,827,
79402416,16,0,521,1,
7941102,2417,16,0,252,
79421,1860,943,1,1803,
7943909,1,2364,949,1,
7944107,2418,16,0,521,
79451,509,2419,16,0,
7946252,1,1114,1461,1,
7947112,2420,16,0,252,
79481,1117,2421,16,0,
7949252,1,352,1467,1,
79501873,958,1,118,2422,
795116,0,521,1,1123,
79522423,16,0,521,1,
7953371,1483,1,515,2424,
795416,0,521,1,1377,
79552425,16,0,521,1,
7956124,2426,16,0,252,
79571,1882,2427,16,0,
7958521,1,377,1499,1,
7959379,1504,1,380,1509,
79601,130,2428,16,0,
7961521,1,346,2429,16,
79620,252,1,2075,2430,
796316,0,252,1,373,
79641527,1,387,2431,16,
79650,521,1,137,2432,
796616,0,252,1,143,
79672433,16,0,521,1,
79681901,2434,16,0,252,
79691,1048,2435,16,0,
7970521,1,1153,2436,16,
79710,252,1,375,1494,
79721,151,2437,16,0,
7973252,1,1407,2438,16,
79740,252,1,1659,2439,
797516,0,252,1,2413,
79762440,16,0,252,1,
79771159,2441,16,0,521,
79781,381,2442,16,0,
7979252,1,157,2443,16,
79800,521,1,1413,2444,
798116,0,521,1,883,
79822445,16,0,521,1,
79831371,2446,16,0,252,
79841,328,1425,1,2105,
7985936,1,2106,2447,16,
79860,252,1,166,2448,
798716,0,252,1,525,
79882449,16,0,252,1,
79891622,2450,16,0,252,
79901,406,2451,16,0,
7991252,1,1574,921,1,
7992172,2452,16,0,521,
79931,1931,983,1,412,
79942453,16,0,521,1,
79951933,2454,16,0,252,
79961,1876,2455,16,0,
7997252,1,431,2456,16,
79980,252,1,1585,2457,
799916,0,252,1,182,
80002458,16,0,252,1,
80011628,2459,16,0,521,
80021,1189,2460,16,0,
8003252,1,437,2461,16,
80040,521,1,1591,2462,
800516,0,521,1,188,
80062463,16,0,521,1,
80071695,2464,16,0,252,
80081,2198,2465,16,0,
8009252,1,1195,2466,16,
80100,521,1,1449,2467,
801116,0,521,1,1701,
80122468,16,0,521,1,
8013447,2469,16,0,252,
80141,2782,2470,16,0,
8015252,1,199,2471,16,
80160,252,1,2459,1004,
80171,1958,2472,16,0,
8018252,1,2462,1011,1,
80191657,1016,1,205,2473,
802016,0,521,1,459,
80212474,16,0,252,1,
8022462,2475,16,0,252,
80231,1665,2476,16,0,
8024521,1,217,2477,16,
80250,252,1,2227,1030,
80261,942,2478,16,0,
8027521,1,1225,2479,16,
80280,252,1,223,2480,
802916,0,521,1,1479,
80302481,16,0,252,1,
80311731,2482,16,0,252,
80321,477,1666,1,1231,
80332483,16,0,521,1,
8034479,1676,1,480,1681,
80351,1485,2484,16,0,
8036521,1,1737,2485,16,
80370,521,1,1989,1038,
80381,1990,2486,16,0,
8039252,1,1443,2487,16,
80400,252,1,236,2488,
804116,0,252,1,2136,
8042965,1,476,1660,1,
8043242,2489,16,0,521,
80441,478,1705,1,1939,
80452490,16,0,521,1,
80461001,1710,1,1002,1715,
80471,1756,2491,16,0,
8048252,1,20,2492,19,
8049496,1,20,2493,5,
805084,1,1011,1224,1,
80511012,2494,16,0,494,
80521,1013,1381,1,262,
80531241,1,1267,2495,16,
80540,494,1,515,2496,
805516,0,494,1,1521,
80562497,16,0,494,1,
8057525,1339,1,2788,2498,
805816,0,494,1,283,
80591295,1,2299,2499,16,
80600,494,1,42,2500,
806116,0,494,1,40,
80621300,1,44,1306,1,
806347,1307,1,1303,2501,
806416,0,494,1,1555,
80652502,16,0,494,1,
806650,1324,1,48,1313,
80671,49,1319,1,51,
80681329,1,63,1345,1,
8069305,1334,1,66,1351,
80701,67,1356,1,68,
80711361,1,69,1366,1,
807270,1371,1,73,2503,
807316,0,494,1,74,
80741376,1,328,2504,16,
80750,494,1,1048,2505,
807616,0,494,1,82,
80772506,16,0,494,1,
80781840,2507,16,0,494,
80791,1591,2508,16,0,
8080494,1,1341,2509,16,
80810,494,1,1096,1694,
80821,93,1435,1,352,
80832510,16,0,494,1,
8084107,2511,16,0,494,
80851,1114,1461,1,118,
80862512,16,0,494,1,
80871123,2513,16,0,494,
80881,371,1483,1,1628,
80892514,16,0,494,1,
8090375,1494,1,1882,2515,
809116,0,494,1,377,
80921499,1,379,1504,1,
8093380,1509,1,883,2516,
809416,0,494,1,373,
80951527,1,130,2517,16,
80960,494,1,143,2518,
809716,0,494,1,387,
80982519,16,0,494,1,
80991159,2520,16,0,494,
81001,157,2521,16,0,
8101494,1,1413,2522,16,
81020,494,1,1665,2523,
810316,0,494,1,412,
81042524,16,0,494,1,
81051377,2525,16,0,494,
81061,172,2526,16,0,
8107494,1,1939,2527,16,
81080,494,1,437,2528,
810916,0,494,1,188,
81102529,16,0,494,1,
8111942,2530,16,0,494,
81121,1195,2531,16,0,
8113494,1,1449,2532,16,
81140,494,1,1701,2533,
811516,0,494,1,447,
81161628,1,205,2534,16,
81170,494,1,827,2535,
811816,0,494,1,223,
81192536,16,0,494,1,
8120476,1660,1,477,1666,
81211,1231,2537,16,0,
8122494,1,479,1676,1,
8123480,1681,1,1485,2538,
812416,0,494,1,1737,
81252539,16,0,494,1,
8126242,2540,16,0,494,
81271,478,1705,1,1001,
81281710,1,1002,1715,1,
812921,2541,19,468,1,
813021,2542,5,84,1,
81311011,1224,1,1012,2543,
813216,0,466,1,1013,
81331381,1,262,1241,1,
81341267,2544,16,0,466,
81351,515,2545,16,0,
8136466,1,1521,2546,16,
81370,466,1,525,1339,
81381,2788,2547,16,0,
8139466,1,283,1295,1,
81402299,2548,16,0,466,
81411,42,2549,16,0,
8142466,1,40,1300,1,
814344,1306,1,47,1307,
81441,1303,2550,16,0,
8145466,1,1555,2551,16,
81460,466,1,50,1324,
81471,48,1313,1,49,
81481319,1,51,1329,1,
814963,1345,1,305,1334,
81501,66,1351,1,67,
81511356,1,68,1361,1,
815269,1366,1,70,1371,
81531,73,2552,16,0,
8154466,1,74,1376,1,
8155328,2553,16,0,466,
81561,1048,2554,16,0,
8157466,1,82,2555,16,
81580,466,1,1840,2556,
815916,0,466,1,1591,
81602557,16,0,466,1,
81611341,2558,16,0,466,
81621,1096,1694,1,93,
81631435,1,352,2559,16,
81640,466,1,107,2560,
816516,0,466,1,1114,
81661461,1,118,2561,16,
81670,466,1,1123,2562,
816816,0,466,1,371,
81691483,1,1628,2563,16,
81700,466,1,375,1494,
81711,1882,2564,16,0,
8172466,1,377,1499,1,
8173379,1504,1,380,1509,
81741,883,2565,16,0,
8175466,1,373,1527,1,
8176130,2566,16,0,466,
81771,143,2567,16,0,
8178466,1,387,2568,16,
81790,466,1,1159,2569,
818016,0,466,1,157,
81812570,16,0,466,1,
81821413,2571,16,0,466,
81831,1665,2572,16,0,
8184466,1,412,2573,16,
81850,466,1,1377,2574,
818616,0,466,1,172,
81872575,16,0,466,1,
81881939,2576,16,0,466,
81891,437,2577,16,0,
8190466,1,188,2578,16,
81910,466,1,942,2579,
819216,0,466,1,1195,
81932580,16,0,466,1,
81941449,2581,16,0,466,
81951,1701,2582,16,0,
8196466,1,447,1628,1,
8197205,2583,16,0,466,
81981,827,2584,16,0,
8199466,1,223,2585,16,
82000,466,1,476,1660,
82011,477,1666,1,1231,
82022586,16,0,466,1,
8203479,1676,1,480,1681,
82041,1485,2587,16,0,
8205466,1,1737,2588,16,
82060,466,1,242,2589,
820716,0,466,1,478,
82081705,1,1001,1710,1,
82091002,1715,1,22,2590,
821019,419,1,22,2591,
82115,84,1,1011,1224,
82121,1012,2592,16,0,
8213417,1,1013,1381,1,
8214262,1241,1,1267,2593,
821516,0,417,1,515,
82162594,16,0,417,1,
82171521,2595,16,0,417,
82181,525,1339,1,2788,
82192596,16,0,417,1,
8220283,1295,1,2299,2597,
822116,0,417,1,42,
82222598,16,0,417,1,
822340,1300,1,44,1306,
82241,47,1307,1,1303,
82252599,16,0,417,1,
82261555,2600,16,0,417,
82271,50,1324,1,48,
82281313,1,49,1319,1,
822951,1329,1,63,1345,
82301,305,1334,1,66,
82311351,1,67,1356,1,
823268,1361,1,69,1366,
82331,70,1371,1,73,
82342601,16,0,417,1,
823574,1376,1,328,2602,
823616,0,417,1,1048,
82372603,16,0,417,1,
823882,2604,16,0,417,
82391,1840,2605,16,0,
8240417,1,1591,2606,16,
82410,417,1,1341,2607,
824216,0,417,1,1096,
82431694,1,93,1435,1,
8244352,2608,16,0,417,
82451,107,2609,16,0,
8246417,1,1114,1461,1,
8247118,2610,16,0,417,
82481,1123,2611,16,0,
8249417,1,371,1483,1,
82501628,2612,16,0,417,
82511,375,1494,1,1882,
82522613,16,0,417,1,
8253377,1499,1,379,1504,
82541,380,1509,1,883,
82552614,16,0,417,1,
8256373,1527,1,130,2615,
825716,0,417,1,143,
82582616,16,0,417,1,
8259387,2617,16,0,417,
82601,1159,2618,16,0,
8261417,1,157,2619,16,
82620,417,1,1413,2620,
826316,0,417,1,1665,
82642621,16,0,417,1,
8265412,2622,16,0,417,
82661,1377,2623,16,0,
8267417,1,172,2624,16,
82680,417,1,1939,2625,
826916,0,417,1,437,
82702626,16,0,417,1,
8271188,2627,16,0,417,
82721,942,2628,16,0,
8273417,1,1195,2629,16,
82740,417,1,1449,2630,
827516,0,417,1,1701,
82762631,16,0,417,1,
8277447,1628,1,205,2632,
827816,0,417,1,827,
82792633,16,0,417,1,
8280223,2634,16,0,417,
82811,476,1660,1,477,
82821666,1,1231,2635,16,
82830,417,1,479,1676,
82841,480,1681,1,1485,
82852636,16,0,417,1,
82861737,2637,16,0,417,
82871,242,2638,16,0,
8288417,1,478,1705,1,
82891001,1710,1,1002,1715,
82901,23,2639,19,582,
82911,23,2640,5,38,
82921,1901,2641,16,0,
8293580,1,2075,2642,16,
82940,580,1,1860,943,
82951,1803,909,1,1804,
82962643,16,0,580,1,
82972413,2644,16,0,580,
82981,2198,2645,16,0,
8299580,1,1873,958,1,
83001657,1016,1,1989,1038,
83011,1990,2646,16,0,
8302580,1,1775,2647,16,
83030,580,1,32,2648,
830416,0,580,1,2105,
8305936,1,2106,2649,16,
83060,580,1,2364,949,
83071,2227,1030,1,2337,
83082650,16,0,580,1,
83092021,840,1,2458,998,
83101,2459,1004,1,2462,
83111011,1,2136,965,1,
83122464,1021,1,2029,847,
83131,2030,853,1,2031,
8314858,1,2032,863,1,
83152033,868,1,2035,874,
83161,2037,879,1,2039,
8317884,1,1931,983,1,
83182041,890,1,2043,896,
83191,2045,901,1,1574,
8320921,1,1958,2651,16,
83210,580,1,24,2652,
832219,196,1,24,2653,
83235,5,1,44,2654,
832416,0,194,1,377,
83252655,16,0,618,1,
832640,2656,16,0,796,
83271,63,2657,16,0,
8328222,1,373,2658,16,
83290,614,1,25,2659,
833019,324,1,25,2660,
83315,177,1,256,2661,
833216,0,623,1,1261,
83332662,16,0,623,1,
83341011,1224,1,1012,2663,
833516,0,322,1,2458,
8336998,1,262,1241,1,
83371267,2664,16,0,322,
83381,2021,840,1,1521,
83392665,16,0,322,1,
83401775,2666,16,0,623,
83411,2029,847,1,2030,
8342853,1,2031,858,1,
83432032,863,1,2033,868,
83441,277,2667,16,0,
8345623,1,2788,2668,16,
83460,322,1,2037,879,
83471,2039,884,1,32,
83482669,16,0,623,1,
83492464,1021,1,2293,2670,
835016,0,623,1,2043,
8351896,1,2045,901,1,
83522299,2671,16,0,322,
83531,41,2672,16,0,
8354623,1,42,2673,16,
83550,322,1,40,1300,
83561,44,1306,1,43,
83572674,16,0,623,1,
83581804,2675,16,0,623,
83591,48,1313,1,49,
83601319,1,47,1307,1,
836151,1329,1,52,2676,
836216,0,623,1,50,
83631324,1,305,1334,1,
83641096,1694,1,1515,2677,
836516,0,623,1,2318,
83662678,16,0,623,1,
836762,2679,16,0,623,
83681,63,1345,1,66,
83691351,1,67,1356,1,
837068,1361,1,69,1366,
83711,70,1371,1,71,
83722680,16,0,623,1,
8373283,1295,1,73,2681,
837416,0,322,1,74,
83751376,1,1013,1381,1,
837676,2682,16,0,623,
83771,1834,2683,16,0,
8378623,1,2337,2684,16,
83790,623,1,79,2685,
838016,0,623,1,1335,
83812686,16,0,623,1,
8382299,2687,16,0,623,
83831,82,2688,16,0,
8384322,1,1840,2689,16,
83850,322,1,1297,2690,
838616,0,623,1,85,
83872691,16,0,623,1,
83881341,2692,16,0,322,
83891,89,2693,16,0,
8390623,1,1303,2694,16,
83910,322,1,2035,874,
83921,93,1435,1,322,
83932695,16,0,623,1,
839497,2696,16,0,623,
83951,2041,890,1,1555,
83962697,16,0,322,1,
8397827,2698,16,0,322,
83981,102,2699,16,0,
8399623,1,1860,943,1,
84001803,909,1,2364,949,
84011,107,2700,16,0,
8402322,1,509,2701,16,
84030,623,1,1114,1461,
84041,112,2702,16,0,
8405623,1,1117,2703,16,
84060,623,1,352,1467,
84071,1873,958,1,118,
84081473,1,1123,2704,16,
84090,322,1,371,1483,
84101,515,2705,16,0,
8411322,1,1377,2706,16,
84120,322,1,124,2707,
841316,0,623,1,1882,
84142708,16,0,322,1,
8415377,1499,1,379,1504,
84161,380,1509,1,130,
84171532,1,346,2709,16,
84180,623,1,2075,2710,
841916,0,623,1,373,
84201527,1,387,2711,16,
84210,322,1,137,2712,
842216,0,623,1,143,
84232713,16,0,322,1,
84241901,2714,16,0,623,
84251,1048,1462,1,1153,
84262715,16,0,623,1,
8427375,1494,1,151,2716,
842816,0,623,1,1407,
84292717,16,0,623,1,
84301659,2718,16,0,623,
84311,2413,2719,16,0,
8432623,1,1159,2720,16,
84330,322,1,381,2721,
843416,0,623,1,157,
84352722,16,0,322,1,
84361413,2723,16,0,322,
84371,883,2724,16,0,
8438322,1,1371,2725,16,
84390,623,1,328,1425,
84401,2105,936,1,2106,
84412726,16,0,623,1,
8442166,2727,16,0,623,
84431,525,2728,16,0,
8444623,1,1622,2729,16,
84450,623,1,406,2730,
844616,0,623,1,1574,
8447921,1,172,1586,1,
84481931,983,1,412,2731,
844916,0,322,1,1933,
84502732,16,0,623,1,
84511876,2733,16,0,623,
84521,431,2734,16,0,
8453623,1,1585,2735,16,
84540,623,1,182,2736,
845516,0,623,1,1628,
84562737,16,0,322,1,
84571189,2738,16,0,623,
84581,437,2739,16,0,
8459322,1,1591,2740,16,
84600,322,1,188,1635,
84611,1695,2741,16,0,
8462623,1,2198,2742,16,
84630,623,1,1195,2743,
846416,0,322,1,1449,
84652744,16,0,322,1,
84661701,2745,16,0,322,
84671,447,2746,16,0,
8468623,1,2782,2747,16,
84690,623,1,199,2748,
847016,0,623,1,2459,
84711004,1,1958,2749,16,
84720,623,1,2462,1011,
84731,1657,1016,1,205,
84742750,16,0,322,1,
8475459,2751,16,0,623,
84761,462,2752,16,0,
8477623,1,1665,2753,16,
84780,322,1,217,2754,
847916,0,623,1,2227,
84801030,1,942,1607,1,
84811225,2755,16,0,623,
84821,223,2756,16,0,
8483322,1,1479,2757,16,
84840,623,1,1731,2758,
848516,0,623,1,477,
84861666,1,1231,2759,16,
84870,322,1,479,1676,
84881,480,1681,1,1485,
84892760,16,0,322,1,
84901737,2761,16,0,322,
84911,1989,1038,1,1990,
84922762,16,0,623,1,
84931443,2763,16,0,623,
84941,236,2764,16,0,
8495623,1,2136,965,1,
8496476,1660,1,242,2765,
849716,0,322,1,478,
84981705,1,1939,2766,16,
84990,322,1,1001,1710,
85001,1002,1715,1,1756,
85012767,16,0,623,1,
850226,2768,19,343,1,
850326,2769,5,84,1,
85041011,1224,1,1012,2770,
850516,0,341,1,1013,
85061381,1,262,1241,1,
85071267,2771,16,0,341,
85081,515,2772,16,0,
8509770,1,1521,2773,16,
85100,341,1,525,1339,
85111,2788,2774,16,0,
8512341,1,283,1295,1,
85132299,2775,16,0,341,
85141,42,2776,16,0,
8515341,1,40,1300,1,
851644,1306,1,47,1307,
85171,1303,2777,16,0,
8518341,1,1555,2778,16,
85190,341,1,50,1324,
85201,48,1313,1,49,
85211319,1,51,1329,1,
852263,1345,1,305,1334,
85231,66,1351,1,67,
85241356,1,68,1361,1,
852569,1366,1,70,1371,
85261,73,2779,16,0,
8527341,1,74,1376,1,
8528328,1425,1,1048,1462,
85291,82,2780,16,0,
8530341,1,1840,2781,16,
85310,341,1,1591,2782,
853216,0,341,1,1341,
85332783,16,0,341,1,
85341096,1694,1,93,1435,
85351,352,1467,1,107,
85362784,16,0,341,1,
85371114,1461,1,118,1473,
85381,1123,2785,16,0,
8539341,1,371,1483,1,
85401628,2786,16,0,341,
85411,375,1494,1,1882,
85422787,16,0,341,1,
8543377,1499,1,379,1504,
85441,380,1509,1,883,
85452788,16,0,341,1,
8546373,1527,1,130,1532,
85471,143,2789,16,0,
8548341,1,387,2790,16,
85490,341,1,1159,2791,
855016,0,341,1,157,
85512792,16,0,341,1,
85521413,2793,16,0,341,
85531,1665,2794,16,0,
8554341,1,412,2795,16,
85550,341,1,1377,2796,
855616,0,341,1,172,
85571586,1,1939,2797,16,
85580,341,1,437,2798,
855916,0,694,1,188,
85601635,1,942,1607,1,
85611195,2799,16,0,341,
85621,1449,2800,16,0,
8563341,1,1701,2801,16,
85640,341,1,447,1628,
85651,205,2802,16,0,
8566341,1,827,2803,16,
85670,341,1,223,2804,
856816,0,341,1,476,
85691660,1,477,1666,1,
85701231,2805,16,0,341,
85711,479,1676,1,480,
85721681,1,1485,2806,16,
85730,341,1,1737,2807,
857416,0,341,1,242,
85752808,16,0,341,1,
8576478,1705,1,1001,1710,
85771,1002,1715,1,27,
85782809,19,706,1,27,
85792810,5,95,1,256,
85802811,16,0,704,1,
85811261,2812,16,0,704,
85821,509,2813,16,0,
8583704,1,1515,2814,16,
85840,704,1,2021,840,
85851,1775,2815,16,0,
8586704,1,2029,847,1,
85872030,853,1,2031,858,
85881,2032,863,1,2033,
8589868,1,277,2816,16,
85900,704,1,2035,874,
85911,2037,879,1,2039,
8592884,1,32,2817,16,
85930,704,1,2041,890,
85941,2293,2818,16,0,
8595704,1,2043,896,1,
85962045,901,1,41,2819,
859716,0,704,1,1297,
85982820,16,0,704,1,
859943,2821,16,0,704,
86001,1803,909,1,1804,
86012822,16,0,704,1,
8602299,2823,16,0,704,
86031,52,2824,16,0,
8604704,1,2318,2825,16,
86050,704,1,62,2826,
860616,0,704,1,2075,
86072827,16,0,704,1,
86081574,921,1,71,2828,
860916,0,704,1,76,
86102829,16,0,704,1,
86111834,2830,16,0,704,
86121,2337,2831,16,0,
8613704,1,79,2832,16,
86140,704,1,1335,2833,
861516,0,704,1,322,
86162834,16,0,704,1,
861785,2835,16,0,704,
86181,89,2836,16,0,
8619704,1,346,2837,16,
86200,704,1,2105,936,
86211,2106,2838,16,0,
8622704,1,97,2839,16,
86230,704,1,1860,943,
86241,2364,949,1,102,
86252840,16,0,704,1,
86262782,2841,16,0,704,
86271,112,2842,16,0,
8628704,1,1117,2843,16,
86290,704,1,1873,958,
86301,1876,2844,16,0,
8631704,1,124,2845,16,
86320,704,1,2136,965,
86331,381,2846,16,0,
8634704,1,525,2847,16,
86350,704,1,137,2848,
863616,0,704,1,1901,
86372849,16,0,704,1,
86381153,2850,16,0,704,
86391,151,2851,16,0,
8640704,1,1407,2852,16,
86410,704,1,1659,2853,
864216,0,704,1,2413,
86432854,16,0,704,1,
8644406,2855,16,0,704,
86451,1371,2856,16,0,
8646704,1,166,2857,16,
86470,704,1,1622,2858,
864816,0,704,1,1931,
8649983,1,1933,2859,16,
86500,704,1,431,2860,
865116,0,704,1,1585,
86522861,16,0,704,1,
8653182,2862,16,0,704,
86541,1189,2863,16,0,
8655704,1,1443,2864,16,
86560,704,1,1695,2865,
865716,0,704,1,2198,
86582866,16,0,704,1,
8659447,2867,16,0,704,
86601,2458,998,1,2459,
86611004,1,1958,2868,16,
86620,704,1,2462,1011,
86631,1657,1016,1,2464,
86641021,1,199,2869,16,
86650,704,1,459,2870,
866616,0,704,1,462,
86672871,16,0,704,1,
8668217,2872,16,0,704,
86691,2227,1030,1,1225,
86702873,16,0,704,1,
86711479,2874,16,0,704,
86721,1731,2875,16,0,
8673704,1,1989,1038,1,
86741990,2876,16,0,704,
86751,236,2877,16,0,
8676704,1,1756,2878,16,
86770,704,1,28,2879,
867819,734,1,28,2880,
86795,60,1,328,1425,
86801,223,1650,1,1096,
86811694,1,118,1473,1,
8682883,1515,1,525,1339,
86831,1001,1710,1,130,
86841532,1,459,1949,1,
86851114,1461,1,352,1467,
86861,447,1628,1,464,
86871944,1,1011,1224,1,
86881013,1381,1,242,1700,
86891,143,1537,1,40,
86901300,1,41,1916,1,
869142,1920,1,479,1676,
86921,44,1306,1,481,
86931951,1,373,1527,1,
869447,1307,1,157,1560,
86951,49,1319,1,50,
86961324,1,48,1313,1,
8697379,1504,1,380,1509,
86981,51,1329,1,476,
86991660,1,371,1483,1,
8700478,1705,1,1048,1462,
87011,375,1494,1,172,
87021586,1,262,1241,1,
8703283,1295,1,63,1345,
87041,67,1356,1,68,
87051361,1,69,1366,1,
870666,1351,1,461,2881,
870716,0,732,1,74,
87081376,1,377,1499,1,
87091002,1715,1,70,1371,
87101,188,1635,1,82,
87111403,1,305,1334,1,
8712477,1666,1,827,1448,
87131,93,1435,1,480,
87141681,1,205,1640,1,
8715942,1607,1,107,1455,
87161,29,2882,19,312,
87171,29,2883,5,84,
87181,1011,1224,1,1012,
87192884,16,0,310,1,
87201013,1381,1,262,1241,
87211,1267,2885,16,0,
8722310,1,515,2886,16,
87230,310,1,1521,2887,
872416,0,310,1,525,
87251339,1,2788,2888,16,
87260,310,1,283,1295,
87271,2299,2889,16,0,
8728310,1,42,2890,16,
87290,310,1,40,1300,
87301,44,1306,1,47,
87311307,1,1303,2891,16,
87320,310,1,1555,2892,
873316,0,310,1,50,
87341324,1,48,1313,1,
873549,1319,1,51,1329,
87361,63,1345,1,305,
87371334,1,66,1351,1,
873867,1356,1,68,1361,
87391,69,1366,1,70,
87401371,1,73,2893,16,
87410,310,1,74,1376,
87421,328,1425,1,1048,
87431462,1,82,2894,16,
87440,310,1,1840,2895,
874516,0,310,1,1591,
87462896,16,0,310,1,
87471341,2897,16,0,310,
87481,1096,1694,1,93,
87491435,1,352,1467,1,
8750107,2898,16,0,310,
87511,1114,1461,1,118,
87521473,1,1123,2899,16,
87530,310,1,371,1483,
87541,1628,2900,16,0,
8755310,1,375,1494,1,
87561882,2901,16,0,310,
87571,377,1499,1,379,
87581504,1,380,1509,1,
8759883,2902,16,0,310,
87601,373,1527,1,130,
87611532,1,143,1537,1,
8762387,2903,16,0,310,
87631,1159,2904,16,0,
8764310,1,157,1560,1,
87651413,2905,16,0,310,
87661,1665,2906,16,0,
8767310,1,412,2907,16,
87680,310,1,1377,2908,
876916,0,310,1,172,
87701586,1,1939,2909,16,
87710,310,1,437,2910,
877216,0,310,1,188,
87731635,1,942,1607,1,
87741195,2911,16,0,310,
87751,1449,2912,16,0,
8776310,1,1701,2913,16,
87770,310,1,447,1628,
87781,205,2914,16,0,
8779310,1,827,2915,16,
87800,310,1,223,2916,
878116,0,310,1,476,
87821660,1,477,1666,1,
87831231,2917,16,0,310,
87841,479,1676,1,480,
87851681,1,1485,2918,16,
87860,310,1,1737,2919,
878716,0,310,1,242,
87882920,16,0,310,1,
8789478,1705,1,1001,1710,
87901,1002,1715,1,30,
87912921,19,296,1,30,
87922922,5,84,1,1011,
87931224,1,1012,2923,16,
87940,294,1,1013,1381,
87951,262,1241,1,1267,
87962924,16,0,294,1,
8797515,2925,16,0,294,
87981,1521,2926,16,0,
8799294,1,525,1339,1,
88002788,2927,16,0,294,
88011,283,1295,1,2299,
88022928,16,0,294,1,
880342,2929,16,0,294,
88041,40,1300,1,44,
88051306,1,47,1307,1,
88061303,2930,16,0,294,
88071,1555,2931,16,0,
8808294,1,50,1324,1,
880948,1313,1,49,1319,
88101,51,1329,1,63,
88111345,1,305,1334,1,
881266,1351,1,67,1356,
88131,68,1361,1,69,
88141366,1,70,1371,1,
881573,2932,16,0,294,
88161,74,1376,1,328,
88171425,1,1048,1462,1,
881882,2933,16,0,294,
88191,1840,2934,16,0,
8820294,1,1591,2935,16,
88210,294,1,1341,2936,
882216,0,294,1,1096,
88231694,1,93,1435,1,
8824352,1467,1,107,2937,
882516,0,294,1,1114,
88261461,1,118,1473,1,
88271123,2938,16,0,294,
88281,371,1483,1,1628,
88292939,16,0,294,1,
8830375,1494,1,1882,2940,
883116,0,294,1,377,
88321499,1,379,1504,1,
8833380,1509,1,883,2941,
883416,0,294,1,373,
88351527,1,130,1532,1,
8836143,1537,1,387,2942,
883716,0,294,1,1159,
88382943,16,0,294,1,
8839157,1560,1,1413,2944,
884016,0,294,1,1665,
88412945,16,0,294,1,
8842412,2946,16,0,294,
88431,1377,2947,16,0,
8844294,1,172,1586,1,
88451939,2948,16,0,294,
88461,437,2949,16,0,
8847294,1,188,1635,1,
8848942,1607,1,1195,2950,
884916,0,294,1,1449,
88502951,16,0,294,1,
88511701,2952,16,0,294,
88521,447,1628,1,205,
88532953,16,0,294,1,
8854827,2954,16,0,294,
88551,223,2955,16,0,
8856294,1,476,1660,1,
8857477,1666,1,1231,2956,
885816,0,294,1,479,
88591676,1,480,1681,1,
88601485,2957,16,0,294,
88611,1737,2958,16,0,
8862294,1,242,2959,16,
88630,294,1,478,1705,
88641,1001,1710,1,1002,
88651715,1,31,2960,19,
8866281,1,31,2961,5,
886784,1,1011,1224,1,
88681012,2962,16,0,279,
88691,1013,1381,1,262,
88701241,1,1267,2963,16,
88710,279,1,515,2964,
887216,0,279,1,1521,
88732965,16,0,279,1,
8874525,1339,1,2788,2966,
887516,0,279,1,283,
88761295,1,2299,2967,16,
88770,279,1,42,2968,
887816,0,279,1,40,
88791300,1,44,1306,1,
888047,1307,1,1303,2969,
888116,0,279,1,1555,
88822970,16,0,279,1,
888350,1324,1,48,1313,
88841,49,1319,1,51,
88851329,1,63,1345,1,
8886305,1334,1,66,1351,
88871,67,1356,1,68,
88881361,1,69,1366,1,
888970,1371,1,73,2971,
889016,0,279,1,74,
88911376,1,328,1425,1,
88921048,1462,1,82,2972,
889316,0,279,1,1840,
88942973,16,0,279,1,
88951591,2974,16,0,279,
88961,1341,2975,16,0,
8897279,1,1096,1694,1,
889893,1435,1,352,1467,
88991,107,2976,16,0,
8900279,1,1114,1461,1,
8901118,1473,1,1123,2977,
890216,0,279,1,371,
89031483,1,1628,2978,16,
89040,279,1,375,1494,
89051,1882,2979,16,0,
8906279,1,377,1499,1,
8907379,1504,1,380,1509,
89081,883,2980,16,0,
8909279,1,373,1527,1,
8910130,1532,1,143,2981,
891116,0,279,1,387,
89122982,16,0,279,1,
89131159,2983,16,0,279,
89141,157,2984,16,0,
8915279,1,1413,2985,16,
89160,279,1,1665,2986,
891716,0,279,1,412,
89182987,16,0,279,1,
89191377,2988,16,0,279,
89201,172,1586,1,1939,
89212989,16,0,279,1,
8922437,2990,16,0,279,
89231,188,1635,1,942,
89241607,1,1195,2991,16,
89250,279,1,1449,2992,
892616,0,279,1,1701,
89272993,16,0,279,1,
8928447,1628,1,205,2994,
892916,0,279,1,827,
89302995,16,0,279,1,
8931223,2996,16,0,279,
89321,476,1660,1,477,
89331666,1,1231,2997,16,
89340,279,1,479,1676,
89351,480,1681,1,1485,
89362998,16,0,279,1,
89371737,2999,16,0,279,
89381,242,3000,16,0,
8939279,1,478,1705,1,
89401001,1710,1,1002,1715,
89411,32,3001,19,273,
89421,32,3002,5,84,
89431,1011,1224,1,1012,
89443003,16,0,271,1,
89451013,1381,1,262,1241,
89461,1267,3004,16,0,
8947271,1,515,3005,16,
89480,271,1,1521,3006,
894916,0,271,1,525,
89501339,1,2788,3007,16,
89510,271,1,283,1295,
89521,2299,3008,16,0,
8953271,1,42,3009,16,
89540,271,1,40,1300,
89551,44,1306,1,47,
89561307,1,1303,3010,16,
89570,271,1,1555,3011,
895816,0,271,1,50,
89591324,1,48,1313,1,
896049,1319,1,51,1329,
89611,63,1345,1,305,
89621334,1,66,1351,1,
896367,1356,1,68,1361,
89641,69,1366,1,70,
89651371,1,73,3012,16,
89660,271,1,74,1376,
89671,328,1425,1,1048,
89681462,1,82,3013,16,
89690,271,1,1840,3014,
897016,0,271,1,1591,
89713015,16,0,271,1,
89721341,3016,16,0,271,
89731,1096,1694,1,93,
89741435,1,352,1467,1,
8975107,3017,16,0,271,
89761,1114,1461,1,118,
89771473,1,1123,3018,16,
89780,271,1,371,1483,
89791,1628,3019,16,0,
8980271,1,375,1494,1,
89811882,3020,16,0,271,
89821,377,1499,1,379,
89831504,1,380,1509,1,
8984883,3021,16,0,271,
89851,373,1527,1,130,
89861532,1,143,3022,16,
89870,271,1,387,3023,
898816,0,271,1,1159,
89893024,16,0,271,1,
8990157,3025,16,0,271,
89911,1413,3026,16,0,
8992271,1,1665,3027,16,
89930,271,1,412,3028,
899416,0,271,1,1377,
89953029,16,0,271,1,
8996172,1586,1,1939,3030,
899716,0,271,1,437,
89983031,16,0,271,1,
8999188,1635,1,942,1607,
90001,1195,3032,16,0,
9001271,1,1449,3033,16,
90020,271,1,1701,3034,
900316,0,271,1,447,
90041628,1,205,3035,16,
90050,271,1,827,3036,
900616,0,271,1,223,
90073037,16,0,271,1,
9008476,1660,1,477,1666,
90091,1231,3038,16,0,
9010271,1,479,1676,1,
9011480,1681,1,1485,3039,
901216,0,271,1,1737,
90133040,16,0,271,1,
9014242,3041,16,0,271,
90151,478,1705,1,1001,
90161710,1,1002,1715,1,
901733,3042,19,370,1,
901833,3043,5,84,1,
90191011,1224,1,1012,3044,
902016,0,368,1,1013,
90211381,1,262,1241,1,
90221267,3045,16,0,368,
90231,515,3046,16,0,
9024368,1,1521,3047,16,
90250,368,1,525,1339,
90261,2788,3048,16,0,
9027368,1,283,1295,1,
90282299,3049,16,0,368,
90291,42,3050,16,0,
9030368,1,40,1300,1,
903144,1306,1,47,1307,
90321,1303,3051,16,0,
9033368,1,1555,3052,16,
90340,368,1,50,1324,
90351,48,1313,1,49,
90361319,1,51,1329,1,
903763,1345,1,305,1334,
90381,66,1351,1,67,
90391356,1,68,1361,1,
904069,1366,1,70,1371,
90411,73,3053,16,0,
9042368,1,74,1376,1,
9043328,1425,1,1048,1462,
90441,82,3054,16,0,
9045368,1,1840,3055,16,
90460,368,1,1591,3056,
904716,0,368,1,1341,
90483057,16,0,368,1,
90491096,1694,1,93,1435,
90501,352,1467,1,107,
90513058,16,0,368,1,
90521114,1461,1,118,1473,
90531,1123,3059,16,0,
9054368,1,371,1483,1,
90551628,3060,16,0,368,
90561,375,1494,1,1882,
90573061,16,0,368,1,
9058377,1499,1,379,1504,
90591,380,1509,1,883,
90603062,16,0,368,1,
9061373,1527,1,130,1532,
90621,143,1537,1,387,
90633063,16,0,368,1,
90641159,3064,16,0,368,
90651,157,1560,1,1413,
90663065,16,0,368,1,
90671665,3066,16,0,368,
90681,412,3067,16,0,
9069368,1,1377,3068,16,
90700,368,1,172,1586,
90711,1939,3069,16,0,
9072368,1,437,3070,16,
90730,368,1,188,1635,
90741,942,1607,1,1195,
90753071,16,0,368,1,
90761449,3072,16,0,368,
90771,1701,3073,16,0,
9078368,1,447,1628,1,
9079205,3074,16,0,368,
90801,827,3075,16,0,
9081368,1,223,3076,16,
90820,368,1,476,1660,
90831,477,1666,1,1231,
90843077,16,0,368,1,
9085479,1676,1,480,1681,
90861,1485,3078,16,0,
9087368,1,1737,3079,16,
90880,368,1,242,1700,
90891,478,1705,1,1001,
90901710,1,1002,1715,1,
909134,3080,19,358,1,
909234,3081,5,84,1,
90931011,1224,1,1012,3082,
909416,0,356,1,1013,
90951381,1,262,1241,1,
90961267,3083,16,0,356,
90971,515,3084,16,0,
9098356,1,1521,3085,16,
90990,356,1,525,1339,
91001,2788,3086,16,0,
9101356,1,283,1295,1,
91022299,3087,16,0,356,
91031,42,3088,16,0,
9104356,1,40,1300,1,
910544,1306,1,47,1307,
91061,1303,3089,16,0,
9107356,1,1555,3090,16,
91080,356,1,50,1324,
91091,48,1313,1,49,
91101319,1,51,1329,1,
911163,1345,1,305,1334,
91121,66,1351,1,67,
91131356,1,68,1361,1,
911469,1366,1,70,1371,
91151,73,3091,16,0,
9116356,1,74,1376,1,
9117328,1425,1,1048,1462,
91181,82,3092,16,0,
9119356,1,1840,3093,16,
91200,356,1,1591,3094,
912116,0,356,1,1341,
91223095,16,0,356,1,
91231096,1694,1,93,1435,
91241,352,1467,1,107,
91253096,16,0,356,1,
91261114,1461,1,118,1473,
91271,1123,3097,16,0,
9128356,1,371,1483,1,
91291628,3098,16,0,356,
91301,375,1494,1,1882,
91313099,16,0,356,1,
9132377,1499,1,379,1504,
91331,380,1509,1,883,
91343100,16,0,356,1,
9135373,1527,1,130,1532,
91361,143,1537,1,387,
91373101,16,0,356,1,
91381159,3102,16,0,356,
91391,157,1560,1,1413,
91403103,16,0,356,1,
91411665,3104,16,0,356,
91421,412,3105,16,0,
9143356,1,1377,3106,16,
91440,356,1,172,1586,
91451,1939,3107,16,0,
9146356,1,437,3108,16,
91470,356,1,188,1635,
91481,942,1607,1,1195,
91493109,16,0,356,1,
91501449,3110,16,0,356,
91511,1701,3111,16,0,
9152356,1,447,1628,1,
9153205,1640,1,827,3112,
915416,0,356,1,223,
91551650,1,476,1660,1,
9156477,1666,1,1231,3113,
915716,0,356,1,479,
91581676,1,480,1681,1,
91591485,3114,16,0,356,
91601,1737,3115,16,0,
9161356,1,242,1700,1,
9162478,1705,1,1001,1710,
91631,1002,1715,1,35,
91643116,19,346,1,35,
91653117,5,84,1,1011,
91661224,1,1012,3118,16,
91670,344,1,1013,1381,
91681,262,1241,1,1267,
91693119,16,0,344,1,
9170515,3120,16,0,344,
91711,1521,3121,16,0,
9172344,1,525,1339,1,
91732788,3122,16,0,344,
91741,283,1295,1,2299,
91753123,16,0,344,1,
917642,3124,16,0,344,
91771,40,1300,1,44,
91781306,1,47,1307,1,
91791303,3125,16,0,344,
91801,1555,3126,16,0,
9181344,1,50,1324,1,
918248,1313,1,49,1319,
91831,51,1329,1,63,
91841345,1,305,1334,1,
918566,1351,1,67,1356,
91861,68,1361,1,69,
91871366,1,70,1371,1,
918873,3127,16,0,344,
91891,74,1376,1,328,
91901425,1,1048,1462,1,
919182,3128,16,0,344,
91921,1840,3129,16,0,
9193344,1,1591,3130,16,
91940,344,1,1341,3131,
919516,0,344,1,1096,
91961694,1,93,1435,1,
9197352,1467,1,107,3132,
919816,0,344,1,1114,
91991461,1,118,1473,1,
92001123,3133,16,0,344,
92011,371,1483,1,1628,
92023134,16,0,344,1,
9203375,1494,1,1882,3135,
920416,0,344,1,377,
92051499,1,379,1504,1,
9206380,1509,1,883,3136,
920716,0,344,1,373,
92081527,1,130,1532,1,
9209143,1537,1,387,3137,
921016,0,344,1,1159,
92113138,16,0,344,1,
9212157,1560,1,1413,3139,
921316,0,344,1,1665,
92143140,16,0,344,1,
9215412,3141,16,0,344,
92161,1377,3142,16,0,
9217344,1,172,1586,1,
92181939,3143,16,0,344,
92191,437,3144,16,0,
9220344,1,188,1635,1,
9221942,1607,1,1195,3145,
922216,0,344,1,1449,
92233146,16,0,344,1,
92241701,3147,16,0,344,
92251,447,1628,1,205,
92261640,1,827,3148,16,
92270,344,1,223,3149,
922816,0,344,1,476,
92291660,1,477,1666,1,
92301231,3150,16,0,344,
92311,479,1676,1,480,
92321681,1,1485,3151,16,
92330,344,1,1737,3152,
923416,0,344,1,242,
92351700,1,478,1705,1,
92361001,1710,1,1002,1715,
92371,36,3153,19,242,
92381,36,3154,5,94,
92391,256,3155,16,0,
9240240,1,1261,3156,16,
92410,240,1,509,3157,
924216,0,240,1,1515,
92433158,16,0,240,1,
92442021,840,1,1775,3159,
924516,0,240,1,2029,
9246847,1,2030,853,1,
92472031,858,1,2032,863,
92481,2033,868,1,277,
92493160,16,0,240,1,
92502035,874,1,2037,879,
92511,2039,884,1,32,
92523161,16,0,240,1,
92532041,890,1,2293,3162,
925416,0,240,1,2043,
9255896,1,2045,901,1,
925641,3163,16,0,240,
92571,1297,3164,16,0,
9258240,1,43,3165,16,
92590,240,1,1803,909,
92601,1804,3166,16,0,
9261240,1,299,3167,16,
92620,240,1,52,3168,
926316,0,240,1,2318,
92643169,16,0,240,1,
92652075,3170,16,0,240,
92661,1574,921,1,71,
92673171,16,0,240,1,
926876,3172,16,0,240,
92691,1834,3173,16,0,
9270240,1,2337,3174,16,
92710,240,1,79,3175,
927216,0,240,1,1335,
92733176,16,0,240,1,
9274322,3177,16,0,240,
92751,85,3178,16,0,
9276240,1,89,3179,16,
92770,240,1,346,3180,
927816,0,240,1,2105,
9279936,1,2106,3181,16,
92800,240,1,97,3182,
928116,0,240,1,1860,
9282943,1,2364,949,1,
9283102,3183,16,0,240,
92841,2782,3184,16,0,
9285240,1,112,3185,16,
92860,240,1,1117,3186,
928716,0,240,1,1873,
9288958,1,1876,3187,16,
92890,240,1,124,3188,
929016,0,240,1,2136,
9291965,1,381,3189,16,
92920,240,1,525,3190,
929316,0,240,1,137,
92943191,16,0,240,1,
92951901,3192,16,0,240,
92961,1153,3193,16,0,
9297240,1,151,3194,16,
92980,240,1,1407,3195,
929916,0,240,1,1659,
93003196,16,0,240,1,
93012413,3197,16,0,240,
93021,406,3198,16,0,
9303240,1,1371,3199,16,
93040,240,1,166,3200,
930516,0,240,1,1622,
93063201,16,0,240,1,
93071931,983,1,1933,3202,
930816,0,240,1,431,
93093203,16,0,240,1,
93101585,3204,16,0,240,
93111,182,3205,16,0,
9312240,1,1189,3206,16,
93130,240,1,1443,3207,
931416,0,240,1,1695,
93153208,16,0,240,1,
93162198,3209,16,0,240,
93171,447,3210,16,0,
9318240,1,2458,998,1,
93192459,1004,1,1958,3211,
932016,0,240,1,2462,
93211011,1,1657,1016,1,
93222464,1021,1,199,3212,
932316,0,240,1,459,
93243213,16,0,240,1,
9325462,3214,16,0,240,
93261,217,3215,16,0,
9327240,1,2227,1030,1,
93281225,3216,16,0,240,
93291,1479,3217,16,0,
9330240,1,1731,3218,16,
93310,240,1,1989,1038,
93321,1990,3219,16,0,
9333240,1,236,3220,16,
93340,240,1,1756,3221,
933516,0,240,1,37,
93363222,19,263,1,37,
93373223,5,94,1,256,
93383224,16,0,261,1,
93391261,3225,16,0,261,
93401,509,3226,16,0,
9341261,1,1515,3227,16,
93420,261,1,2021,840,
93431,1775,3228,16,0,
9344261,1,2029,847,1,
93452030,853,1,2031,858,
93461,2032,863,1,2033,
9347868,1,277,3229,16,
93480,261,1,2035,874,
93491,2037,879,1,2039,
9350884,1,32,3230,16,
93510,261,1,2041,890,
93521,2293,3231,16,0,
9353261,1,2043,896,1,
93542045,901,1,41,3232,
935516,0,261,1,1297,
93563233,16,0,261,1,
935743,3234,16,0,261,
93581,1803,909,1,1804,
93593235,16,0,261,1,
9360299,3236,16,0,261,
93611,52,3237,16,0,
9362261,1,2318,3238,16,
93630,261,1,2075,3239,
936416,0,261,1,1574,
9365921,1,71,3240,16,
93660,261,1,76,3241,
936716,0,261,1,1834,
93683242,16,0,261,1,
93692337,3243,16,0,261,
93701,79,3244,16,0,
9371261,1,1335,3245,16,
93720,261,1,322,3246,
937316,0,261,1,85,
93743247,16,0,261,1,
937589,3248,16,0,261,
93761,346,3249,16,0,
9377261,1,2105,936,1,
93782106,3250,16,0,261,
93791,97,3251,16,0,
9380261,1,1860,943,1,
93812364,949,1,102,3252,
938216,0,261,1,2782,
93833253,16,0,261,1,
9384112,3254,16,0,261,
93851,1117,3255,16,0,
9386261,1,1873,958,1,
93871876,3256,16,0,261,
93881,124,3257,16,0,
9389261,1,2136,965,1,
9390381,3258,16,0,261,
93911,525,3259,16,0,
9392261,1,137,3260,16,
93930,261,1,1901,3261,
939416,0,261,1,1153,
93953262,16,0,261,1,
9396151,3263,16,0,261,
93971,1407,3264,16,0,
9398261,1,1659,3265,16,
93990,261,1,2413,3266,
940016,0,261,1,406,
94013267,16,0,261,1,
94021371,3268,16,0,261,
94031,166,3269,16,0,
9404261,1,1622,3270,16,
94050,261,1,1931,983,
94061,1933,3271,16,0,
9407261,1,431,3272,16,
94080,261,1,1585,3273,
940916,0,261,1,182,
94103274,16,0,261,1,
94111189,3275,16,0,261,
94121,1443,3276,16,0,
9413261,1,1695,3277,16,
94140,261,1,2198,3278,
941516,0,261,1,447,
94163279,16,0,261,1,
94172458,998,1,2459,1004,
94181,1958,3280,16,0,
9419261,1,2462,1011,1,
94201657,1016,1,2464,1021,
94211,199,3281,16,0,
9422261,1,459,3282,16,
94230,261,1,462,3283,
942416,0,261,1,217,
94253284,16,0,261,1,
94262227,1030,1,1225,3285,
942716,0,261,1,1479,
94283286,16,0,261,1,
94291731,3287,16,0,261,
94301,1989,1038,1,1990,
94313288,16,0,261,1,
9432236,3289,16,0,261,
94331,1756,3290,16,0,
9434261,1,38,3291,19,
9435260,1,38,3292,5,
943684,1,1011,1224,1,
94371012,3293,16,0,258,
94381,1013,1381,1,262,
94391241,1,1267,3294,16,
94400,258,1,515,3295,
944116,0,258,1,1521,
94423296,16,0,258,1,
9443525,1339,1,2788,3297,
944416,0,258,1,283,
94451295,1,2299,3298,16,
94460,258,1,42,3299,
944716,0,258,1,40,
94481300,1,44,1306,1,
944947,1307,1,1303,3300,
945016,0,258,1,1555,
94513301,16,0,258,1,
945250,1324,1,48,1313,
94531,49,1319,1,51,
94541329,1,63,1345,1,
9455305,1334,1,66,1351,
94561,67,1356,1,68,
94571361,1,69,1366,1,
945870,1371,1,73,3302,
945916,0,258,1,74,
94601376,1,328,1425,1,
94611048,1462,1,82,3303,
946216,0,258,1,1840,
94633304,16,0,258,1,
94641591,3305,16,0,258,
94651,1341,3306,16,0,
9466258,1,1096,1694,1,
946793,1435,1,352,1467,
94681,107,3307,16,0,
9469258,1,1114,1461,1,
9470118,1473,1,1123,3308,
947116,0,258,1,371,
94721483,1,1628,3309,16,
94730,258,1,375,1494,
94741,1882,3310,16,0,
9475258,1,377,1499,1,
9476379,1504,1,380,1509,
94771,883,1515,1,373,
94781527,1,130,1532,1,
9479143,1537,1,387,3311,
948016,0,258,1,1159,
94813312,16,0,258,1,
9482157,1560,1,1413,3313,
948316,0,258,1,1665,
94843314,16,0,258,1,
9485412,3315,16,0,258,
94861,1377,3316,16,0,
9487258,1,172,1586,1,
94881939,3317,16,0,258,
94891,437,3318,16,0,
9490258,1,188,1635,1,
9491942,1607,1,1195,3319,
949216,0,258,1,1449,
94933320,16,0,258,1,
94941701,3321,16,0,258,
94951,447,1628,1,205,
94961640,1,827,1448,1,
9497223,1650,1,476,1660,
94981,477,1666,1,1231,
94993322,16,0,258,1,
9500479,1676,1,480,1681,
95011,1485,3323,16,0,
9502258,1,1737,3324,16,
95030,258,1,242,1700,
95041,478,1705,1,1001,
95051710,1,1002,1715,1,
950639,3325,19,248,1,
950739,3326,5,84,1,
95081011,1224,1,1012,3327,
950916,0,246,1,1013,
95101381,1,262,1241,1,
95111267,3328,16,0,246,
95121,515,3329,16,0,
9513246,1,1521,3330,16,
95140,246,1,525,1339,
95151,2788,3331,16,0,
9516246,1,283,1295,1,
95172299,3332,16,0,246,
95181,42,3333,16,0,
9519246,1,40,1300,1,
952044,1306,1,47,1307,
95211,1303,3334,16,0,
9522246,1,1555,3335,16,
95230,246,1,50,1324,
95241,48,1313,1,49,
95251319,1,51,1329,1,
952663,1345,1,305,1334,
95271,66,1351,1,67,
95281356,1,68,1361,1,
952969,1366,1,70,1371,
95301,73,3336,16,0,
9531246,1,74,1376,1,
9532328,1425,1,1048,1462,
95331,82,3337,16,0,
9534246,1,1840,3338,16,
95350,246,1,1591,3339,
953616,0,246,1,1341,
95373340,16,0,246,1,
95381096,1694,1,93,1435,
95391,352,1467,1,107,
95403341,16,0,246,1,
95411114,1461,1,118,1473,
95421,1123,3342,16,0,
9543246,1,371,1483,1,
95441628,3343,16,0,246,
95451,375,1494,1,1882,
95463344,16,0,246,1,
9547377,1499,1,379,1504,
95481,380,1509,1,883,
95491515,1,373,1527,1,
9550130,1532,1,143,1537,
95511,387,3345,16,0,
9552246,1,1159,3346,16,
95530,246,1,157,1560,
95541,1413,3347,16,0,
9555246,1,1665,3348,16,
95560,246,1,412,3349,
955716,0,246,1,1377,
95583350,16,0,246,1,
9559172,1586,1,1939,3351,
956016,0,246,1,437,
95613352,16,0,246,1,
9562188,1635,1,942,1607,
95631,1195,3353,16,0,
9564246,1,1449,3354,16,
95650,246,1,1701,3355,
956616,0,246,1,447,
95671628,1,205,1640,1,
9568827,1448,1,223,1650,
95691,476,1660,1,477,
95701666,1,1231,3356,16,
95710,246,1,479,1676,
95721,480,1681,1,1485,
95733357,16,0,246,1,
95741737,3358,16,0,246,
95751,242,1700,1,478,
95761705,1,1001,1710,1,
95771002,1715,1,40,3359,
957819,236,1,40,3360,
95795,84,1,1011,1224,
95801,1012,3361,16,0,
9581234,1,1013,1381,1,
9582262,1241,1,1267,3362,
958316,0,234,1,515,
95843363,16,0,234,1,
95851521,3364,16,0,234,
95861,525,1339,1,2788,
95873365,16,0,234,1,
9588283,1295,1,2299,3366,
958916,0,234,1,42,
95903367,16,0,234,1,
959140,1300,1,44,1306,
95921,47,1307,1,1303,
95933368,16,0,234,1,
95941555,3369,16,0,234,
95951,50,1324,1,48,
95961313,1,49,1319,1,
959751,1329,1,63,1345,
95981,305,1334,1,66,
95991351,1,67,1356,1,
960068,1361,1,69,1366,
96011,70,1371,1,73,
96023370,16,0,234,1,
960374,1376,1,328,1425,
96041,1048,1462,1,82,
96053371,16,0,234,1,
96061840,3372,16,0,234,
96071,1591,3373,16,0,
9608234,1,1341,3374,16,
96090,234,1,1096,1694,
96101,93,1435,1,352,
96111467,1,107,3375,16,
96120,234,1,1114,1461,
96131,118,3376,16,0,
9614234,1,1123,3377,16,
96150,234,1,371,1483,
96161,1628,3378,16,0,
9617234,1,375,1494,1,
96181882,3379,16,0,234,
96191,377,1499,1,379,
96201504,1,380,1509,1,
9621883,3380,16,0,234,
96221,373,1527,1,130,
96233381,16,0,234,1,
9624143,3382,16,0,234,
96251,387,3383,16,0,
9626234,1,1159,3384,16,
96270,234,1,157,3385,
962816,0,234,1,1413,
96293386,16,0,234,1,
96301665,3387,16,0,234,
96311,412,3388,16,0,
9632234,1,1377,3389,16,
96330,234,1,172,3390,
963416,0,234,1,1939,
96353391,16,0,234,1,
9636437,3392,16,0,234,
96371,188,3393,16,0,
9638234,1,942,1607,1,
96391195,3394,16,0,234,
96401,1449,3395,16,0,
9641234,1,1701,3396,16,
96420,234,1,447,1628,
96431,205,3397,16,0,
9644234,1,827,3398,16,
96450,234,1,223,3399,
964616,0,234,1,476,
96471660,1,477,1666,1,
96481231,3400,16,0,234,
96491,479,1676,1,480,
96501681,1,1485,3401,16,
96510,234,1,1737,3402,
965216,0,234,1,242,
96533403,16,0,234,1,
9654478,1705,1,1001,1710,
96551,1002,1715,1,41,
96563404,19,191,1,41,
96573405,5,84,1,1011,
96581224,1,1012,3406,16,
96590,189,1,1013,1381,
96601,262,1241,1,1267,
96613407,16,0,189,1,
9662515,3408,16,0,189,
96631,1521,3409,16,0,
9664189,1,525,1339,1,
96652788,3410,16,0,189,
96661,283,1295,1,2299,
96673411,16,0,189,1,
966842,3412,16,0,189,
96691,40,1300,1,44,
96701306,1,47,1307,1,
96711303,3413,16,0,189,
96721,1555,3414,16,0,
9673189,1,50,1324,1,
967448,1313,1,49,1319,
96751,51,1329,1,63,
96761345,1,305,1334,1,
967766,1351,1,67,1356,
96781,68,1361,1,69,
96791366,1,70,1371,1,
968073,3415,16,0,189,
96811,74,1376,1,328,
96821425,1,1048,1462,1,
968382,3416,16,0,189,
96841,1840,3417,16,0,
9685189,1,1591,3418,16,
96860,189,1,1341,3419,
968716,0,189,1,1096,
96881694,1,93,1435,1,
9689352,1467,1,107,3420,
969016,0,189,1,1114,
96911461,1,118,3421,16,
96920,189,1,1123,3422,
969316,0,189,1,371,
96941483,1,1628,3423,16,
96950,189,1,375,1494,
96961,1882,3424,16,0,
9697189,1,377,1499,1,
9698379,1504,1,380,1509,
96991,883,3425,16,0,
9700189,1,373,1527,1,
9701130,3426,16,0,189,
97021,143,3427,16,0,
9703189,1,387,3428,16,
97040,189,1,1159,3429,
970516,0,189,1,157,
97063430,16,0,189,1,
97071413,3431,16,0,189,
97081,1665,3432,16,0,
9709189,1,412,3433,16,
97100,189,1,1377,3434,
971116,0,189,1,172,
97123435,16,0,189,1,
97131939,3436,16,0,189,
97141,437,3437,16,0,
9715189,1,188,3438,16,
97160,189,1,942,1607,
97171,1195,3439,16,0,
9718189,1,1449,3440,16,
97190,189,1,1701,3441,
972016,0,189,1,447,
97211628,1,205,3442,16,
97220,189,1,827,3443,
972316,0,189,1,223,
97243444,16,0,189,1,
9725476,1660,1,477,1666,
97261,1231,3445,16,0,
9727189,1,479,1676,1,
9728480,1681,1,1485,3446,
972916,0,189,1,1737,
97303447,16,0,189,1,
9731242,3448,16,0,189,
97321,478,1705,1,1001,
97331710,1,1002,1715,1,
973442,3449,19,430,1,
973542,3450,5,38,1,
97361901,3451,16,0,428,
97371,2075,3452,16,0,
9738428,1,1860,943,1,
97391803,909,1,1804,3453,
974016,0,428,1,2413,
97413454,16,0,428,1,
97422198,3455,16,0,428,
97431,1873,958,1,1657,
97441016,1,1989,1038,1,
97451990,3456,16,0,428,
97461,1775,3457,16,0,
9747428,1,32,3458,16,
97480,428,1,2105,936,
97491,2106,3459,16,0,
9750428,1,2364,949,1,
97512227,1030,1,2337,3460,
975216,0,428,1,2021,
9753840,1,2458,998,1,
97542459,1004,1,2462,1011,
97551,2136,965,1,2464,
97561021,1,2029,847,1,
97572030,853,1,2031,858,
97581,2032,863,1,2033,
9759868,1,2035,874,1,
97602037,879,1,2039,884,
97611,1931,983,1,2041,
9762890,1,2043,896,1,
97632045,901,1,1574,921,
97641,1958,3461,16,0,
9765428,1,43,3462,19,
9766518,1,43,3463,5,
976725,1,2035,874,1,
97682037,879,1,2039,884,
97691,2041,890,1,2227,
97701030,1,2043,896,1,
97711657,1016,1,1860,943,
97721,2136,965,1,2021,
9773840,1,2459,1004,1,
97741574,921,1,2105,3464,
977516,0,683,1,1931,
9776983,1,1873,958,1,
97772031,858,1,1803,909,
97781,1989,3465,16,0,
9779516,1,2464,1021,1,
97802029,847,1,2030,853,
97811,2364,949,1,2032,
9782863,1,2033,868,1,
97832045,901,1,44,3466,
978419,289,1,44,3467,
97855,38,1,1901,3468,
978616,0,287,1,2075,
97873469,16,0,287,1,
97881860,943,1,1803,909,
97891,1804,3470,16,0,
9790287,1,2413,3471,16,
97910,287,1,2198,3472,
979216,0,287,1,1873,
9793958,1,1657,1016,1,
97941989,1038,1,1990,3473,
979516,0,287,1,1775,
97963474,16,0,287,1,
979732,3475,16,0,287,
97981,2105,936,1,2106,
97993476,16,0,287,1,
98002364,949,1,2227,1030,
98011,2337,3477,16,0,
9802287,1,2021,840,1,
98032458,998,1,2459,1004,
98041,2462,1011,1,2136,
9805965,1,2464,1021,1,
98062029,847,1,2030,853,
98071,2031,858,1,2032,
9808863,1,2033,868,1,
98092035,874,1,2037,879,
98101,2039,884,1,1931,
9811983,1,2041,890,1,
98122043,896,1,2045,901,
98131,1574,921,1,1958,
98143478,16,0,287,1,
981545,3479,19,320,1,
981645,3480,5,39,1,
98171901,3481,16,0,350,
98181,2075,3482,16,0,
9819350,1,1860,943,1,
98201803,909,1,1804,3483,
982116,0,350,1,2413,
98223484,16,0,350,1,
98232198,3485,16,0,350,
98241,1873,958,1,1657,
98251016,1,1989,1038,1,
98261990,3486,16,0,350,
98271,1775,3487,16,0,
9828350,1,32,3488,16,
98290,350,1,2105,936,
98301,2106,3489,16,0,
9831350,1,2364,949,1,
98322227,1030,1,2337,3490,
983316,0,350,1,2021,
9834840,1,2458,998,1,
98352459,1004,1,2462,1011,
98361,2136,965,1,2464,
98371021,1,2029,847,1,
98382030,853,1,2031,858,
98391,2032,863,1,2033,
9840868,1,2035,874,1,
98412037,879,1,2039,884,
98421,1931,983,1,2041,
9843890,1,2043,896,1,
98442045,901,1,1832,3491,
984516,0,318,1,1574,
9846921,1,1958,3492,16,
98470,350,1,46,3493,
984819,789,1,46,3494,
98495,38,1,1901,3495,
985016,0,787,1,2075,
98513496,16,0,787,1,
98521860,943,1,1803,909,
98531,1804,3497,16,0,
9854787,1,2413,3498,16,
98550,787,1,2198,3499,
985616,0,787,1,1873,
9857958,1,1657,1016,1,
98581989,1038,1,1990,3500,
985916,0,787,1,1775,
98603501,16,0,787,1,
986132,3502,16,0,787,
98621,2105,936,1,2106,
98633503,16,0,787,1,
98642364,949,1,2227,1030,
98651,2337,3504,16,0,
9866787,1,2021,840,1,
98672458,998,1,2459,1004,
98681,2462,1011,1,2136,
9869965,1,2464,1021,1,
98702029,847,1,2030,853,
98711,2031,858,1,2032,
9872863,1,2033,868,1,
98732035,874,1,2037,879,
98741,2039,884,1,1931,
9875983,1,2041,890,1,
98762043,896,1,2045,901,
98771,1574,921,1,1958,
98783505,16,0,787,1,
987947,3506,19,660,1,
988047,3507,5,19,1,
98810,3508,16,0,760,
98821,2760,3509,16,0,
9883760,1,2779,3510,17,
98843511,15,3512,4,50,
845837,0,71,0,108, 988537,0,71,0,108,
84590,111,0,98,0, 98860,111,0,98,0,
846097,0,108,0,70, 988797,0,108,0,70,
@@ -8465,8 +9892,8 @@ public yyLSLSyntax
84650,105,0,110,0, 98920,105,0,110,0,
8466105,0,116,0,105, 9893105,0,116,0,105,
84670,111,0,110,0, 98940,111,0,110,0,
84681,-1,1,5,3203, 98951,-1,1,5,3513,
846920,3204,4,52,71, 989620,3514,4,52,71,
84700,108,0,111,0, 98970,108,0,111,0,
847198,0,97,0,108, 989898,0,97,0,108,
84720,70,0,117,0, 98990,70,0,117,0,
@@ -8476,27 +9903,47 @@ public yyLSLSyntax
84760,102,0,105,0, 99030,102,0,105,0,
8477110,0,105,0,116, 9904110,0,105,0,116,
84780,105,0,111,0, 99050,105,0,111,0,
8479110,0,95,0,50, 9906110,0,95,0,49,
84800,1,151,1,3, 99070,1,174,1,3,
84811,7,1,6,3205, 99081,6,1,5,3515,
848222,1,10,1,2640, 990922,1,9,1,2764,
8483685,1,2713,3206,17, 9910801,1,2818,3516,17,
84843207,15,3185,1,-1, 99113517,15,3518,4,52,
84851,5,3208,20,3209, 991237,0,71,0,108,
84864,38,71,0,108,
84870,111,0,98,0, 99130,111,0,98,0,
848897,0,108,0,68, 991497,0,108,0,86,
84890,101,0,102,0, 99150,97,0,114,0,
8490105,0,110,0,105, 9916105,0,97,0,98,
84910,116,0,105,0, 99170,108,0,101,0,
8492111,0,110,0,115, 991868,0,101,0,99,
84930,95,0,52,0, 99190,108,0,97,0,
84941,147,1,3,1, 9920114,0,97,0,116,
84953,1,2,3210,22, 99210,105,0,111,0,
84961,6,1,2655,3211, 9922110,0,1,-1,1,
849717,3212,15,3202,1, 99235,3519,20,3520,4,
8498-1,1,5,3213,20, 992454,71,0,108,0,
84993214,4,52,71,0, 9925111,0,98,0,97,
99260,108,0,86,0,
992797,0,114,0,105,
99280,97,0,98,0,
9929108,0,101,0,68,
99300,101,0,99,0,
9931108,0,97,0,114,
99320,97,0,116,0,
9933105,0,111,0,110,
99340,95,0,49,0,
99351,172,1,3,1,
99363,1,2,3521,22,
99371,7,1,2819,3522,
993816,0,760,1,2751,
9939807,1,2022,3523,16,
99400,658,1,2459,1004,
99411,2830,3524,16,0,
9942760,1,2647,824,1,
99432464,1021,1,2466,3525,
994417,3526,15,3512,1,
9945-1,1,5,3527,20,
99463528,4,52,71,0,
8500108,0,111,0,98, 9947108,0,111,0,98,
85010,97,0,108,0, 99480,97,0,108,0,
850270,0,117,0,110, 994970,0,117,0,110,
@@ -8506,41 +9953,73 @@ public yyLSLSyntax
8506102,0,105,0,110, 9953102,0,105,0,110,
85070,105,0,116,0, 99540,105,0,116,0,
8508105,0,111,0,110, 9955105,0,111,0,110,
85090,95,0,49,0, 99560,95,0,50,0,
85101,150,1,3,1, 99571,175,1,3,1,
85116,1,5,3215,22, 99587,1,6,3529,22,
85121,9,1,2694,3216, 99591,10,1,2837,3530,
851317,3217,15,3218,4, 996017,3531,15,3532,4,
851452,37,0,71,0, 996136,37,0,71,0,
8515108,0,111,0,98, 9962108,0,111,0,98,
85160,97,0,108,0, 99630,97,0,108,0,
851786,0,97,0,114, 996468,0,101,0,102,
85180,105,0,97,0, 99650,105,0,110,0,
851998,0,108,0,101, 9966105,0,116,0,105,
85200,68,0,101,0, 99670,111,0,110,0,
852199,0,108,0,97, 9968115,0,1,-1,1,
85220,114,0,97,0, 99695,3533,20,3534,4,
997038,71,0,108,0,
9971111,0,98,0,97,
99720,108,0,68,0,
9973101,0,102,0,105,
99740,110,0,105,0,
8523116,0,105,0,111, 9975116,0,105,0,111,
85240,110,0,1,-1, 99760,110,0,115,0,
85251,5,3219,20,3220, 997795,0,52,0,1,
85264,54,71,0,108, 9978171,1,3,1,3,
99791,2,3535,22,1,
99806,1,2838,3536,17,
99813537,15,3532,1,-1,
99821,5,3538,20,3539,
99834,38,71,0,108,
85270,111,0,98,0, 99840,111,0,98,0,
852897,0,108,0,86, 998597,0,108,0,68,
85290,97,0,114,0, 99860,101,0,102,0,
8530105,0,97,0,98, 9987105,0,110,0,105,
85310,108,0,101,0, 99880,116,0,105,0,
853268,0,101,0,99, 9989111,0,110,0,115,
85330,108,0,97,0, 99900,95,0,50,0,
8534114,0,97,0,116, 99911,169,1,3,1,
85350,105,0,111,0, 99923,1,2,3540,22,
8536110,0,95,0,49, 99931,4,1,2839,3541,
85370,1,148,1,3, 999417,3542,15,3532,1,
85381,3,1,2,3221, 9995-1,1,5,3543,20,
853922,1,7,1,2695, 99963544,4,38,71,0,
85403222,16,0,464,1, 9997108,0,111,0,98,
85412683,3223,17,3224,15, 99980,97,0,108,0,
85423218,1,-1,1,5, 999968,0,101,0,102,
85433225,20,3226,4,54, 100000,105,0,110,0,
10001105,0,116,0,105,
100020,111,0,110,0,
10003115,0,95,0,51,
100040,1,170,1,3,
100051,2,1,1,3545,
1000622,1,5,1,2840,
100073546,17,3547,15,3532,
100081,-1,1,5,3548,
1000920,3549,4,38,71,
100100,108,0,111,0,
1001198,0,97,0,108,
100120,68,0,101,0,
10013102,0,105,0,110,
100140,105,0,116,0,
10015105,0,111,0,110,
100160,115,0,95,0,
1001749,0,1,168,1,
100183,1,2,1,1,
100193550,22,1,3,1,
100202807,3551,17,3552,15,
100213518,1,-1,1,5,
100223553,20,3554,4,54,
854471,0,108,0,111, 1002371,0,108,0,111,
85450,98,0,97,0, 100240,98,0,97,0,
8546108,0,86,0,97, 10025108,0,86,0,97,
@@ -8552,2183 +10031,2826 @@ public yyLSLSyntax
855297,0,116,0,105, 1003197,0,116,0,105,
85530,111,0,110,0, 100320,111,0,110,0,
855495,0,50,0,1, 1003395,0,50,0,1,
8555149,1,3,1,5, 10034173,1,3,1,5,
85561,4,3227,22,1, 100351,4,3555,22,1,
85578,1,48,3228,19, 100368,1,2763,813,1,
8558339,1,48,3229,5, 1003748,3556,19,375,1,
855954,1,0,3230,16, 1003848,3557,5,54,1,
85600,337,1,2075,3231, 100390,3558,16,0,373,
856116,0,495,1,1860, 100401,2837,3530,1,2838,
8562821,1,1803,787,1, 100413536,1,2839,3541,1,
85631804,3232,16,0,495, 100422840,3546,1,1860,943,
85641,2413,3233,16,0, 100431,1958,3559,16,0,
8565495,1,2634,691,1, 10044573,1,2760,3560,16,
85661873,835,1,1657,894, 100450,373,1,2413,3561,
85671,2639,707,1,2640, 1004616,0,573,1,2198,
8568685,1,1989,916,1, 100473562,16,0,573,1,
85691990,3234,16,0,495, 100481873,958,1,1657,1016,
85701,2459,882,1,1775, 100491,2030,853,1,2751,
85713235,16,0,495,1, 10050807,1,1989,1038,1,
857232,3236,16,0,495, 100511990,3563,16,0,573,
85731,2105,814,1,2106, 100521,2458,998,1,2459,
85743237,16,0,495,1, 100531004,1,1775,3564,16,
85752466,3200,1,2655,3211, 100540,573,1,32,3565,
85761,2683,3223,1,2227, 1005516,0,573,1,2105,
8577908,1,2337,3238,16, 10056936,1,2106,3566,16,
85780,495,1,2558,697, 100570,573,1,2763,813,
85791,2694,3216,1,2695, 100581,2764,801,1,2227,
85803239,16,0,337,1, 100591030,1,2337,3567,16,
85812021,718,1,2458,876, 100600,573,1,2075,3568,
85821,1901,3240,16,0, 1006116,0,573,1,2779,
8583495,1,2462,889,1, 100623510,1,1803,909,1,
85842136,842,1,2464,899, 100631804,3569,16,0,573,
85851,2029,725,1,2030, 100641,1901,3570,16,0,
8586731,1,2031,736,1, 10065573,1,2462,1011,1,
85872032,741,1,2033,746, 100662136,965,1,2464,1021,
85881,2035,752,1,2364, 100671,2029,847,1,2466,
8589827,1,2715,3195,1, 100683525,1,2031,858,1,
85902039,762,1,1931,861, 100692032,863,1,2033,868,
85911,2041,768,1,2043, 100701,2035,874,1,2364,
8592774,1,2045,779,1, 10071949,1,2039,884,1,
85932198,3241,16,0,495, 100721931,983,1,2041,890,
85941,2706,3242,16,0, 100731,2021,840,1,2043,
8595337,1,2037,757,1, 10074896,1,2807,3551,1,
85962713,3206,1,2714,3183, 100752045,901,1,2647,824,
85971,1574,799,1,2716, 100761,2818,3516,1,2819,
85983189,1,2636,3243,16, 100773571,16,0,373,1,
85990,337,1,1958,3244, 100782037,879,1,1574,921,
860016,0,495,1,49, 100791,2830,3572,16,0,
86013245,19,500,1,49, 10080373,1,49,3573,19,
86023246,5,38,1,1901, 10081578,1,49,3574,5,
86033247,16,0,498,1, 1008238,1,1901,3575,16,
86042075,3248,16,0,498, 100830,576,1,2075,3576,
86051,1860,821,1,1803, 1008416,0,576,1,1860,
8606787,1,1804,3249,16, 10085943,1,1803,909,1,
86070,498,1,2413,3250, 100861804,3577,16,0,576,
860816,0,498,1,2198, 100871,2413,3578,16,0,
86093251,16,0,498,1, 10088576,1,2198,3579,16,
86101873,835,1,1657,894, 100890,576,1,1873,958,
86111,1989,916,1,1990, 100901,1657,1016,1,1989,
86123252,16,0,498,1, 100911038,1,1990,3580,16,
86131775,3253,16,0,498, 100920,576,1,1775,3581,
86141,32,3254,16,0, 1009316,0,576,1,32,
8615498,1,2105,814,1, 100943582,16,0,576,1,
86162106,3255,16,0,498, 100952105,936,1,2106,3583,
86171,2364,827,1,2227, 1009616,0,576,1,2364,
8618908,1,2337,3256,16, 10097949,1,2227,1030,1,
86190,498,1,2021,718, 100982337,3584,16,0,576,
86201,2458,876,1,2459, 100991,2021,840,1,2458,
8621882,1,2462,889,1, 10100998,1,2459,1004,1,
86222136,842,1,2464,899, 101012462,1011,1,2136,965,
86231,2029,725,1,2030, 101021,2464,1021,1,2029,
8624731,1,2031,736,1, 10103847,1,2030,853,1,
86252032,741,1,2033,746, 101042031,858,1,2032,863,
86261,2035,752,1,2037, 101051,2033,868,1,2035,
8627757,1,2039,762,1, 10106874,1,2037,879,1,
86281931,861,1,2041,768, 101072039,884,1,1931,983,
86291,2043,774,1,2045, 101081,2041,890,1,2043,
8630779,1,1574,799,1, 10109896,1,2045,901,1,
86311958,3257,16,0,498, 101101574,921,1,1958,3585,
86321,50,3258,19,614, 1011116,0,576,1,50,
86331,50,3259,5,38, 101123586,19,718,1,50,
86341,1901,3260,16,0, 101133587,5,38,1,1901,
8635612,1,2075,3261,16, 101143588,16,0,716,1,
86360,612,1,1860,821, 101152075,3589,16,0,716,
86371,1803,787,1,1804, 101161,1860,943,1,1803,
86383262,16,0,612,1, 10117909,1,1804,3590,16,
86392413,3263,16,0,612, 101180,716,1,2413,3591,
86401,2198,3264,16,0, 1011916,0,716,1,2198,
8641612,1,1873,835,1, 101203592,16,0,716,1,
86421657,894,1,1989,916, 101211873,958,1,1657,1016,
86431,1990,3265,16,0, 101221,1989,1038,1,1990,
8644612,1,1775,3266,16, 101233593,16,0,716,1,
86450,612,1,32,3267, 101241775,3594,16,0,716,
864616,0,612,1,2105, 101251,32,3595,16,0,
8647814,1,2106,3268,16, 10126716,1,2105,936,1,
86480,612,1,2364,827, 101272106,3596,16,0,716,
86491,2227,908,1,2337, 101281,2364,949,1,2227,
86503269,16,0,612,1, 101291030,1,2337,3597,16,
86512021,718,1,2458,876, 101300,716,1,2021,840,
86521,2459,882,1,2462, 101311,2458,998,1,2459,
8653889,1,2136,842,1, 101321004,1,2462,1011,1,
86542464,899,1,2029,725, 101332136,965,1,2464,1021,
86551,2030,731,1,2031, 101341,2029,847,1,2030,
8656736,1,2032,741,1, 10135853,1,2031,858,1,
86572033,746,1,2035,752, 101362032,863,1,2033,868,
86581,2037,757,1,2039, 101371,2035,874,1,2037,
8659762,1,1931,861,1, 10138879,1,2039,884,1,
86602041,768,1,2043,774, 101391931,983,1,2041,890,
86611,2045,779,1,1574, 101401,2043,896,1,2045,
8662799,1,1958,3270,16, 10141901,1,1574,921,1,
86630,612,1,51,3271, 101421958,3598,16,0,716,
866419,127,1,51,3272, 101431,51,3599,19,127,
86655,53,1,0,3273, 101441,51,3600,5,58,
866616,0,125,1,2075, 101451,0,3601,16,0,
86673274,16,0,125,1, 10146125,1,2537,3602,16,
86681860,821,1,1803,787, 101470,691,1,2837,3530,
86691,1804,3275,16,0, 101481,2838,3536,1,2839,
8670125,1,10,3276,16, 101493541,1,2840,3546,1,
86710,125,1,2413,3277, 101501860,943,1,10,3603,
867216,0,125,1,2198, 1015116,0,125,1,2413,
86733278,16,0,125,1, 101523604,16,0,125,1,
86741873,835,1,21,3279, 101532198,3605,16,0,125,
867516,0,125,1,1657, 101541,1873,958,1,21,
8676894,1,2030,731,1, 101553606,16,0,125,1,
86772642,3280,16,0,125, 101561657,1016,1,2030,853,
86781,1989,916,1,1990, 101571,1989,1038,1,1990,
86793281,16,0,125,1, 101583607,16,0,125,1,
86802459,882,1,1775,3282, 101592458,998,1,2459,1004,
868116,0,125,1,32, 101601,1775,3608,16,0,
86823283,16,0,125,1, 10161125,1,32,3609,16,
86832105,814,1,2106,3284, 101620,125,1,2105,936,
868416,0,125,1,2655, 101631,2106,3610,16,0,
86853211,1,2683,3223,1, 10164125,1,2045,901,1,
86862227,908,1,2337,3285, 101652766,3611,16,0,125,
101661,2227,1030,1,2337,
101673612,16,0,125,1,
101682075,3613,16,0,125,
101691,52,3614,16,0,
10170125,1,2560,3615,16,
101710,691,1,2779,3510,
101721,1803,909,1,1804,
101733616,16,0,125,1,
101741901,3617,16,0,125,
101751,2462,1011,1,2136,
10176965,1,2464,1021,1,
101772029,847,1,2466,3525,
101781,2031,858,1,2032,
10179863,1,2033,868,1,
101802035,874,1,2581,3618,
1018116,0,125,1,2364,
10182949,1,2039,884,1,
101831931,983,1,2041,890,
101841,2021,840,1,2043,
10185896,1,2807,3551,1,
101862510,3619,16,0,691,
101871,2514,3620,16,0,
10188691,1,2818,3516,1,
101892819,3621,16,0,125,
101901,2522,3622,16,0,
10191691,1,2037,879,1,
101921574,921,1,1958,3623,
868716,0,125,1,52, 1019316,0,125,1,52,
86883286,16,0,125,1, 101943624,19,124,1,52,
86892694,3216,1,2695,3287, 101953625,5,53,1,0,
869016,0,125,1,2021, 101963626,16,0,122,1,
8691718,1,2458,876,1, 101972837,3530,1,2838,3536,
86921901,3288,16,0,125, 101981,2839,3541,1,2840,
86931,2462,889,1,2136, 101993546,1,1860,943,1,
8694842,1,2464,899,1, 1020010,3627,16,0,122,
86952029,725,1,2466,3200, 102011,2413,3628,16,0,
86961,2031,736,1,2032, 10202122,1,2198,3629,16,
8697741,1,2033,746,1, 102030,122,1,1873,958,
86982035,752,1,2364,827, 102041,21,3630,16,0,
86991,2715,3195,1,2039, 10205122,1,1657,1016,1,
8700762,1,1931,861,1, 102062030,853,1,1989,1038,
87012041,768,1,2043,774, 102071,1990,3631,16,0,
87021,2045,779,1,2037, 10208122,1,2458,998,1,
8703757,1,2713,3206,1, 102092459,1004,1,1775,3632,
87042714,3183,1,1574,799, 1021016,0,122,1,32,
87051,2716,3189,1,1958, 102113633,16,0,122,1,
87063289,16,0,125,1, 102122105,936,1,2106,3634,
87072506,3290,16,0,125, 1021316,0,122,1,2766,
87081,52,3291,19,124, 102143635,16,0,122,1,
87091,52,3292,5,53, 102152227,1030,1,2337,3636,
87101,0,3293,16,0, 1021616,0,122,1,2075,
8711122,1,2075,3294,16, 102173637,16,0,122,1,
87120,122,1,1860,821, 1021852,3638,16,0,122,
87131,1803,787,1,1804, 102191,2779,3510,1,1803,
87143295,16,0,122,1, 10220909,1,1804,3639,16,
871510,3296,16,0,122, 102210,122,1,1901,3640,
87161,2413,3297,16,0,
8717122,1,2198,3298,16,
87180,122,1,1873,835,
87191,21,3299,16,0,
8720122,1,1657,894,1,
87212030,731,1,2642,3300,
872216,0,122,1,1989,
8723916,1,1990,3301,16,
87240,122,1,2459,882,
87251,1775,3302,16,0,
8726122,1,32,3303,16,
87270,122,1,2105,814,
87281,2106,3304,16,0,
8729122,1,2655,3211,1,
87302683,3223,1,2227,908,
87311,2337,3305,16,0,
8732122,1,52,3306,16,
87330,122,1,2694,3216,
87341,2695,3307,16,0,
8735122,1,2021,718,1,
87362458,876,1,1901,3308,
873716,0,122,1,2462, 1022216,0,122,1,2462,
8738889,1,2136,842,1, 102231011,1,2136,965,1,
87392464,899,1,2029,725, 102242464,1021,1,2029,847,
87401,2466,3200,1,2031, 102251,2466,3525,1,2031,
8741736,1,2032,741,1, 10226858,1,2032,863,1,
87422033,746,1,2035,752, 102272033,868,1,2035,874,
87431,2364,827,1,2715, 102281,2581,3641,16,0,
87443195,1,2039,762,1, 10229122,1,2364,949,1,
87451931,861,1,2041,768, 102302039,884,1,1931,983,
87461,2043,774,1,2045, 102311,2041,890,1,2021,
8747779,1,2037,757,1, 10232840,1,2043,896,1,
87482713,3206,1,2714,3183, 102332807,3551,1,2045,901,
87491,1574,799,1,2716, 102341,2818,3516,1,2819,
87503189,1,1958,3309,16, 102353642,16,0,122,1,
87510,122,1,2506,3310, 102362037,879,1,1574,921,
875216,0,122,1,53, 102371,1958,3643,16,0,
87533311,19,121,1,53, 10238122,1,53,3644,19,
87543312,5,53,1,0, 10239121,1,53,3645,5,
87553313,16,0,119,1, 1024053,1,0,3646,16,
87562075,3314,16,0,119, 102410,119,1,2837,3530,
87571,1860,821,1,1803, 102421,2838,3536,1,2839,
8758787,1,1804,3315,16, 102433541,1,2840,3546,1,
87590,119,1,10,3316, 102441860,943,1,10,3647,
876016,0,119,1,2413, 1024516,0,119,1,2413,
87613317,16,0,119,1, 102463648,16,0,119,1,
87622198,3318,16,0,119, 102472198,3649,16,0,119,
87631,1873,835,1,21, 102481,1873,958,1,21,
87643319,16,0,119,1, 102493650,16,0,119,1,
87651657,894,1,2030,731, 102501657,1016,1,2030,853,
87661,2642,3320,16,0, 102511,1989,1038,1,1990,
8767119,1,1989,916,1, 102523651,16,0,119,1,
87681990,3321,16,0,119, 102532458,998,1,2459,1004,
87691,2459,882,1,1775, 102541,1775,3652,16,0,
87703322,16,0,119,1, 10255119,1,32,3653,16,
877132,3323,16,0,119, 102560,119,1,2105,936,
87721,2105,814,1,2106, 102571,2106,3654,16,0,
87733324,16,0,119,1, 10258119,1,2766,3655,16,
87742655,3211,1,2683,3223, 102590,119,1,2227,1030,
87751,2227,908,1,2337, 102601,2337,3656,16,0,
87763325,16,0,119,1, 10261119,1,2075,3657,16,
877752,3326,16,0,119, 102620,119,1,52,3658,
87781,2694,3216,1,2695, 1026316,0,119,1,2779,
87793327,16,0,119,1, 102643510,1,1803,909,1,
87802021,718,1,2458,876, 102651804,3659,16,0,119,
87811,1901,3328,16,0, 102661,1901,3660,16,0,
8782119,1,2462,889,1, 10267119,1,2462,1011,1,
87832136,842,1,2464,899, 102682136,965,1,2464,1021,
87841,2029,725,1,2466, 102691,2029,847,1,2466,
87853200,1,2031,736,1, 102703525,1,2031,858,1,
87862032,741,1,2033,746, 102712032,863,1,2033,868,
87871,2035,752,1,2364, 102721,2035,874,1,2581,
8788827,1,2715,3195,1, 102733661,16,0,119,1,
87892039,762,1,1931,861, 102742364,949,1,2039,884,
87901,2041,768,1,2043, 102751,1931,983,1,2041,
8791774,1,2045,779,1, 10276890,1,2021,840,1,
87922037,757,1,2713,3206, 102772043,896,1,2807,3551,
87931,2714,3183,1,1574, 102781,2045,901,1,2818,
8794799,1,2716,3189,1, 102793516,1,2819,3662,16,
87951958,3329,16,0,119, 102800,119,1,2037,879,
87961,2506,3330,16,0, 102811,1574,921,1,1958,
8797119,1,54,3331,19, 102823663,16,0,119,1,
8798118,1,54,3332,5, 1028354,3664,19,118,1,
879953,1,0,3333,16, 1028454,3665,5,55,1,
88000,116,1,2075,3334, 102850,3666,16,0,116,
880116,0,116,1,1860, 102861,2837,3530,1,2838,
8802821,1,1803,787,1, 102873536,1,2839,3541,1,
88031804,3335,16,0,116, 102882840,3546,1,1860,943,
88041,10,3336,16,0, 102891,10,3667,16,0,
8805116,1,2413,3337,16, 10290116,1,2413,3668,16,
88060,116,1,2198,3338, 102910,116,1,2198,3669,
880716,0,116,1,1873, 1029216,0,116,1,1873,
8808835,1,21,3339,16, 10293958,1,21,3670,16,
88090,116,1,1657,894, 102940,116,1,1657,1016,
88101,2030,731,1,2642, 102951,2030,853,1,1989,
88113340,16,0,116,1, 102961038,1,1990,3671,16,
88121989,916,1,1990,3341, 102970,116,1,2458,998,
881316,0,116,1,2459, 102981,2459,1004,1,1775,
8814882,1,1775,3342,16, 102993672,16,0,116,1,
88150,116,1,32,3343, 1030032,3673,16,0,116,
881616,0,116,1,2105, 103011,2105,936,1,2106,
8817814,1,2106,3344,16, 103023674,16,0,116,1,
88180,116,1,2655,3211, 103032766,3675,16,0,116,
88191,2683,3223,1,2227, 103041,2227,1030,1,2337,
8820908,1,2337,3345,16, 103053676,16,0,116,1,
88210,116,1,52,3346, 103062075,3677,16,0,116,
882216,0,116,1,2694, 103071,52,3678,16,0,
88233216,1,2695,3347,16, 10308116,1,2779,3510,1,
88240,116,1,2021,718, 103091803,909,1,1804,3679,
88251,2458,876,1,1901, 1031016,0,116,1,1901,
88263348,16,0,116,1, 103113680,16,0,116,1,
88272462,889,1,2136,842, 103122462,1011,1,2136,965,
88281,2464,899,1,2029, 103131,2464,1021,1,2029,
8829725,1,2466,3200,1, 10314847,1,2466,3525,1,
88302031,736,1,2032,741, 103152031,858,1,2032,863,
88311,2033,746,1,2035, 103161,2033,868,1,2035,
8832752,1,2364,827,1, 10317874,1,2581,3681,16,
88332715,3195,1,2039,762, 103180,116,1,2364,949,
88341,1931,861,1,2041, 103191,2039,884,1,1931,
8835768,1,2043,774,1, 10320983,1,2041,890,1,
88362045,779,1,2037,757, 103212021,840,1,2043,896,
88371,2713,3206,1,2714, 103221,2807,3551,1,2045,
88383183,1,1574,799,1, 10323901,1,2568,3682,16,
88392716,3189,1,1958,3349, 103240,470,1,2818,3516,
103251,2819,3683,16,0,
10326116,1,2037,879,1,
103271574,921,1,1958,3684,
884016,0,116,1,2506, 1032816,0,116,1,2506,
88413350,16,0,116,1, 103293685,16,0,470,1,
884255,3351,19,115,1, 1033055,3686,19,115,1,
884355,3352,5,53,1, 1033155,3687,5,56,1,
88440,3353,16,0,113, 103320,3688,16,0,113,
88451,2075,3354,16,0, 103331,2837,3530,1,2838,
8846113,1,1860,821,1, 103343536,1,2839,3541,1,
88471803,787,1,1804,3355, 103352840,3546,1,1860,943,
884816,0,113,1,10, 103361,10,3689,16,0,
88493356,16,0,113,1, 10337113,1,2413,3690,16,
88502413,3357,16,0,113, 103380,113,1,2525,3691,
88511,2198,3358,16,0, 1033916,0,493,1,1657,
8852113,1,1873,835,1, 103401016,1,1873,958,1,
885321,3359,16,0,113, 1034121,3692,16,0,113,
88541,1657,894,1,2030, 103421,2529,3693,16,0,
8855731,1,2642,3360,16, 10343493,1,2030,853,1,
88560,113,1,1989,916, 103441989,1038,1,1990,3694,
88571,1990,3361,16,0, 1034516,0,113,1,2458,
8858113,1,2459,882,1, 10346998,1,2459,1004,1,
88591775,3362,16,0,113, 103471775,3695,16,0,113,
88601,32,3363,16,0, 103481,32,3696,16,0,
8861113,1,2105,814,1, 10349113,1,2105,936,1,
88622106,3364,16,0,113, 103502106,3697,16,0,113,
88631,2655,3211,1,2683, 103511,2766,3698,16,0,
88643223,1,2227,908,1, 10352113,1,2552,3699,16,
88652337,3365,16,0,113, 103530,493,1,2227,1030,
88661,52,3366,16,0, 103541,2337,3700,16,0,
8867113,1,2694,3216,1, 10355113,1,2075,3701,16,
88682695,3367,16,0,113, 103560,113,1,52,3702,
88691,2021,718,1,2458, 1035716,0,113,1,2779,
8870876,1,1901,3368,16, 103583510,1,1803,909,1,
88710,113,1,2462,889, 103591804,3703,16,0,113,
88721,2136,842,1,2464, 103601,1901,3704,16,0,
8873899,1,2029,725,1, 10361113,1,2462,1011,1,
88742466,3200,1,2031,736, 103622136,965,1,2464,1021,
88751,2032,741,1,2033, 103631,2029,847,1,2466,
8876746,1,2035,752,1, 103643525,1,2031,858,1,
88772364,827,1,2715,3195, 103652032,863,1,2033,868,
88781,2039,762,1,1931, 103661,2035,874,1,2581,
8879861,1,2041,768,1, 103673705,16,0,113,1,
88802043,774,1,2045,779, 103682364,949,1,2039,884,
88811,2037,757,1,2713, 103691,1931,983,1,2041,
88823206,1,2714,3183,1, 10370890,1,2021,840,1,
88831574,799,1,2716,3189, 103712043,896,1,2807,3551,
88841,1958,3369,16,0, 103721,2045,901,1,2198,
8885113,1,2506,3370,16, 103733706,16,0,113,1,
88860,113,1,56,3371, 103742818,3516,1,2819,3707,
888719,112,1,56,3372, 1037516,0,113,1,2037,
88885,53,1,0,3373, 10376879,1,1574,921,1,
888916,0,110,1,2075, 103771958,3708,16,0,113,
88903374,16,0,110,1, 103781,56,3709,19,112,
88911860,821,1,1803,787, 103791,56,3710,5,55,
88921,1804,3375,16,0, 103801,0,3711,16,0,
8893110,1,10,3376,16, 10381110,1,2837,3530,1,
88940,110,1,2413,3377, 103822838,3536,1,2839,3541,
103831,2840,3546,1,1860,
10384943,1,10,3712,16,
103850,110,1,2413,3713,
889516,0,110,1,2198, 1038616,0,110,1,2198,
88963378,16,0,110,1, 103873714,16,0,110,1,
88971873,835,1,21,3379, 103881873,958,1,21,3715,
889816,0,110,1,1657, 1038916,0,110,1,1657,
8899894,1,2030,731,1, 103901016,1,2030,853,1,
89002642,3380,16,0,110, 103911989,1038,1,1990,3716,
89011,1989,916,1,1990, 1039216,0,110,1,2458,
89023381,16,0,110,1, 10393998,1,2459,1004,1,
89032459,882,1,1775,3382, 103941775,3717,16,0,110,
890416,0,110,1,32, 103951,32,3718,16,0,
89053383,16,0,110,1, 10396110,1,2540,3719,16,
89062105,814,1,2106,3384, 103970,511,1,2105,936,
890716,0,110,1,2655, 103981,2106,3720,16,0,
89083211,1,2683,3223,1, 10399110,1,2544,3721,16,
89092227,908,1,2337,3385, 104000,511,1,2766,3722,
1040116,0,110,1,2227,
104021030,1,2337,3723,16,
104030,110,1,2075,3724,
891016,0,110,1,52, 1040416,0,110,1,52,
89113386,16,0,110,1, 104053725,16,0,110,1,
89122694,3216,1,2695,3387, 104062779,3510,1,1803,909,
891316,0,110,1,2021, 104071,1804,3726,16,0,
8914718,1,2458,876,1, 10408110,1,1901,3727,16,
89151901,3388,16,0,110, 104090,110,1,2462,1011,
89161,2462,889,1,2136, 104101,2136,965,1,2464,
8917842,1,2464,899,1, 104111021,1,2029,847,1,
89182029,725,1,2466,3200, 104122466,3525,1,2031,858,
89191,2031,736,1,2032, 104131,2032,863,1,2033,
8920741,1,2033,746,1, 10414868,1,2035,874,1,
89212035,752,1,2364,827, 104152581,3728,16,0,110,
89221,2715,3195,1,2039, 104161,2364,949,1,2039,
8923762,1,1931,861,1, 10417884,1,1931,983,1,
89242041,768,1,2043,774, 104182041,890,1,2021,840,
89251,2045,779,1,2037, 104191,2043,896,1,2807,
8926757,1,2713,3206,1, 104203551,1,2045,901,1,
89272714,3183,1,1574,799, 104212818,3516,1,2819,3729,
89281,2716,3189,1,1958, 1042216,0,110,1,2037,
89293389,16,0,110,1, 10423879,1,1574,921,1,
89302506,3390,16,0,110, 104241958,3730,16,0,110,
89311,57,3391,19,109, 104251,57,3731,19,109,
89321,57,3392,5,53, 104261,57,3732,5,53,
89331,0,3393,16,0, 104271,0,3733,16,0,
8934107,1,2075,3394,16, 10428107,1,2837,3530,1,
89350,107,1,1860,821, 104292838,3536,1,2839,3541,
89361,1803,787,1,1804, 104301,2840,3546,1,1860,
89373395,16,0,107,1, 10431943,1,10,3734,16,
893810,3396,16,0,107, 104320,107,1,2413,3735,
89391,2413,3397,16,0, 1043316,0,107,1,2198,
8940107,1,2198,3398,16, 104343736,16,0,107,1,
89410,107,1,1873,835, 104351873,958,1,21,3737,
89421,21,3399,16,0, 1043616,0,107,1,1657,
8943107,1,1657,894,1, 104371016,1,2030,853,1,
89442030,731,1,2642,3400, 104381989,1038,1,1990,3738,
894516,0,107,1,1989, 1043916,0,107,1,2458,
8946916,1,1990,3401,16, 10440998,1,2459,1004,1,
89470,107,1,2459,882, 104411775,3739,16,0,107,
89481,1775,3402,16,0, 104421,32,3740,16,0,
8949107,1,32,3403,16, 10443107,1,2105,936,1,
89500,107,1,2105,814, 104442106,3741,16,0,107,
89511,2106,3404,16,0, 104451,2766,3742,16,0,
8952107,1,2655,3211,1, 10446107,1,2227,1030,1,
89532683,3223,1,2227,908, 104472337,3743,16,0,107,
89541,2337,3405,16,0, 104481,2075,3744,16,0,
8955107,1,52,3406,16, 10449107,1,52,3745,16,
89560,107,1,2694,3216, 104500,107,1,2779,3510,
89571,2695,3407,16,0, 104511,1803,909,1,1804,
8958107,1,2021,718,1, 104523746,16,0,107,1,
89592458,876,1,1901,3408, 104531901,3747,16,0,107,
896016,0,107,1,2462, 104541,2462,1011,1,2136,
8961889,1,2136,842,1, 10455965,1,2464,1021,1,
89622464,899,1,2029,725, 104562029,847,1,2466,3525,
89631,2466,3200,1,2031, 104571,2031,858,1,2032,
8964736,1,2032,741,1, 10458863,1,2033,868,1,
89652033,746,1,2035,752, 104592035,874,1,2581,3748,
89661,2364,827,1,2715, 1046016,0,107,1,2364,
89673195,1,2039,762,1, 10461949,1,2039,884,1,
89681931,861,1,2041,768, 104621931,983,1,2041,890,
89691,2043,774,1,2045, 104631,2021,840,1,2043,
8970779,1,2037,757,1, 10464896,1,2807,3551,1,
89712713,3206,1,2714,3183, 104652045,901,1,2818,3516,
89721,1574,799,1,2716, 104661,2819,3749,16,0,
89733189,1,1958,3409,16, 10467107,1,2037,879,1,
89740,107,1,2506,3410, 104681574,921,1,1958,3750,
897516,0,107,1,58, 1046916,0,107,1,58,
89763411,19,429,1,58, 104703751,19,386,1,58,
89773412,5,9,1,2519, 104713752,5,30,1,2644,
89781618,1,2557,1627,1, 104721753,1,2520,1758,1,
89792521,3413,16,0,427, 104732639,1765,1,2640,1770,
89801,2559,1633,1,2597, 104741,2641,1775,1,2642,
89813414,16,0,427,1, 104751780,1,2643,1747,1,
89822561,3415,16,0,427, 104762535,1785,1,2645,1791,
89831,2459,882,1,2464, 104771,2646,1796,1,2648,
8984899,1,2470,3416,16, 104781875,1,2649,1802,1,
89850,427,1,59,3417, 104792650,1807,1,2651,1812,
898619,426,1,59,3418, 104801,2652,1817,1,2653,
89875,9,1,2519,1618, 104811822,1,2654,1827,1,
89881,2557,1627,1,2521, 104822655,1832,1,2657,3753,
89893419,16,0,424,1, 1048316,0,384,1,2550,
89902559,1633,1,2597,3420, 104841843,1,2579,1861,1,
899116,0,424,1,2561, 104852558,1849,1,2566,1855,
89923421,16,0,424,1, 104861,2459,1004,1,2464,
89932459,882,1,2464,899, 104871021,1,2574,1837,1,
89941,2470,3422,16,0, 104882470,3754,16,0,384,
8995424,1,60,3423,19, 104891,2700,3755,16,0,
8996423,1,60,3424,5, 10490384,1,2594,1868,1,
89979,1,2519,1618,1, 104912596,3756,16,0,384,
89982557,1627,1,2521,3425, 104921,59,3757,19,383,
899916,0,421,1,2559, 104931,59,3758,5,30,
90001633,1,2597,3426,16, 104941,2644,1753,1,2520,
90010,421,1,2561,3427, 104951758,1,2639,1765,1,
900216,0,421,1,2459, 104962640,1770,1,2641,1775,
9003882,1,2464,899,1, 104971,2642,1780,1,2643,
90042470,3428,16,0,421, 104981747,1,2535,1785,1,
90051,61,3429,19,420, 104992645,1791,1,2646,1796,
90061,61,3430,5,9, 105001,2648,1875,1,2649,
90071,2519,1618,1,2557, 105011802,1,2650,1807,1,
90081627,1,2521,3431,16, 105022651,1812,1,2652,1817,
90090,418,1,2559,1633, 105031,2653,1822,1,2654,
90101,2597,3432,16,0, 105041827,1,2655,1832,1,
9011418,1,2561,3433,16, 105052657,3759,16,0,381,
90120,418,1,2459,882, 105061,2550,1843,1,2579,
90131,2464,899,1,2470, 105071861,1,2558,1849,1,
90143434,16,0,418,1, 105082566,1855,1,2459,1004,
901562,3435,19,417,1, 105091,2464,1021,1,2574,
901662,3436,5,9,1, 105101837,1,2470,3760,16,
90172519,1618,1,2557,1627, 105110,381,1,2700,3761,
90181,2521,3437,16,0, 1051216,0,381,1,2594,
9019415,1,2559,1633,1, 105131868,1,2596,3762,16,
90202597,3438,16,0,415, 105140,381,1,60,3763,
90211,2561,3439,16,0, 1051519,545,1,60,3764,
9022415,1,2459,882,1, 105165,30,1,2644,1753,
90232464,899,1,2470,3440, 105171,2520,1758,1,2639,
902416,0,415,1,63, 105181765,1,2640,1770,1,
90253441,19,414,1,63, 105192641,1775,1,2642,1780,
90263442,5,9,1,2519, 105201,2643,1747,1,2535,
90271618,1,2557,1627,1, 105211785,1,2645,1791,1,
90282521,3443,16,0,412, 105222646,1796,1,2648,1875,
90291,2559,1633,1,2597, 105231,2649,1802,1,2650,
90303444,16,0,412,1, 105241807,1,2651,1812,1,
90312561,3445,16,0,412, 105252652,1817,1,2653,1822,
90321,2459,882,1,2464, 105261,2654,1827,1,2655,
9033899,1,2470,3446,16, 105271832,1,2657,3765,16,
90340,412,1,64,3447, 105280,543,1,2550,1843,
903519,653,1,64,3448, 105291,2579,1861,1,2558,
90365,9,1,2519,1618, 105301849,1,2566,1855,1,
90371,2557,1627,1,2521, 105312459,1004,1,2464,1021,
90383449,16,0,651,1, 105321,2574,1837,1,2470,
90392559,1633,1,2597,3450, 105333766,16,0,543,1,
904016,0,651,1,2561, 105342700,3767,16,0,543,
90413451,16,0,651,1, 105351,2594,1868,1,2596,
90422459,882,1,2464,899, 105363768,16,0,543,1,
90431,2470,3452,16,0, 1053761,3769,19,423,1,
9044651,1,65,3453,19, 1053861,3770,5,30,1,
9045410,1,65,3454,5, 105392644,1753,1,2520,1758,
90469,1,2519,1618,1, 105401,2639,1765,1,2640,
90472557,1627,1,2521,3455, 105411770,1,2641,1775,1,
904816,0,408,1,2559, 105422642,1780,1,2643,1747,
90491633,1,2597,3456,16, 105431,2535,1785,1,2645,
90500,408,1,2561,3457, 105441791,1,2646,1796,1,
905116,0,408,1,2459, 105452648,1875,1,2649,1802,
9052882,1,2464,899,1, 105461,2650,1807,1,2651,
90532470,3458,16,0,408, 105471812,1,2652,1817,1,
90541,66,3459,19,493, 105482653,1822,1,2654,1827,
90551,66,3460,5,9, 105491,2655,1832,1,2657,
90561,2519,1618,1,2557, 105503771,16,0,421,1,
90571627,1,2521,3461,16, 105512550,1843,1,2579,1861,
90580,491,1,2559,1633, 105521,2558,1849,1,2566,
90591,2597,3462,16,0, 105531855,1,2459,1004,1,
9060491,1,2561,3463,16, 105542464,1021,1,2574,1837,
90610,491,1,2459,882, 105551,2470,3772,16,0,
90621,2464,899,1,2470, 10556421,1,2700,3773,16,
90633464,16,0,491,1, 105570,421,1,2594,1868,
906467,3465,19,406,1, 105581,2596,3774,16,0,
906567,3466,5,9,1, 10559421,1,62,3775,19,
90662519,1618,1,2557,1627, 10560541,1,62,3776,5,
90671,2521,3467,16,0, 1056130,1,2644,1753,1,
9068404,1,2559,1633,1, 105622520,1758,1,2639,1765,
90692597,3468,16,0,404, 105631,2640,1770,1,2641,
90701,2561,3469,16,0, 105641775,1,2642,1780,1,
9071404,1,2459,882,1, 105652643,1747,1,2535,1785,
90722464,899,1,2470,3470, 105661,2645,1791,1,2646,
907316,0,404,1,68, 105671796,1,2648,1875,1,
90743471,19,403,1,68, 105682649,1802,1,2650,1807,
90753472,5,9,1,2519, 105691,2651,1812,1,2652,
90761618,1,2557,1627,1, 105701817,1,2653,1822,1,
90772521,3473,16,0,401, 105712654,1827,1,2655,1832,
90781,2559,1633,1,2597, 105721,2657,3777,16,0,
90793474,16,0,401,1, 10573539,1,2550,1843,1,
90802561,3475,16,0,401, 105742579,1861,1,2558,1849,
90811,2459,882,1,2464, 105751,2566,1855,1,2459,
9082899,1,2470,3476,16, 105761004,1,2464,1021,1,
90830,401,1,69,3477, 105772574,1837,1,2470,3778,
908419,486,1,69,3478, 1057816,0,539,1,2700,
90855,9,1,2519,1618, 105793779,16,0,539,1,
90861,2557,1627,1,2521, 105802594,1868,1,2596,3780,
90873479,16,0,484,1, 1058116,0,539,1,63,
90882559,1633,1,2597,3480, 105823781,19,653,1,63,
908916,0,484,1,2561, 105833782,5,30,1,2644,
90903481,16,0,484,1, 105841753,1,2520,1758,1,
90912459,882,1,2464,899, 105852639,1765,1,2640,1770,
90921,2470,3482,16,0, 105861,2641,1775,1,2642,
9093484,1,70,3483,19, 105871780,1,2643,1747,1,
9094399,1,70,3484,5, 105882535,1785,1,2645,1791,
90959,1,2519,1618,1, 105891,2646,1796,1,2648,
90962557,1627,1,2521,3485, 105901875,1,2649,1802,1,
909716,0,397,1,2559, 105912650,1807,1,2651,1812,
90981633,1,2597,3486,16, 105921,2652,1817,1,2653,
90990,397,1,2561,3487, 105931822,1,2654,1827,1,
910016,0,397,1,2459, 105942655,1832,1,2657,3783,
9101882,1,2464,899,1, 1059516,0,651,1,2550,
91022470,3488,16,0,397, 105961843,1,2579,1861,1,
91031,71,3489,19,483, 105972558,1849,1,2566,1855,
91041,71,3490,5,9, 105981,2459,1004,1,2464,
91051,2519,1618,1,2557, 105991021,1,2574,1837,1,
91061627,1,2521,3491,16, 106002470,3784,16,0,651,
91070,481,1,2559,1633, 106011,2700,3785,16,0,
91081,2597,3492,16,0, 10602651,1,2594,1868,1,
9109481,1,2561,3493,16, 106032596,3786,16,0,651,
91100,481,1,2459,882, 106041,64,3787,19,416,
91111,2464,899,1,2470, 106051,64,3788,5,30,
91123494,16,0,481,1, 106061,2644,1753,1,2520,
911372,3495,19,480,1, 106071758,1,2639,1765,1,
911472,3496,5,9,1, 106082640,1770,1,2641,1775,
91152519,1618,1,2557,1627, 106091,2642,1780,1,2643,
91161,2521,3497,16,0, 106101747,1,2535,1785,1,
9117478,1,2559,1633,1, 106112645,1791,1,2646,1796,
91182597,3498,16,0,478, 106121,2648,1875,1,2649,
91191,2561,3499,16,0, 106131802,1,2650,1807,1,
9120478,1,2459,882,1, 106142651,1812,1,2652,1817,
91212464,899,1,2470,3500, 106151,2653,1822,1,2654,
912216,0,478,1,73, 106161827,1,2655,1832,1,
91233501,19,477,1,73, 106172657,3789,16,0,414,
91243502,5,9,1,2519, 106181,2550,1843,1,2579,
91251618,1,2557,1627,1, 106191861,1,2558,1849,1,
91262521,3503,16,0,475, 106202566,1855,1,2459,1004,
91271,2559,1633,1,2597, 106211,2464,1021,1,2574,
91283504,16,0,475,1, 106221837,1,2470,3790,16,
91292561,3505,16,0,475, 106230,414,1,2700,3791,
91301,2459,882,1,2464, 1062416,0,414,1,2594,
9131899,1,2470,3506,16, 106251868,1,2596,3792,16,
91320,475,1,74,3507, 106260,414,1,65,3793,
913319,474,1,74,3508, 1062719,380,1,65,3794,
91345,9,1,2519,1618, 106285,30,1,2644,1753,
91351,2557,1627,1,2521, 106291,2520,1758,1,2639,
91363509,16,0,472,1, 106301765,1,2640,1770,1,
91372559,1633,1,2597,3510, 106312641,1775,1,2642,1780,
913816,0,472,1,2561, 106321,2643,1747,1,2535,
91393511,16,0,472,1, 106331785,1,2645,1791,1,
91402459,882,1,2464,899, 106342646,1796,1,2648,1875,
91411,2470,3512,16,0, 106351,2649,1802,1,2650,
9142472,1,75,3513,19, 106361807,1,2651,1812,1,
9143390,1,75,3514,5, 106372652,1817,1,2653,1822,
91449,1,2519,1618,1, 106381,2654,1827,1,2655,
91452557,1627,1,2521,3515, 106391832,1,2657,3795,16,
914616,0,388,1,2559, 106400,378,1,2550,1843,
91471633,1,2597,3516,16, 106411,2579,1861,1,2558,
91480,388,1,2561,3517, 106421849,1,2566,1855,1,
914916,0,388,1,2459, 106432459,1004,1,2464,1021,
9150882,1,2464,899,1, 106441,2574,1837,1,2470,
91512470,3518,16,0,388, 106453796,16,0,378,1,
91521,76,3519,19,387, 106462700,3797,16,0,378,
91531,76,3520,5,9, 106471,2594,1868,1,2596,
91541,2519,1618,1,2557, 106483798,16,0,378,1,
91551627,1,2521,3521,16, 1064966,3799,19,465,1,
91560,385,1,2559,1633, 1065066,3800,5,30,1,
91571,2597,3522,16,0, 106512644,1753,1,2520,1758,
9158385,1,2561,3523,16, 106521,2639,1765,1,2640,
91590,385,1,2459,882, 106531770,1,2641,1775,1,
91601,2464,899,1,2470, 106542642,1780,1,2643,1747,
91613524,16,0,385,1, 106551,2535,1785,1,2645,
916277,3525,19,471,1, 106561791,1,2646,1796,1,
916377,3526,5,9,1, 106572648,1875,1,2649,1802,
91642519,1618,1,2557,1627, 106581,2650,1807,1,2651,
91651,2521,3527,16,0, 106591812,1,2652,1817,1,
9166469,1,2559,1633,1, 106602653,1822,1,2654,1827,
91672597,3528,16,0,469, 106611,2655,1832,1,2657,
91681,2561,3529,16,0, 106623801,16,0,463,1,
9169469,1,2459,882,1, 106632550,1843,1,2579,1861,
91702464,899,1,2470,3530, 106641,2558,1849,1,2566,
917116,0,469,1,78, 106651855,1,2459,1004,1,
91723531,19,566,1,78, 106662464,1021,1,2574,1837,
91733532,5,9,1,2519, 106671,2470,3802,16,0,
91741618,1,2557,1627,1, 10668463,1,2700,3803,16,
91752521,3533,16,0,564, 106690,463,1,2594,1868,
91761,2559,1633,1,2597, 106701,2596,3804,16,0,
91773534,16,0,564,1, 10671463,1,67,3805,19,
91782561,3535,16,0,564, 10672462,1,67,3806,5,
91791,2459,882,1,2464, 1067330,1,2644,1753,1,
9180899,1,2470,3536,16, 106742520,1758,1,2639,1765,
91810,564,1,79,3537, 106751,2640,1770,1,2641,
918219,380,1,79,3538, 106761775,1,2642,1780,1,
91835,9,1,2519,1618, 106772643,1747,1,2535,1785,
91841,2557,1627,1,2521, 106781,2645,1791,1,2646,
91853539,16,0,378,1, 106791796,1,2648,1875,1,
91862559,1633,1,2597,3540, 106802649,1802,1,2650,1807,
918716,0,378,1,2561, 106811,2651,1812,1,2652,
91883541,16,0,378,1, 106821817,1,2653,1822,1,
91892459,882,1,2464,899, 106832654,1827,1,2655,1832,
91901,2470,3542,16,0, 106841,2657,3807,16,0,
9191378,1,80,3543,19, 10685460,1,2550,1843,1,
9192377,1,80,3544,5, 106862579,1861,1,2558,1849,
91939,1,2519,1618,1, 106871,2566,1855,1,2459,
91942557,1627,1,2521,3545, 106881004,1,2464,1021,1,
919516,0,375,1,2559, 106892574,1837,1,2470,3808,
91961633,1,2597,3546,16, 1069016,0,460,1,2700,
91970,375,1,2561,3547, 106913809,16,0,460,1,
919816,0,375,1,2459, 106922594,1868,1,2596,3810,
9199882,1,2464,899,1, 1069316,0,460,1,68,
92002470,3548,16,0,375, 106943811,19,459,1,68,
92011,81,3549,19,374, 106953812,5,30,1,2644,
92021,81,3550,5,9, 106961753,1,2520,1758,1,
92031,2519,1618,1,2557, 106972639,1765,1,2640,1770,
92041627,1,2521,3551,16, 106981,2641,1775,1,2642,
92050,372,1,2559,1633, 106991780,1,2643,1747,1,
92061,2597,3552,16,0, 107002535,1785,1,2645,1791,
9207372,1,2561,3553,16, 107011,2646,1796,1,2648,
92080,372,1,2459,882, 107021875,1,2649,1802,1,
92091,2464,899,1,2470, 107032650,1807,1,2651,1812,
92103554,16,0,372,1, 107041,2652,1817,1,2653,
921182,3555,19,371,1, 107051822,1,2654,1827,1,
921282,3556,5,9,1, 107062655,1832,1,2657,3813,
92132519,1618,1,2557,1627, 1070716,0,457,1,2550,
92141,2521,3557,16,0, 107081843,1,2579,1861,1,
9215369,1,2559,1633,1, 107092558,1849,1,2566,1855,
92162597,3558,16,0,369, 107101,2459,1004,1,2464,
92171,2561,3559,16,0, 107111021,1,2574,1837,1,
9218369,1,2459,882,1, 107122470,3814,16,0,457,
92192464,899,1,2470,3560, 107131,2700,3815,16,0,
922016,0,369,1,83, 10714457,1,2594,1868,1,
92213561,19,368,1,83, 107152596,3816,16,0,457,
92223562,5,9,1,2519, 107161,69,3817,19,395,
92231618,1,2557,1627,1, 107171,69,3818,5,30,
92242521,3563,16,0,366, 107181,2644,1753,1,2520,
92251,2559,1633,1,2597, 107191758,1,2639,1765,1,
92263564,16,0,366,1, 107202640,1770,1,2641,1775,
92272561,3565,16,0,366, 107211,2642,1780,1,2643,
92281,2459,882,1,2464, 107221747,1,2535,1785,1,
9229899,1,2470,3566,16, 107232645,1791,1,2646,1796,
92300,366,1,84,3567, 107241,2648,1875,1,2649,
923119,365,1,84,3568, 107251802,1,2650,1807,1,
92325,9,1,2519,1618, 107262651,1812,1,2652,1817,
92331,2557,1627,1,2521, 107271,2653,1822,1,2654,
92343569,16,0,363,1, 107281827,1,2655,1832,1,
92352559,1633,1,2597,3570, 107292657,3819,16,0,393,
923616,0,363,1,2561, 107301,2550,1843,1,2579,
92373571,16,0,363,1, 107311861,1,2558,1849,1,
92382459,882,1,2464,899, 107322566,1855,1,2459,1004,
92391,2470,3572,16,0, 107331,2464,1021,1,2574,
9240363,1,85,3573,19, 107341837,1,2470,3820,16,
9241362,1,85,3574,5, 107350,393,1,2700,3821,
92429,1,2519,1618,1, 1073616,0,393,1,2594,
92432557,1627,1,2521,3575, 107371868,1,2596,3822,16,
924416,0,360,1,2559, 107380,393,1,70,3823,
92451633,1,2597,3576,16, 1073919,392,1,70,3824,
92460,360,1,2561,3577, 107405,30,1,2644,1753,
924716,0,360,1,2459, 107411,2520,1758,1,2639,
9248882,1,2464,899,1, 107421765,1,2640,1770,1,
92492470,3578,16,0,360, 107432641,1775,1,2642,1780,
92501,86,3579,19,359, 107441,2643,1747,1,2535,
92511,86,3580,5,9, 107451785,1,2645,1791,1,
92521,2519,1618,1,2557, 107462646,1796,1,2648,1875,
92531627,1,2521,3581,16, 107471,2649,1802,1,2650,
92540,357,1,2559,1633, 107481807,1,2651,1812,1,
92551,2597,3582,16,0, 107492652,1817,1,2653,1822,
9256357,1,2561,3583,16, 107501,2654,1827,1,2655,
92570,357,1,2459,882, 107511832,1,2657,3825,16,
92581,2464,899,1,2470, 107520,390,1,2550,1843,
92593584,16,0,357,1, 107531,2579,1861,1,2558,
926087,3585,19,356,1, 107541849,1,2566,1855,1,
926187,3586,5,9,1, 107552459,1004,1,2464,1021,
92622519,1618,1,2557,1627, 107561,2574,1837,1,2470,
92631,2521,3587,16,0, 107573826,16,0,390,1,
9264354,1,2559,1633,1, 107582700,3827,16,0,390,
92652597,3588,16,0,354, 107591,2594,1868,1,2596,
92661,2561,3589,16,0, 107603828,16,0,390,1,
9267354,1,2459,882,1, 1076171,3829,19,389,1,
92682464,899,1,2470,3590, 1076271,3830,5,30,1,
926916,0,354,1,88, 107632644,1753,1,2520,1758,
92703591,19,353,1,88, 107641,2639,1765,1,2640,
92713592,5,9,1,2519, 107651770,1,2641,1775,1,
92721618,1,2557,1627,1, 107662642,1780,1,2643,1747,
92732521,3593,16,0,351, 107671,2535,1785,1,2645,
92741,2559,1633,1,2597, 107681791,1,2646,1796,1,
92753594,16,0,351,1, 107692648,1875,1,2649,1802,
92762561,3595,16,0,351, 107701,2650,1807,1,2651,
92771,2459,882,1,2464, 107711812,1,2652,1817,1,
9278899,1,2470,3596,16, 107722653,1822,1,2654,1827,
92790,351,1,89,3597, 107731,2655,1832,1,2657,
928019,347,1,89,3598, 107743831,16,0,387,1,
92815,9,1,2519,1618, 107752550,1843,1,2579,1861,
92821,2557,1627,1,2521, 107761,2558,1849,1,2566,
92833599,16,0,345,1, 107771855,1,2459,1004,1,
92842559,1633,1,2597,3600, 107782464,1021,1,2574,1837,
928516,0,345,1,2561, 107791,2470,3832,16,0,
92863601,16,0,345,1, 10780387,1,2700,3833,16,
92872459,882,1,2464,899, 107810,387,1,2594,1868,
92881,2470,3602,16,0, 107821,2596,3834,16,0,
9289345,1,90,3603,19, 10783387,1,72,3835,19,
9290350,1,90,3604,5, 10784456,1,72,3836,5,
92919,1,2519,1618,1, 1078530,1,2644,1753,1,
92922557,1627,1,2521,3605, 107862520,1758,1,2639,1765,
929316,0,348,1,2559, 107871,2640,1770,1,2641,
92941633,1,2597,3606,16, 107881775,1,2642,1780,1,
92950,348,1,2561,3607, 107892643,1747,1,2535,1785,
929616,0,348,1,2459, 107901,2645,1791,1,2646,
9297882,1,2464,899,1, 107911796,1,2648,1875,1,
92982470,3608,16,0,348, 107922649,1802,1,2650,1807,
92991,91,3609,19,344, 107931,2651,1812,1,2652,
93001,91,3610,5,9, 107941817,1,2653,1822,1,
93011,2519,1618,1,2557, 107952654,1827,1,2655,1832,
93021627,1,2521,3611,16, 107961,2657,3837,16,0,
93030,342,1,2559,1633, 10797454,1,2550,1843,1,
93041,2597,3612,16,0, 107982579,1861,1,2558,1849,
9305342,1,2561,3613,16, 107991,2566,1855,1,2459,
93060,342,1,2459,882, 108001004,1,2464,1021,1,
93071,2464,899,1,2470, 108012574,1837,1,2470,3838,
93083614,16,0,342,1, 1080216,0,454,1,2700,
930992,3615,19,133,1, 108033839,16,0,454,1,
931092,3616,5,125,1, 108042594,1868,1,2596,3840,
93110,3617,16,0,563, 1080516,0,454,1,73,
93121,1,1951,1,2, 108063841,19,453,1,73,
93131957,1,3,1962,1, 108073842,5,30,1,2644,
93144,1967,1,5,1972, 108081753,1,2520,1758,1,
93151,6,1977,1,7, 108092639,1765,1,2640,1770,
93161982,1,8,3618,16, 108101,2641,1775,1,2642,
93170,131,1,1515,3619, 108111780,1,2643,1747,1,
931816,0,165,1,2021, 108122535,1785,1,2645,1791,
9319718,1,2022,3620,16, 108131,2646,1796,1,2648,
93200,497,1,256,3621, 108141875,1,2649,1802,1,
932116,0,173,1,2025, 108152650,1807,1,2651,1812,
93223622,16,0,501,1, 108161,2652,1817,1,2653,
932318,3623,16,0,138, 108171822,1,2654,1827,1,
93241,2027,3624,16,0, 108182655,1832,1,2657,3843,
9325505,1,2695,3625,16, 1081916,0,451,1,2550,
93260,563,1,2029,725, 108201843,1,2579,1861,1,
93271,2030,731,1,2031, 108212558,1849,1,2566,1855,
9328736,1,2032,741,1, 108221,2459,1004,1,2464,
93292033,746,1,277,3626, 108231021,1,2574,1837,1,
933016,0,173,1,2035, 108242470,3844,16,0,451,
9331752,1,2037,757,1, 108251,2700,3845,16,0,
93322039,762,1,32,3627, 10826451,1,2594,1868,1,
933316,0,165,1,2041, 108272596,3846,16,0,451,
9334768,1,2293,3628,16, 108281,74,3847,19,450,
93350,173,1,2043,774, 108291,74,3848,5,30,
93361,2045,779,1,2713, 108301,2644,1753,1,2520,
93373206,1,2715,3195,1, 108311758,1,2639,1765,1,
933841,3629,16,0,173, 108322640,1770,1,2641,1775,
93391,1297,3630,16,0, 108331,2642,1780,1,2643,
9340165,1,43,3631,16, 108341747,1,2535,1785,1,
93410,173,1,46,3632, 108352645,1791,1,2646,1796,
934216,0,178,1,1804, 108361,2648,1875,1,2649,
93433633,16,0,165,1, 108371802,1,2650,1807,1,
9344299,3634,16,0,173, 108382651,1812,1,2652,1817,
93451,52,3635,16,0, 108391,2653,1822,1,2654,
9346165,1,509,3636,16, 108401827,1,2655,1832,1,
93470,173,1,2318,3637, 108412657,3849,16,0,448,
934816,0,165,1,62, 108421,2550,1843,1,2579,
93493638,16,0,195,1, 108431861,1,2558,1849,1,
935065,3639,16,0,197, 108442566,1855,1,2459,1004,
93511,2075,3640,16,0, 108451,2464,1021,1,2574,
9352165,1,1574,799,1, 108461837,1,2470,3850,16,
935371,3641,16,0,173, 108470,448,1,2700,3851,
93541,1775,3642,16,0, 1084816,0,448,1,2594,
9355165,1,76,3643,16, 108491868,1,2596,3852,16,
93560,173,1,1834,3644, 108500,448,1,75,3853,
935716,0,165,1,2337, 1085119,439,1,75,3854,
93583645,16,0,165,1, 108525,30,1,2644,1753,
935979,3646,16,0,173, 108531,2520,1758,1,2639,
93601,1335,3647,16,0, 108541765,1,2640,1770,1,
9361165,1,322,3648,16, 108552641,1775,1,2642,1780,
93620,173,1,85,3649, 108561,2643,1747,1,2535,
936316,0,173,1,1261, 108571785,1,2645,1791,1,
93643650,16,0,165,1, 108582646,1796,1,2648,1875,
936589,3651,16,0,173, 108591,2649,1802,1,2650,
93661,346,3652,16,0, 108601807,1,2651,1812,1,
9367173,1,97,3653,16, 108612652,1817,1,2653,1822,
93680,173,1,2106,3654, 108621,2654,1827,1,2655,
936916,0,165,1,102, 108631832,1,2657,3855,16,
93703655,16,0,173,1, 108640,437,1,2550,1843,
93711860,821,1,1803,787, 108651,2579,1861,1,2558,
93721,2364,827,1,1113, 108661849,1,2566,1855,1,
93733656,16,0,158,1, 108672459,1004,1,2464,1021,
9374112,3657,16,0,173, 108681,2574,1837,1,2470,
93751,1117,3658,16,0, 108693856,16,0,437,1,
9376165,1,1873,835,1, 108702700,3857,16,0,437,
93771876,3659,16,0,165, 108711,2594,1868,1,2596,
93781,372,3660,16,0, 108723858,16,0,437,1,
9379535,1,374,3661,16, 1087376,3859,19,560,1,
93800,537,1,124,3662, 1087476,3860,5,30,1,
938116,0,173,1,376, 108752644,1753,1,2520,1758,
93823663,16,0,539,1, 108761,2639,1765,1,2640,
9383378,3664,16,0,541, 108771770,1,2641,1775,1,
93841,2136,842,1,381, 108782642,1780,1,2643,1747,
93853665,16,0,173,1, 108791,2535,1785,1,2645,
9386525,3666,16,0,173, 108801791,1,2646,1796,1,
93871,137,3667,16,0, 108812648,1875,1,2649,1802,
9388173,1,1901,3668,16, 108821,2650,1807,1,2651,
93890,165,1,2655,3211, 108831812,1,2652,1817,1,
93901,2658,3669,16,0, 108842653,1822,1,2654,1827,
9391173,1,1153,3670,16, 108851,2655,1832,1,2657,
93920,165,1,151,3671, 108863861,16,0,558,1,
939316,0,173,1,1407, 108872550,1843,1,2579,1861,
93943672,16,0,165,1, 108881,2558,1849,1,2566,
93951659,3673,16,0,165, 108891855,1,2459,1004,1,
93961,2413,3674,16,0, 108902464,1021,1,2574,1837,
9397165,1,406,3675,16, 108911,2470,3862,16,0,
93980,173,1,1371,3676, 10892558,1,2700,3863,16,
939916,0,165,1,2105, 108930,558,1,2594,1868,
9400814,1,1657,894,1, 108941,2596,3864,16,0,
9401166,3677,16,0,173, 10895558,1,77,3865,19,
94021,1622,3678,16,0, 10896435,1,77,3866,5,
9403173,1,2683,3223,1, 1089730,1,2644,1753,1,
94041931,861,1,1933,3679, 108982520,1758,1,2639,1765,
940516,0,165,1,431, 108991,2640,1770,1,2641,
94063680,16,0,173,1, 109001775,1,2642,1780,1,
94071585,3681,16,0,173, 109012643,1747,1,2535,1785,
94081,182,3682,16,0, 109021,2645,1791,1,2646,
9409173,1,2694,3216,1, 109031796,1,2648,1875,1,
94101189,3683,16,0,165, 109042649,1802,1,2650,1807,
94111,1443,3684,16,0, 109051,2651,1812,1,2652,
9412165,1,1695,3685,16, 109061817,1,2653,1822,1,
94130,165,1,2198,3686, 109072654,1827,1,2655,1832,
941416,0,165,1,447, 109081,2657,3867,16,0,
94153687,16,0,173,1, 10909433,1,2550,1843,1,
94162458,876,1,2459,882, 109102579,1861,1,2558,1849,
94171,1958,3688,16,0, 109111,2566,1855,1,2459,
9418165,1,2462,889,1, 109121004,1,2464,1021,1,
94192714,3183,1,2464,899, 109132574,1837,1,2470,3868,
94201,2716,3189,1,2466, 1091416,0,433,1,2700,
94213200,1,459,3689,16, 109153869,16,0,433,1,
94220,173,1,2468,3690, 109162594,1868,1,2596,3870,
942316,0,340,1,462, 1091716,0,433,1,78,
94243691,16,0,173,1, 109183871,19,554,1,78,
9425199,3692,16,0,173, 109193872,5,30,1,2644,
94261,217,3693,16,0, 109201753,1,2520,1758,1,
9427173,1,2227,908,1, 109212639,1765,1,2640,1770,
94281225,3694,16,0,165, 109221,2641,1775,1,2642,
94291,1479,3695,16,0, 109231780,1,2643,1747,1,
9430165,1,1731,3696,16, 109242535,1785,1,2645,1791,
94310,173,1,1989,916, 109251,2646,1796,1,2648,
94321,1990,3697,16,0, 109261875,1,2649,1802,1,
9433165,1,236,3698,16, 109272650,1807,1,2651,1812,
94340,173,1,1756,3699, 109281,2652,1817,1,2653,
943516,0,165,1,93, 109291822,1,2654,1827,1,
94363700,19,626,1,93, 109302655,1832,1,2657,3873,
94373701,5,95,1,256, 1093116,0,552,1,2550,
94383702,16,0,624,1, 109321843,1,2579,1861,1,
94391261,3703,16,0,624, 109332558,1849,1,2566,1855,
94401,509,3704,16,0, 109341,2459,1004,1,2464,
9441624,1,1515,3705,16, 109351021,1,2574,1837,1,
94420,624,1,2021,718, 109362470,3874,16,0,552,
94431,1775,3706,16,0, 109371,2700,3875,16,0,
9444624,1,2029,725,1, 10938552,1,2594,1868,1,
94452030,731,1,2031,736, 109392596,3876,16,0,552,
94461,2032,741,1,2033, 109401,79,3877,19,551,
9447746,1,277,3707,16, 109411,79,3878,5,30,
94480,624,1,2035,752, 109421,2644,1753,1,2520,
94491,2037,757,1,2039, 109431758,1,2639,1765,1,
9450762,1,32,3708,16, 109442640,1770,1,2641,1775,
94510,624,1,2041,768, 109451,2642,1780,1,2643,
94521,2293,3709,16,0, 109461747,1,2535,1785,1,
9453624,1,2043,774,1, 109472645,1791,1,2646,1796,
94542045,779,1,41,3710, 109481,2648,1875,1,2649,
945516,0,624,1,1297, 109491802,1,2650,1807,1,
94563711,16,0,624,1, 109502651,1812,1,2652,1817,
945743,3712,16,0,624, 109511,2653,1822,1,2654,
94581,1803,787,1,1804, 109521827,1,2655,1832,1,
94593713,16,0,624,1, 109532657,3879,16,0,549,
9460299,3714,16,0,624, 109541,2550,1843,1,2579,
94611,52,3715,16,0, 109551861,1,2558,1849,1,
9462624,1,2318,3716,16, 109562566,1855,1,2459,1004,
94630,624,1,62,3717, 109571,2464,1021,1,2574,
946416,0,624,1,2075, 109581837,1,2470,3880,16,
94653718,16,0,624,1, 109590,549,1,2700,3881,
94661574,799,1,71,3719, 1096016,0,549,1,2594,
946716,0,624,1,76, 109611868,1,2596,3882,16,
94683720,16,0,624,1, 109620,549,1,80,3883,
94691834,3721,16,0,624, 1096319,426,1,80,3884,
94701,2337,3722,16,0, 109645,30,1,2644,1753,
9471624,1,79,3723,16, 109651,2520,1758,1,2639,
94720,624,1,1335,3724, 109661765,1,2640,1770,1,
947316,0,624,1,322, 109672641,1775,1,2642,1780,
94743725,16,0,624,1, 109681,2643,1747,1,2535,
947585,3726,16,0,624, 109691785,1,2645,1791,1,
94761,89,3727,16,0, 109702646,1796,1,2648,1875,
9477624,1,346,3728,16, 109711,2649,1802,1,2650,
94780,624,1,2105,814, 109721807,1,2651,1812,1,
94791,2106,3729,16,0, 109732652,1817,1,2653,1822,
9480624,1,97,3730,16, 109741,2654,1827,1,2655,
94810,624,1,1860,821, 109751832,1,2657,3885,16,
94821,2364,827,1,102, 109760,424,1,2550,1843,
94833731,16,0,624,1, 109771,2579,1861,1,2558,
9484112,3732,16,0,624, 109781849,1,2566,1855,1,
94851,1117,3733,16,0, 109792459,1004,1,2464,1021,
9486624,1,1873,835,1, 109801,2574,1837,1,2470,
94871876,3734,16,0,624, 109813886,16,0,424,1,
94881,124,3735,16,0, 109822700,3887,16,0,424,
9489624,1,2136,842,1, 109831,2594,1868,1,2596,
9490381,3736,16,0,624, 109843888,16,0,424,1,
94911,525,3737,16,0, 1098581,3889,19,413,1,
9492624,1,137,3738,16, 1098681,3890,5,30,1,
94930,624,1,1901,3739, 109872644,1753,1,2520,1758,
949416,0,624,1,2658, 109881,2639,1765,1,2640,
94953740,16,0,624,1, 109891770,1,2641,1775,1,
94961153,3741,16,0,624, 109902642,1780,1,2643,1747,
94971,151,3742,16,0, 109911,2535,1785,1,2645,
9498624,1,1407,3743,16, 109921791,1,2646,1796,1,
94990,624,1,1659,3744, 109932648,1875,1,2649,1802,
950016,0,624,1,2413, 109941,2650,1807,1,2651,
95013745,16,0,624,1, 109951812,1,2652,1817,1,
9502406,3746,16,0,624, 109962653,1822,1,2654,1827,
95031,1371,3747,16,0, 109971,2655,1832,1,2657,
9504624,1,166,3748,16, 109983891,16,0,411,1,
95050,624,1,1622,3749, 109992550,1843,1,2579,1861,
950616,0,624,1,1931, 110001,2558,1849,1,2566,
9507861,1,1933,3750,16, 110011855,1,2459,1004,1,
95080,624,1,431,3751, 110022464,1021,1,2574,1837,
950916,0,624,1,1585, 110031,2470,3892,16,0,
95103752,16,0,624,1, 11004411,1,2700,3893,16,
9511182,3753,16,0,624, 110050,411,1,2594,1868,
95121,1189,3754,16,0, 110061,2596,3894,16,0,
9513624,1,1443,3755,16, 11007411,1,82,3895,19,
95140,624,1,1695,3756, 11008758,1,82,3896,5,
951516,0,624,1,2198, 1100930,1,2644,1753,1,
95163757,16,0,624,1, 110102520,1758,1,2639,1765,
9517447,3758,16,0,624, 110111,2640,1770,1,2641,
95181,2458,876,1,2459, 110121775,1,2642,1780,1,
9519882,1,1958,3759,16, 110132643,1747,1,2535,1785,
95200,624,1,2462,889, 110141,2645,1791,1,2646,
95211,1657,894,1,2464, 110151796,1,2648,1875,1,
9522899,1,199,3760,16, 110162649,1802,1,2650,1807,
95230,624,1,459,3761, 110171,2651,1812,1,2652,
110181817,1,2653,1822,1,
110192654,1827,1,2655,1832,
110201,2657,3897,16,0,
11021756,1,2550,1843,1,
110222579,1861,1,2558,1849,
110231,2566,1855,1,2459,
110241004,1,2464,1021,1,
110252574,1837,1,2470,3898,
1102616,0,756,1,2700,
110273899,16,0,756,1,
110282594,1868,1,2596,3900,
1102916,0,756,1,83,
110303901,19,410,1,83,
110313902,5,30,1,2644,
110321753,1,2520,1758,1,
110332639,1765,1,2640,1770,
110341,2641,1775,1,2642,
110351780,1,2643,1747,1,
110362535,1785,1,2645,1791,
110371,2646,1796,1,2648,
110381875,1,2649,1802,1,
110392650,1807,1,2651,1812,
110401,2652,1817,1,2653,
110411822,1,2654,1827,1,
110422655,1832,1,2657,3903,
1104316,0,408,1,2550,
110441843,1,2579,1861,1,
110452558,1849,1,2566,1855,
110461,2459,1004,1,2464,
110471021,1,2574,1837,1,
110482470,3904,16,0,408,
110491,2700,3905,16,0,
11050408,1,2594,1868,1,
110512596,3906,16,0,408,
110521,84,3907,19,407,
110531,84,3908,5,30,
110541,2644,1753,1,2520,
110551758,1,2639,1765,1,
110562640,1770,1,2641,1775,
110571,2642,1780,1,2643,
110581747,1,2535,1785,1,
110592645,1791,1,2646,1796,
110601,2648,1875,1,2649,
110611802,1,2650,1807,1,
110622651,1812,1,2652,1817,
110631,2653,1822,1,2654,
110641827,1,2655,1832,1,
110652657,3909,16,0,405,
110661,2550,1843,1,2579,
110671861,1,2558,1849,1,
110682566,1855,1,2459,1004,
110691,2464,1021,1,2574,
110701837,1,2470,3910,16,
110710,405,1,2700,3911,
1107216,0,405,1,2594,
110731868,1,2596,3912,16,
110740,405,1,85,3913,
1107519,570,1,85,3914,
110765,30,1,2644,1753,
110771,2520,1758,1,2639,
110781765,1,2640,1770,1,
110792641,1775,1,2642,1780,
110801,2643,1747,1,2535,
110811785,1,2645,1791,1,
110822646,1796,1,2648,1875,
110831,2649,1802,1,2650,
110841807,1,2651,1812,1,
110852652,1817,1,2653,1822,
110861,2654,1827,1,2655,
110871832,1,2657,3915,16,
110880,568,1,2550,1843,
110891,2579,1861,1,2558,
110901849,1,2566,1855,1,
110912459,1004,1,2464,1021,
110921,2574,1837,1,2470,
110933916,16,0,568,1,
110942700,3917,16,0,568,
110951,2594,1868,1,2596,
110963918,16,0,568,1,
1109786,3919,19,442,1,
1109886,3920,5,30,1,
110992644,1753,1,2520,1758,
111001,2639,1765,1,2640,
111011770,1,2641,1775,1,
111022642,1780,1,2643,1747,
111031,2535,1785,1,2645,
111041791,1,2646,1796,1,
111052648,1875,1,2649,1802,
111061,2650,1807,1,2651,
111071812,1,2652,1817,1,
111082653,1822,1,2654,1827,
111091,2655,1832,1,2657,
111103921,16,0,440,1,
111112550,1843,1,2579,1861,
111121,2558,1849,1,2566,
111131855,1,2459,1004,1,
111142464,1021,1,2574,1837,
111151,2470,3922,16,0,
11116440,1,2700,3923,16,
111170,440,1,2594,1868,
111181,2596,3924,16,0,
11119440,1,87,3925,19,
11120548,1,87,3926,5,
1112130,1,2644,1753,1,
111222520,1758,1,2639,1765,
111231,2640,1770,1,2641,
111241775,1,2642,1780,1,
111252643,1747,1,2535,1785,
111261,2645,1791,1,2646,
111271796,1,2648,1875,1,
111282649,1802,1,2650,1807,
111291,2651,1812,1,2652,
111301817,1,2653,1822,1,
111312654,1827,1,2655,1832,
111321,2657,3927,16,0,
11133546,1,2550,1843,1,
111342579,1861,1,2558,1849,
111351,2566,1855,1,2459,
111361004,1,2464,1021,1,
111372574,1837,1,2470,3928,
1113816,0,546,1,2700,
111393929,16,0,546,1,
111402594,1868,1,2596,3930,
1114116,0,546,1,88,
111423931,19,404,1,88,
111433932,5,30,1,2644,
111441753,1,2520,1758,1,
111452639,1765,1,2640,1770,
111461,2641,1775,1,2642,
111471780,1,2643,1747,1,
111482535,1785,1,2645,1791,
111491,2646,1796,1,2648,
111501875,1,2649,1802,1,
111512650,1807,1,2651,1812,
111521,2652,1817,1,2653,
111531822,1,2654,1827,1,
111542655,1832,1,2657,3933,
1115516,0,402,1,2550,
111561843,1,2579,1861,1,
111572558,1849,1,2566,1855,
111581,2459,1004,1,2464,
111591021,1,2574,1837,1,
111602470,3934,16,0,402,
111611,2700,3935,16,0,
11162402,1,2594,1868,1,
111632596,3936,16,0,402,
111641,89,3937,19,398,
111651,89,3938,5,30,
111661,2644,1753,1,2520,
111671758,1,2639,1765,1,
111682640,1770,1,2641,1775,
111691,2642,1780,1,2643,
111701747,1,2535,1785,1,
111712645,1791,1,2646,1796,
111721,2648,1875,1,2649,
111731802,1,2650,1807,1,
111742651,1812,1,2652,1817,
111751,2653,1822,1,2654,
111761827,1,2655,1832,1,
111772657,3939,16,0,396,
111781,2550,1843,1,2579,
111791861,1,2558,1849,1,
111802566,1855,1,2459,1004,
111811,2464,1021,1,2574,
111821837,1,2470,3940,16,
111830,396,1,2700,3941,
1118416,0,396,1,2594,
111851868,1,2596,3942,16,
111860,396,1,90,3943,
1118719,401,1,90,3944,
111885,30,1,2644,1753,
111891,2520,1758,1,2639,
111901765,1,2640,1770,1,
111912641,1775,1,2642,1780,
111921,2643,1747,1,2535,
111931785,1,2645,1791,1,
111942646,1796,1,2648,1875,
111951,2649,1802,1,2650,
111961807,1,2651,1812,1,
111972652,1817,1,2653,1822,
111981,2654,1827,1,2655,
111991832,1,2657,3945,16,
112000,399,1,2550,1843,
112011,2579,1861,1,2558,
112021849,1,2566,1855,1,
112032459,1004,1,2464,1021,
112041,2574,1837,1,2470,
112053946,16,0,399,1,
112062700,3947,16,0,399,
112071,2594,1868,1,2596,
112083948,16,0,399,1,
1120991,3949,19,446,1,
1121091,3950,5,30,1,
112112644,1753,1,2520,1758,
112121,2639,1765,1,2640,
112131770,1,2641,1775,1,
112142642,1780,1,2643,1747,
112151,2535,1785,1,2645,
112161791,1,2646,1796,1,
112172648,1875,1,2649,1802,
112181,2650,1807,1,2651,
112191812,1,2652,1817,1,
112202653,1822,1,2654,1827,
112211,2655,1832,1,2657,
112223951,16,0,444,1,
112232550,1843,1,2579,1861,
112241,2558,1849,1,2566,
112251855,1,2459,1004,1,
112262464,1021,1,2574,1837,
112271,2470,3952,16,0,
11228444,1,2700,3953,16,
112290,444,1,2594,1868,
112301,2596,3954,16,0,
11231444,1,92,3955,19,
11232133,1,92,3956,5,
11233129,1,0,3957,16,
112340,314,1,1,2236,
112351,2,2242,1,3,
112362247,1,4,2252,1,
112375,2257,1,6,2262,
112381,7,2267,1,8,
112393958,16,0,131,1,
112401515,3959,16,0,184,
112411,2021,840,1,2022,
112423960,16,0,575,1,
11243256,3961,16,0,192,
112441,2526,3962,16,0,
11245300,1,2025,3963,16,
112460,579,1,18,3964,
1124716,0,138,1,2027,
112483965,16,0,583,1,
112492029,847,1,2030,853,
112501,2031,858,1,2032,
11251863,1,2033,868,1,
11252277,3966,16,0,192,
112531,2035,874,1,2037,
11254879,1,2541,3967,16,
112550,512,1,32,3968,
1125616,0,184,1,2041,
11257890,1,2293,3969,16,
112580,192,1,2043,896,
112591,2045,901,1,41,
112603970,16,0,192,1,
112611297,3971,16,0,184,
112621,43,3972,16,0,
11263192,1,46,3973,16,
112640,197,1,1804,3974,
1126516,0,184,1,299,
112663975,16,0,192,1,
1126752,3976,16,0,184,
112681,2818,3516,1,2819,
112693977,16,0,314,1,
112702318,3978,16,0,184,
112711,62,3979,16,0,
11272221,1,65,3980,16,
112730,223,1,2075,3981,
1127416,0,184,1,1574,
11275921,1,71,3982,16,
112760,192,1,1775,3983,
1127716,0,184,1,2837,
112783530,1,2838,3536,1,
112792337,3984,16,0,184,
112801,79,3985,16,0,
11281192,1,1335,3986,16,
112820,184,1,2511,3987,
1128316,0,477,1,322,
112843988,16,0,192,1,
1128576,3989,16,0,192,
112861,85,3990,16,0,
11287192,1,1261,3991,16,
112880,184,1,89,3992,
1128916,0,192,1,509,
112903993,16,0,192,1,
11291346,3994,16,0,192,
112921,2039,884,1,97,
112933995,16,0,192,1,
112942106,3996,16,0,184,
112951,102,3997,16,0,
11296192,1,1860,943,1,
112971803,909,1,2364,949,
112981,2779,3510,1,2782,
112993998,16,0,192,1,
11300112,3999,16,0,192,
113011,1117,4000,16,0,
11302184,1,1873,958,1,
113031876,4001,16,0,184,
113041,372,4002,16,0,
11305613,1,374,4003,16,
113060,615,1,124,4004,
1130716,0,192,1,376,
113084005,16,0,617,1,
11309378,4006,16,0,619,
113101,2136,965,1,381,
113114007,16,0,192,1,
11312525,4008,16,0,192,
113131,2807,3551,1,1834,
113144009,16,0,184,1,
11315137,4010,16,0,192,
113161,1901,4011,16,0,
11317184,1,1113,4012,16,
113180,176,1,1153,4013,
1131916,0,184,1,151,
113204014,16,0,192,1,
113211407,4015,16,0,184,
113221,1659,4016,16,0,
11323184,1,2413,4017,16,
113240,184,1,406,4018,
1132516,0,192,1,1371,
113264019,16,0,184,1,
113272105,936,1,166,4020,
1132816,0,192,1,2839,
113293541,1,2840,3546,1,
113301931,983,1,1933,4021,
1133116,0,184,1,431,
113324022,16,0,192,1,
113331585,4023,16,0,192,
113341,182,4024,16,0,
11335192,1,1189,4025,16,
113360,184,1,1443,4026,
1133716,0,184,1,1695,
113384027,16,0,184,1,
113392198,4028,16,0,184,
113401,447,4029,16,0,
11341192,1,2458,998,1,
113422459,1004,1,1958,4030,
1134316,0,184,1,2462,
113441011,1,1657,1016,1,
113452464,1021,1,2466,3525,
113461,459,4031,16,0,
11347192,1,2468,4032,16,
113480,376,1,462,4033,
1134916,0,192,1,199,
113504034,16,0,192,1,
11351217,4035,16,0,192,
113521,2227,1030,1,1622,
113534036,16,0,192,1,
113541225,4037,16,0,184,
113551,1479,4038,16,0,
11356184,1,1731,4039,16,
113570,192,1,1989,1038,
113581,1990,4040,16,0,
11359184,1,236,4041,16,
113600,192,1,2507,4042,
1136116,0,471,1,1756,
113624043,16,0,184,1,
1136393,4044,19,731,1,
1136493,4045,5,95,1,
11365256,4046,16,0,729,
113661,1261,4047,16,0,
11367729,1,509,4048,16,
113680,729,1,1515,4049,
1136916,0,729,1,2021,
11370840,1,1775,4050,16,
113710,729,1,2029,847,
113721,2030,853,1,2031,
11373858,1,2032,863,1,
113742033,868,1,277,4051,
1137516,0,729,1,2035,
11376874,1,2037,879,1,
113772039,884,1,32,4052,
1137816,0,729,1,2041,
11379890,1,2293,4053,16,
113800,729,1,2043,896,
113811,2045,901,1,41,
113824054,16,0,729,1,
113831297,4055,16,0,729,
113841,43,4056,16,0,
11385729,1,1803,909,1,
113861804,4057,16,0,729,
113871,299,4058,16,0,
11388729,1,52,4059,16,
113890,729,1,2318,4060,
1139016,0,729,1,62,
113914061,16,0,729,1,
113922075,4062,16,0,729,
113931,1574,921,1,71,
113944063,16,0,729,1,
1139576,4064,16,0,729,
113961,1834,4065,16,0,
11397729,1,2337,4066,16,
113980,729,1,79,4067,
1139916,0,729,1,1335,
114004068,16,0,729,1,
11401322,4069,16,0,729,
114021,85,4070,16,0,
11403729,1,89,4071,16,
114040,729,1,346,4072,
1140516,0,729,1,2105,
11406936,1,2106,4073,16,
114070,729,1,97,4074,
1140816,0,729,1,1860,
11409943,1,2364,949,1,
11410102,4075,16,0,729,
114111,2782,4076,16,0,
11412729,1,112,4077,16,
114130,729,1,1117,4078,
1141416,0,729,1,1873,
11415958,1,1876,4079,16,
114160,729,1,124,4080,
1141716,0,729,1,2136,
11418965,1,381,4081,16,
114190,729,1,525,4082,
1142016,0,729,1,137,
114214083,16,0,729,1,
114221901,4084,16,0,729,
114231,1153,4085,16,0,
11424729,1,151,4086,16,
114250,729,1,1407,4087,
1142616,0,729,1,1659,
114274088,16,0,729,1,
114282413,4089,16,0,729,
114291,406,4090,16,0,
11430729,1,1371,4091,16,
114310,729,1,166,4092,
1143216,0,729,1,1622,
114334093,16,0,729,1,
114341931,983,1,1933,4094,
1143516,0,729,1,431,
114364095,16,0,729,1,
114371585,4096,16,0,729,
114381,182,4097,16,0,
11439729,1,1189,4098,16,
114400,729,1,1443,4099,
1144116,0,729,1,1695,
114424100,16,0,729,1,
114432198,4101,16,0,729,
114441,447,4102,16,0,
11445729,1,2458,998,1,
114462459,1004,1,1958,4103,
1144716,0,729,1,2462,
114481011,1,1657,1016,1,
114492464,1021,1,199,4104,
1145016,0,729,1,459,
114514105,16,0,729,1,
11452462,4106,16,0,729,
114531,217,4107,16,0,
11454729,1,2227,1030,1,
114551225,4108,16,0,729,
114561,1479,4109,16,0,
11457729,1,1731,4110,16,
114580,729,1,1989,1038,
114591,1990,4111,16,0,
11460729,1,236,4112,16,
114610,729,1,1756,4113,
1146216,0,729,1,94,
114634114,19,728,1,94,
114644115,5,95,1,256,
114654116,16,0,726,1,
114661261,4117,16,0,726,
114671,509,4118,16,0,
11468726,1,1515,4119,16,
114690,726,1,2021,840,
114701,1775,4120,16,0,
11471726,1,2029,847,1,
114722030,853,1,2031,858,
114731,2032,863,1,2033,
11474868,1,277,4121,16,
114750,726,1,2035,874,
114761,2037,879,1,2039,
11477884,1,32,4122,16,
114780,726,1,2041,890,
114791,2293,4123,16,0,
11480726,1,2043,896,1,
114812045,901,1,41,4124,
1148216,0,726,1,1297,
114834125,16,0,726,1,
1148443,4126,16,0,726,
114851,1803,909,1,1804,
114864127,16,0,726,1,
11487299,4128,16,0,726,
114881,52,4129,16,0,
11489726,1,2318,4130,16,
114900,726,1,62,4131,
1149116,0,726,1,2075,
114924132,16,0,726,1,
114931574,921,1,71,4133,
1149416,0,726,1,76,
114954134,16,0,726,1,
114961834,4135,16,0,726,
114971,2337,4136,16,0,
11498726,1,79,4137,16,
114990,726,1,1335,4138,
1150016,0,726,1,322,
115014139,16,0,726,1,
1150285,4140,16,0,726,
115031,89,4141,16,0,
11504726,1,346,4142,16,
115050,726,1,2105,936,
115061,2106,4143,16,0,
11507726,1,97,4144,16,
115080,726,1,1860,943,
115091,2364,949,1,102,
115104145,16,0,726,1,
115112782,4146,16,0,726,
115121,112,4147,16,0,
11513726,1,1117,4148,16,
115140,726,1,1873,958,
115151,1876,4149,16,0,
11516726,1,124,4150,16,
115170,726,1,2136,965,
115181,381,4151,16,0,
11519726,1,525,4152,16,
115200,726,1,137,4153,
1152116,0,726,1,1901,
115224154,16,0,726,1,
115231153,4155,16,0,726,
115241,151,4156,16,0,
11525726,1,1407,4157,16,
115260,726,1,1659,4158,
1152716,0,726,1,2413,
115284159,16,0,726,1,
11529406,4160,16,0,726,
115301,1371,4161,16,0,
11531726,1,166,4162,16,
115320,726,1,1622,4163,
1153316,0,726,1,1931,
11534983,1,1933,4164,16,
115350,726,1,431,4165,
1153616,0,726,1,1585,
115374166,16,0,726,1,
11538182,4167,16,0,726,
115391,1189,4168,16,0,
11540726,1,1443,4169,16,
115410,726,1,1695,4170,
1154216,0,726,1,2198,
115434171,16,0,726,1,
11544447,4172,16,0,726,
115451,2458,998,1,2459,
115461004,1,1958,4173,16,
115470,726,1,2462,1011,
115481,1657,1016,1,2464,
115491021,1,199,4174,16,
115500,726,1,459,4175,
1155116,0,726,1,462,
115524176,16,0,726,1,
11553217,4177,16,0,726,
115541,2227,1030,1,1225,
115554178,16,0,726,1,
115561479,4179,16,0,726,
115571,1731,4180,16,0,
11558726,1,1989,1038,1,
115591990,4181,16,0,726,
115601,236,4182,16,0,
11561726,1,1756,4183,16,
115620,726,1,95,4184,
1156319,725,1,95,4185,
115645,95,1,256,4186,
1156516,0,723,1,1261,
115664187,16,0,723,1,
11567509,4188,16,0,723,
115681,1515,4189,16,0,
11569723,1,2021,840,1,
115701775,4190,16,0,723,
115711,2029,847,1,2030,
11572853,1,2031,858,1,
115732032,863,1,2033,868,
115741,277,4191,16,0,
11575723,1,2035,874,1,
115762037,879,1,2039,884,
115771,32,4192,16,0,
11578723,1,2041,890,1,
115792293,4193,16,0,723,
115801,2043,896,1,2045,
11581901,1,41,4194,16,
115820,723,1,1297,4195,
1158316,0,723,1,43,
115844196,16,0,723,1,
115851803,909,1,1804,4197,
1158616,0,723,1,299,
115874198,16,0,723,1,
1158852,4199,16,0,723,
115891,2318,4200,16,0,
11590723,1,62,4201,16,
115910,723,1,2075,4202,
1159216,0,723,1,1574,
11593921,1,71,4203,16,
115940,723,1,76,4204,
1159516,0,723,1,1834,
115964205,16,0,723,1,
115972337,4206,16,0,723,
115981,79,4207,16,0,
11599723,1,1335,4208,16,
116000,723,1,322,4209,
1160116,0,723,1,85,
116024210,16,0,723,1,
1160389,4211,16,0,723,
116041,346,4212,16,0,
11605723,1,2105,936,1,
116062106,4213,16,0,723,
116071,97,4214,16,0,
11608723,1,1860,943,1,
116092364,949,1,102,4215,
1161016,0,723,1,2782,
116114216,16,0,723,1,
11612112,4217,16,0,723,
116131,1117,4218,16,0,
11614723,1,1873,958,1,
116151876,4219,16,0,723,
116161,124,4220,16,0,
11617723,1,2136,965,1,
11618381,4221,16,0,723,
116191,525,4222,16,0,
11620723,1,137,4223,16,
116210,723,1,1901,4224,
1162216,0,723,1,1153,
116234225,16,0,723,1,
11624151,4226,16,0,723,
116251,1407,4227,16,0,
11626723,1,1659,4228,16,
116270,723,1,2413,4229,
1162816,0,723,1,406,
116294230,16,0,723,1,
116301371,4231,16,0,723,
116311,166,4232,16,0,
11632723,1,1622,4233,16,
116330,723,1,1931,983,
116341,1933,4234,16,0,
11635723,1,431,4235,16,
116360,723,1,1585,4236,
1163716,0,723,1,182,
116384237,16,0,723,1,
116391189,4238,16,0,723,
116401,1443,4239,16,0,
11641723,1,1695,4240,16,
116420,723,1,2198,4241,
1164316,0,723,1,447,
116444242,16,0,723,1,
116452458,998,1,2459,1004,
116461,1958,4243,16,0,
11647723,1,2462,1011,1,
116481657,1016,1,2464,1021,
116491,199,4244,16,0,
11650723,1,459,4245,16,
116510,723,1,462,4246,
1165216,0,723,1,217,
116534247,16,0,723,1,
116542227,1030,1,1225,4248,
1165516,0,723,1,1479,
116564249,16,0,723,1,
116571731,4250,16,0,723,
116581,1989,1038,1,1990,
116594251,16,0,723,1,
11660236,4252,16,0,723,
116611,1756,4253,16,0,
11662723,1,96,4254,19,
11663103,1,96,4255,5,
116641,1,0,4256,16,
116650,104,1,97,4257,
1166619,172,1,97,4258,
116675,1,1,0,4259,
1166816,0,170,1,98,
116694260,19,213,1,98,
116704261,5,2,1,0,
116714262,16,0,211,1,
116722819,4263,16,0,366,
116731,99,4264,19,210,
116741,99,4265,5,2,
116751,0,4266,16,0,
11676208,1,2819,4267,16,
116770,365,1,100,4268,
1167819,292,1,100,4269,
116795,2,1,0,4270,
1168016,0,775,1,2819,
116814271,16,0,290,1,
11682101,4272,19,781,1,
11683101,4273,5,4,1,
116840,4274,16,0,782,
116851,2830,4275,16,0,
11686779,1,2819,4276,16,
116870,782,1,2760,4277,
1168816,0,779,1,102,
116894278,19,698,1,102,
116904279,5,2,1,2470,
116914280,16,0,696,1,
116922657,4281,16,0,719,
116931,103,4282,19,157,
116941,103,4283,5,4,
116951,2596,4284,16,0,
11696155,1,2470,4285,16,
116970,674,1,2700,4286,
1169816,0,155,1,2657,
116994287,16,0,674,1,
11700104,4288,19,154,1,
11701104,4289,5,4,1,
117022596,4290,16,0,152,
117031,2470,4291,16,0,
11704177,1,2700,4292,16,
117050,152,1,2657,4293,
1170616,0,177,1,105,
117074294,19,657,1,105,
117084295,5,4,1,2596,
117094296,16,0,655,1,
117102470,4297,16,0,672,
117111,2700,4298,16,0,
11712655,1,2657,4299,16,
117130,672,1,106,4300,
1171419,175,1,106,4301,
117155,4,1,2596,4302,
1171616,0,654,1,2470,
117174303,16,0,173,1,
117182700,4304,16,0,654,
117191,2657,4305,16,0,
11720173,1,107,4306,19,
11721670,1,107,4307,5,
117224,1,2596,4308,16,
117230,742,1,2470,4309,
1172416,0,668,1,2700,
117254310,16,0,742,1,
117262657,4311,16,0,668,
117271,108,4312,19,169,
117281,108,4313,5,4,
117291,2596,4314,16,0,
11730650,1,2470,4315,16,
117310,167,1,2700,4316,
1173216,0,650,1,2657,
117334317,16,0,167,1,
11734109,4318,19,741,1,
11735109,4319,5,4,1,
117362596,4320,16,0,739,
117371,2470,4321,16,0,
11738751,1,2700,4322,16,
117390,739,1,2657,4323,
1174016,0,751,1,110,
117414324,19,648,1,110,
117424325,5,4,1,2596,
117434326,16,0,646,1,
117442470,4327,16,0,663,
117451,2700,4328,16,0,
11746646,1,2657,4329,16,
117470,663,1,111,4330,
1174819,141,1,111,4331,
117495,3,1,2766,4332,
1175016,0,791,1,2581,
117514333,16,0,355,1,
1175210,4334,16,0,139,
117531,112,4335,19,557,
117541,112,4336,5,1,
117551,2568,4337,16,0,
11756555,1,113,4338,19,
11757745,1,113,4339,5,
117581,1,2560,4340,16,
117590,743,1,114,4341,
1176019,529,1,114,4342,
117615,1,1,2552,4343,
1176216,0,527,1,115,
117634344,19,251,1,115,
117644345,5,1,1,2537,
117654346,16,0,249,1,
11766116,4347,19,502,1,
11767116,4348,5,1,1,
117682522,4349,16,0,500,
117691,117,4350,19,486,
117701,117,4351,5,1,
117711,2506,4352,16,0,
11772484,1,118,4353,19,
11773160,1,118,4354,5,
1177417,1,0,4355,16,
117750,794,1,2581,4356,
1177616,0,372,1,2075,
117774357,16,0,753,1,
117782337,4358,16,0,753,
117791,2819,4359,16,0,
11780794,1,2413,4360,16,
117810,753,1,10,4361,
1178216,0,372,1,1901,
117834362,16,0,753,1,
117842198,4363,16,0,753,
117851,21,4364,16,0,
11786158,1,2106,4365,16,
117870,753,1,2766,4366,
1178816,0,372,1,1804,
117894367,16,0,753,1,
117901990,4368,16,0,753,
117911,32,4369,16,0,
11792753,1,1958,4370,16,
117930,753,1,1775,4371,
1179416,0,753,1,119,
117954372,19,474,1,119,
117964373,5,2,1,2568,
117974374,16,0,671,1,
117982506,4375,16,0,472,
117991,120,4376,19,480,
118001,120,4377,5,5,
118011,2510,4378,16,0,
11802478,1,2522,4379,16,
118030,491,1,2514,4380,
1180416,0,483,1,2537,
118054381,16,0,509,1,
118062560,4382,16,0,537,
118071,121,4383,19,309,
118081,121,4384,5,3,
118091,2552,4385,16,0,
11810737,1,2525,4386,16,
118110,307,1,2529,4387,
1181216,0,499,1,122,
118134388,19,636,1,122,
118144389,5,2,1,2544,
118154390,16,0,637,1,
118162540,4391,16,0,634,
118171,123,4392,19,130,
118181,123,4393,5,18,
118191,0,4394,16,0,
11820128,1,2581,4395,16,
118210,137,1,2075,4396,
1182216,0,137,1,2337,
118234397,16,0,137,1,
118242819,4398,16,0,128,
118251,2413,4399,16,0,
11826137,1,10,4400,16,
118270,137,1,2198,4401,
1182816,0,137,1,1901,
118294402,16,0,137,1,
1183052,4403,16,0,219,
118311,21,4404,16,0,
11832137,1,2106,4405,16,
118330,137,1,2766,4406,
1183416,0,137,1,1804,
118354407,16,0,137,1,
118361990,4408,16,0,137,
118371,32,4409,16,0,
11838137,1,1958,4410,16,
118390,137,1,1775,4411,
1184016,0,137,1,124,
118414412,19,765,1,124,
118424413,5,4,1,2596,
118434414,16,0,763,1,
118442470,4415,16,0,763,
118451,2700,4416,16,0,
11846763,1,2657,4417,16,
118470,763,1,125,4418,
1184819,567,1,125,4419,
118495,4,1,2596,4420,
1185016,0,565,1,2470,
118514421,16,0,565,1,
118522700,4422,16,0,565,
118531,2657,4423,16,0,
11854565,1,126,4424,19,
11855666,1,126,4425,5,
118564,1,2596,4426,16,
118570,664,1,2470,4427,
1185816,0,664,1,2700,
118594428,16,0,664,1,
118602657,4429,16,0,664,
118611,127,4430,19,535,
118621,127,4431,5,4,
118631,2596,4432,16,0,
11864533,1,2470,4433,16,
118650,533,1,2700,4434,
1186616,0,533,1,2657,
118674435,16,0,533,1,
11868128,4436,19,524,1,
11869128,4437,5,4,1,
118702596,4438,16,0,522,
118711,2470,4439,16,0,
11872522,1,2700,4440,16,
118730,522,1,2657,4441,
1187416,0,522,1,129,
118754442,19,632,1,129,
118764443,5,4,1,2596,
118774444,16,0,630,1,
118782470,4445,16,0,630,
118791,2700,4446,16,0,
11880630,1,2657,4447,16,
118810,630,1,130,4448,
1188219,778,1,130,4449,
118835,4,1,2596,4450,
1188416,0,776,1,2470,
118854451,16,0,776,1,
118862700,4452,16,0,776,
118871,2657,4453,16,0,
11888776,1,131,4454,19,
11889768,1,131,4455,5,
118904,1,2596,4456,16,
118910,766,1,2470,4457,
1189216,0,766,1,2700,
118934458,16,0,766,1,
118942657,4459,16,0,766,
118951,132,4460,19,328,
118961,132,4461,5,21,
118971,2518,4462,16,0,
11898699,1,2075,4463,16,
118990,584,1,2548,4464,
1190016,0,736,1,2337,
119014465,16,0,584,1,
119022413,4466,16,0,584,
119031,2564,4467,16,0,
11904542,1,2556,4468,16,
119050,532,1,2592,4469,
1190616,0,695,1,1901,
119074470,16,0,584,1,
119082198,4471,16,0,584,
119091,2533,4472,16,0,
11910504,1,2777,4473,16,
119110,326,1,2572,4474,
1191216,0,675,1,2106,
119134475,16,0,584,1,
119142577,4476,16,0,681,
119151,1804,4477,16,0,
11916584,1,1990,4478,16,
119170,584,1,31,4479,
1191816,0,371,1,32,
119194480,16,0,584,1,
119201958,4481,16,0,584,
119211,1775,4482,16,0,
11922584,1,133,4483,19,
11923337,1,133,4484,5,
119241,1,32,4485,16,
119250,335,1,134,4486,
1192619,286,1,134,4487,
119275,11,1,2075,4488,
1192816,0,682,1,2337,
119294489,16,0,293,1,
119302413,4490,16,0,505,
119311,1901,4491,16,0,
11932427,1,2198,4492,16,
119330,354,1,2106,4493,
1193416,0,715,1,1804,
119354494,16,0,317,1,
119361990,4495,16,0,572,
119371,32,4496,16,0,
11938367,1,1958,4497,16,
119390,515,1,1775,4498,
1194016,0,284,1,135,
119414499,19,688,1,135,
119424500,5,11,1,2075,
119434501,16,0,686,1,
119442337,4502,16,0,686,
119451,2413,4503,16,0,
11946686,1,1901,4504,16,
119470,686,1,2198,4505,
1194816,0,686,1,2106,
119494506,16,0,686,1,
119501804,4507,16,0,686,
119511,1990,4508,16,0,
11952686,1,32,4509,16,
119530,686,1,1958,4510,
1195416,0,686,1,1775,
119554511,16,0,686,1,
11956136,4512,19,748,1,
11957136,4513,5,11,1,
119582075,4514,16,0,746,
119591,2337,4515,16,0,
11960746,1,2413,4516,16,
119610,746,1,1901,4517,
1196216,0,746,1,2198,
119634518,16,0,746,1,
119642106,4519,16,0,746,
119651,1804,4520,16,0,
11966746,1,1990,4521,16,
119670,746,1,32,4522,
1196816,0,746,1,1958,
119694523,16,0,746,1,
119701775,4524,16,0,746,
119711,137,4525,19,180,
119721,137,4526,5,31,
119731,1901,4527,16,0,
11974752,1,1479,4528,16,
119750,638,1,2075,4529,
1197616,0,752,1,1695,
119774530,16,0,217,1,
119781756,4531,16,0,207,
119791,2413,4532,16,0,
11980752,1,2198,4533,16,
119810,752,1,1876,4534,
1198216,0,771,1,1659,
119834535,16,0,207,1,
119841443,4536,16,0,600,
119851,1117,4537,16,0,
11986178,1,1990,4538,16,
119870,752,1,1189,4539,
1198816,0,267,1,1775,
119894540,16,0,752,1,
1199032,4541,16,0,752,
119911,2106,4542,16,0,
11992752,1,1515,4543,16,
119930,684,1,2337,4544,
1199416,0,752,1,52,
119954545,16,0,700,1,
119961804,4546,16,0,752,
119971,1261,4547,16,0,
11998331,1,1153,4548,16,
119990,274,1,1225,4549,
1200016,0,303,1,1335,
120014550,16,0,497,1,
120021933,4551,16,0,640,
120031,1834,4552,16,0,
12004347,1,1297,4553,16,
120050,359,1,1407,4554,
1200616,0,667,1,2318,
120074555,16,0,207,1,
120081958,4556,16,0,752,
120091,1371,4557,16,0,
12010488,1,138,4558,19,
12011609,1,138,4559,5,
1201211,1,2075,4560,16,
120130,607,1,2337,4561,
1201416,0,607,1,2413,
120154562,16,0,607,1,
120161901,4563,16,0,607,
120171,2198,4564,16,0,
12018607,1,2106,4565,16,
120190,607,1,1804,4566,
1202016,0,607,1,1990,
120214567,16,0,607,1,
1202232,4568,16,0,607,
120231,1958,4569,16,0,
12024607,1,1775,4570,16,
120250,607,1,139,4571,
1202619,605,1,139,4572,
120275,11,1,2075,4573,
1202816,0,603,1,2337,
120294574,16,0,603,1,
120302413,4575,16,0,603,
120311,1901,4576,16,0,
12032603,1,2198,4577,16,
120330,603,1,2106,4578,
1203416,0,603,1,1804,
120354579,16,0,603,1,
120361990,4580,16,0,603,
120371,32,4581,16,0,
12038603,1,1958,4582,16,
120390,603,1,1775,4583,
1204016,0,603,1,140,
120414584,19,679,1,140,
120424585,5,11,1,2075,
120434586,16,0,677,1,
120442337,4587,16,0,677,
120451,2413,4588,16,0,
12046677,1,1901,4589,16,
120470,677,1,2198,4590,
1204816,0,677,1,2106,
120494591,16,0,677,1,
120501804,4592,16,0,677,
120511,1990,4593,16,0,
12052677,1,32,4594,16,
120530,677,1,1958,4595,
1205416,0,677,1,1775,
120554596,16,0,677,1,
12056141,4597,19,599,1,
12057141,4598,5,11,1,
120582075,4599,16,0,597,
120591,2337,4600,16,0,
12060597,1,2413,4601,16,
120610,597,1,1901,4602,
1206216,0,597,1,2198,
120634603,16,0,597,1,
120642106,4604,16,0,597,
120651,1804,4605,16,0,
12066597,1,1990,4606,16,
120670,597,1,32,4607,
1206816,0,597,1,1958,
120694608,16,0,597,1,
120701775,4609,16,0,597,
120711,142,4610,19,596,
120721,142,4611,5,11,
120731,2075,4612,16,0,
12074594,1,2337,4613,16,
120750,594,1,2413,4614,
1207616,0,594,1,1901,
120774615,16,0,594,1,
120782198,4616,16,0,594,
120791,2106,4617,16,0,
12080594,1,1804,4618,16,
120810,594,1,1990,4619,
1208216,0,594,1,32,
120834620,16,0,594,1,
120841958,4621,16,0,594,
120851,1775,4622,16,0,
12086594,1,143,4623,19,
12087593,1,143,4624,5,
1208811,1,2075,4625,16,
120890,591,1,2337,4626,
1209016,0,591,1,2413,
120914627,16,0,591,1,
120921901,4628,16,0,591,
120931,2198,4629,16,0,
12094591,1,2106,4630,16,
120950,591,1,1804,4631,
1209616,0,591,1,1990,
120974632,16,0,591,1,
1209832,4633,16,0,591,
120991,1958,4634,16,0,
12100591,1,1775,4635,16,
121010,591,1,144,4636,
1210219,590,1,144,4637,
121035,11,1,2075,4638,
1210416,0,588,1,2337,
121054639,16,0,588,1,
121062413,4640,16,0,588,
121071,1901,4641,16,0,
12108588,1,2198,4642,16,
121090,588,1,2106,4643,
1211016,0,588,1,1804,
121114644,16,0,588,1,
121121990,4645,16,0,588,
121131,32,4646,16,0,
12114588,1,1958,4647,16,
121150,588,1,1775,4648,
1211616,0,588,1,145,
121174649,19,587,1,145,
121184650,5,11,1,2075,
121194651,16,0,585,1,
121202337,4652,16,0,585,
121211,2413,4653,16,0,
12122585,1,1901,4654,16,
121230,585,1,2198,4655,
1212416,0,585,1,2106,
121254656,16,0,585,1,
121261804,4657,16,0,585,
121271,1990,4658,16,0,
12128585,1,32,4659,16,
121290,585,1,1958,4660,
1213016,0,585,1,1775,
121314661,16,0,585,1,
12132146,4662,19,150,1,
12133146,4663,5,3,1,
121341756,4664,16,0,316,
121351,2318,4665,16,0,
12136330,1,1659,4666,16,
121370,148,1,147,4667,
1213819,626,1,147,4668,
121395,68,1,1901,4669,
1214016,0,624,1,1479,
121414670,16,0,624,1,
12142112,4671,16,0,624,
121431,2293,4672,16,0,
12144624,1,1804,4673,16,
121450,624,1,431,4674,
1214616,0,624,1,1443,
121474675,16,0,624,1,
121481756,4676,16,0,624,
121491,124,4677,16,0,
12150624,1,525,4678,16,
121510,624,1,236,4679,
1215216,0,624,1,346,
121534680,16,0,624,1,
121541876,4681,16,0,624,
121551,1659,4682,16,0,
12156624,1,1225,4683,16,
121570,624,1,1117,4684,
1215816,0,624,1,137,
121594685,16,0,624,1,
121602318,4686,16,0,624,
121611,1775,4687,16,0,
12162624,1,32,4688,16,
121630,624,1,1407,4689,
1216416,0,624,1,2782,
121654690,16,0,624,1,
12166256,4691,16,0,624,
121671,459,4692,16,0,
12168624,1,406,4693,16,
121690,624,1,41,4694,
1217016,0,624,1,151,
121714695,16,0,624,1,
1217243,4696,16,0,624,
121731,1585,4697,16,0,
12174624,1,1990,4698,16,
121750,624,1,2337,4699,
1217616,0,624,1,509,
121774700,16,0,624,1,
1217852,4701,16,0,624,
121791,381,4702,16,0,
12180624,1,447,4703,16,
121810,624,1,166,4704,
952416,0,624,1,462, 1218216,0,624,1,462,
95253762,16,0,624,1, 121834705,16,0,624,1,
9526217,3763,16,0,624, 12184277,4706,16,0,624,
95271,2227,908,1,1225, 121851,1695,4707,16,0,
95283764,16,0,624,1, 12186624,1,62,4708,16,
95291479,3765,16,0,624, 121870,692,1,1153,4709,
95301,1731,3766,16,0, 1218816,0,624,1,2106,
9531624,1,1989,916,1, 121894710,16,0,624,1,
95321990,3767,16,0,624, 121901335,4711,16,0,624,
95331,236,3768,16,0, 121911,71,4712,16,0,
9534624,1,1756,3769,16, 12192624,1,182,4713,16,
95350,624,1,94,3770, 121930,624,1,76,4714,
953619,623,1,94,3771, 1219416,0,624,1,79,
95375,95,1,256,3772, 121954715,16,0,624,1,
953816,0,621,1,1261, 121961933,4716,16,0,624,
95393773,16,0,621,1, 121971,299,4717,16,0,
9540509,3774,16,0,621, 12198624,1,85,4718,16,
95411,1515,3775,16,0, 121990,624,1,1515,4719,
9542621,1,2021,718,1, 1220016,0,624,1,2198,
95431775,3776,16,0,621, 122014720,16,0,624,1,
95441,2029,725,1,2030, 1220289,4721,16,0,624,
9545731,1,2031,736,1, 122031,1834,4722,16,0,
95462032,741,1,2033,746, 12204624,1,1622,4723,16,
95471,277,3777,16,0, 122050,624,1,2413,4724,
9548621,1,2035,752,1, 1220616,0,624,1,2075,
95492037,757,1,2039,762, 122074725,16,0,624,1,
95501,32,3778,16,0, 122081731,4726,16,0,624,
9551621,1,2041,768,1, 122091,97,4727,16,0,
95522293,3779,16,0,621, 12210624,1,1297,4728,16,
95531,2043,774,1,2045, 122110,624,1,1189,4729,
9554779,1,41,3780,16, 1221216,0,624,1,102,
95550,621,1,1297,3781, 122134730,16,0,624,1,
955616,0,621,1,43, 122141261,4731,16,0,624,
95573782,16,0,621,1, 122151,322,4732,16,0,
95581803,787,1,1804,3783, 12216624,1,1958,4733,16,
955916,0,621,1,299, 122170,624,1,199,4734,
95603784,16,0,621,1, 1221816,0,624,1,1371,
956152,3785,16,0,621, 122194735,16,0,624,1,
95621,2318,3786,16,0, 12220217,4736,16,0,624,
9563621,1,62,3787,16, 122211,148,4737,19,710,
95640,621,1,2075,3788, 122221,148,4738,5,2,
956516,0,621,1,1574, 122231,459,4739,16,0,
9566799,1,71,3789,16, 12224708,1,41,4740,16,
95670,621,1,76,3790, 122250,783,1,149,4741,
956816,0,621,1,1834, 1222619,714,1,149,4742,
95693791,16,0,621,1, 122275,3,1,462,4743,
95702337,3792,16,0,621, 1222816,0,712,1,459,
95711,79,3793,16,0, 122294744,16,0,735,1,
9572621,1,1335,3794,16, 1223041,4745,16,0,735,
95730,621,1,322,3795, 122311,150,4746,19,4747,
957416,0,621,1,85, 122324,36,69,0,120,
95753796,16,0,621,1, 122330,112,0,114,0,
957689,3797,16,0,621, 12234101,0,115,0,115,
95771,346,3798,16,0, 122350,105,0,111,0,
9578621,1,2105,814,1, 12236110,0,65,0,114,
95792106,3799,16,0,621, 122370,103,0,117,0,
95801,97,3800,16,0, 12238109,0,101,0,110,
9581621,1,1860,821,1, 122390,116,0,1,150,
95822364,827,1,102,3801, 122404742,1,151,4748,19,
958316,0,621,1,112, 12241622,1,151,4749,5,
95843802,16,0,621,1, 1224268,1,1901,4750,16,
95851117,3803,16,0,621, 122430,620,1,1479,4751,
95861,1873,835,1,1876, 1224416,0,620,1,112,
95873804,16,0,621,1, 122454752,16,0,620,1,
9588124,3805,16,0,621, 122462293,4753,16,0,620,
95891,2136,842,1,381, 122471,1804,4754,16,0,
95903806,16,0,621,1, 12248620,1,431,4755,16,
9591525,3807,16,0,621, 122490,620,1,1443,4756,
95921,137,3808,16,0, 1225016,0,620,1,1756,
9593621,1,1901,3809,16, 122514757,16,0,620,1,
95940,621,1,2658,3810, 12252124,4758,16,0,620,
959516,0,621,1,1153, 122531,525,4759,16,0,
95963811,16,0,621,1, 12254620,1,236,4760,16,
9597151,3812,16,0,621, 122550,620,1,346,4761,
95981,1407,3813,16,0, 1225616,0,620,1,1876,
9599621,1,1659,3814,16, 122574762,16,0,620,1,
96000,621,1,2413,3815, 122581659,4763,16,0,620,
960116,0,621,1,406, 122591,1225,4764,16,0,
96023816,16,0,621,1, 12260620,1,1117,4765,16,
96031371,3817,16,0,621, 122610,620,1,137,4766,
96041,166,3818,16,0, 1226216,0,620,1,2318,
9605621,1,1622,3819,16, 122634767,16,0,620,1,
96060,621,1,1931,861, 122641775,4768,16,0,620,
96071,1933,3820,16,0, 122651,32,4769,16,0,
9608621,1,431,3821,16, 12266620,1,1407,4770,16,
96090,621,1,1585,3822, 122670,620,1,2782,4771,
961016,0,621,1,182, 1226816,0,620,1,256,
96113823,16,0,621,1, 122694772,16,0,620,1,
96121189,3824,16,0,621, 12270459,4773,16,0,620,
96131,1443,3825,16,0, 122711,406,4774,16,0,
9614621,1,1695,3826,16, 12272620,1,41,4775,16,
96150,621,1,2198,3827, 122730,620,1,151,4776,
961616,0,621,1,447, 1227416,0,620,1,43,
96173828,16,0,621,1, 122754777,16,0,620,1,
96182458,876,1,2459,882, 122761585,4778,16,0,620,
96191,1958,3829,16,0, 122771,1990,4779,16,0,
9620621,1,2462,889,1, 12278620,1,2337,4780,16,
96211657,894,1,2464,899, 122790,620,1,509,4781,
96221,199,3830,16,0, 1228016,0,620,1,52,
9623621,1,459,3831,16, 122814782,16,0,620,1,
96240,621,1,462,3832, 12282381,4783,16,0,620,
962516,0,621,1,217, 122831,447,4784,16,0,
96263833,16,0,621,1, 12284620,1,166,4785,16,
96272227,908,1,1225,3834, 122850,620,1,462,4786,
962816,0,621,1,1479, 1228616,0,620,1,277,
96293835,16,0,621,1, 122874787,16,0,620,1,
96301731,3836,16,0,621, 122881695,4788,16,0,620,
96311,1989,916,1,1990, 122891,62,4789,16,0,
96323837,16,0,621,1, 12290693,1,1153,4790,16,
9633236,3838,16,0,621, 122910,620,1,2106,4791,
96341,1756,3839,16,0, 1229216,0,620,1,1335,
9635621,1,95,3840,19, 122934792,16,0,620,1,
9636620,1,95,3841,5, 1229471,4793,16,0,620,
963795,1,256,3842,16, 122951,182,4794,16,0,
96380,618,1,1261,3843, 12296620,1,76,4795,16,
963916,0,618,1,509, 122970,620,1,79,4796,
96403844,16,0,618,1, 1229816,0,620,1,1933,
96411515,3845,16,0,618, 122994797,16,0,620,1,
96421,2021,718,1,1775, 12300299,4798,16,0,620,
96433846,16,0,618,1, 123011,85,4799,16,0,
96442029,725,1,2030,731, 12302620,1,1515,4800,16,
96451,2031,736,1,2032, 123030,620,1,2198,4801,
9646741,1,2033,746,1, 1230416,0,620,1,89,
9647277,3847,16,0,618, 123054802,16,0,620,1,
96481,2035,752,1,2037, 123061834,4803,16,0,620,
9649757,1,2039,762,1, 123071,1622,4804,16,0,
965032,3848,16,0,618, 12308620,1,2413,4805,16,
96511,2041,768,1,2293, 123090,620,1,2075,4806,
96523849,16,0,618,1, 1231016,0,620,1,1731,
96532043,774,1,2045,779, 123114807,16,0,620,1,
96541,41,3850,16,0, 1231297,4808,16,0,620,
9655618,1,1297,3851,16, 123131,1297,4809,16,0,
96560,618,1,43,3852, 12314620,1,1189,4810,16,
965716,0,618,1,1803, 123150,620,1,102,4811,
9658787,1,1804,3853,16, 1231616,0,620,1,1261,
96590,618,1,299,3854, 123174812,16,0,620,1,
966016,0,618,1,52, 12318322,4813,16,0,620,
96613855,16,0,618,1, 123191,1958,4814,16,0,
96622318,3856,16,0,618, 12320620,1,199,4815,16,
96631,62,3857,16,0, 123210,620,1,1371,4816,
9664618,1,2075,3858,16, 1232216,0,620,1,217,
96650,618,1,1574,799, 123234817,16,0,620,1,
96661,71,3859,16,0, 12324152,4818,19,4819,4,
9667618,1,76,3860,16, 1232528,86,0,101,0,
96680,618,1,1834,3861, 1232699,0,116,0,111,
966916,0,618,1,2337, 123270,114,0,67,0,
96703862,16,0,618,1,
967179,3863,16,0,618,
96721,1335,3864,16,0,
9673618,1,322,3865,16,
96740,618,1,85,3866,
967516,0,618,1,89,
96763867,16,0,618,1,
9677346,3868,16,0,618,
96781,2105,814,1,2106,
96793869,16,0,618,1,
968097,3870,16,0,618,
96811,1860,821,1,2364,
9682827,1,102,3871,16,
96830,618,1,112,3872,
968416,0,618,1,1117,
96853873,16,0,618,1,
96861873,835,1,1876,3874,
968716,0,618,1,124,
96883875,16,0,618,1,
96892136,842,1,381,3876,
969016,0,618,1,525,
96913877,16,0,618,1,
9692137,3878,16,0,618,
96931,1901,3879,16,0,
9694618,1,2658,3880,16,
96950,618,1,1153,3881,
969616,0,618,1,151,
96973882,16,0,618,1,
96981407,3883,16,0,618,
96991,1659,3884,16,0,
9700618,1,2413,3885,16,
97010,618,1,406,3886,
970216,0,618,1,1371,
97033887,16,0,618,1,
9704166,3888,16,0,618,
97051,1622,3889,16,0,
9706618,1,1931,861,1,
97071933,3890,16,0,618,
97081,431,3891,16,0,
9709618,1,1585,3892,16,
97100,618,1,182,3893,
971116,0,618,1,1189,
97123894,16,0,618,1,
97131443,3895,16,0,618,
97141,1695,3896,16,0,
9715618,1,2198,3897,16,
97160,618,1,447,3898,
971716,0,618,1,2458,
9718876,1,2459,882,1,
97191958,3899,16,0,618,
97201,2462,889,1,1657,
9721894,1,2464,899,1,
9722199,3900,16,0,618,
97231,459,3901,16,0,
9724618,1,462,3902,16,
97250,618,1,217,3903,
972616,0,618,1,2227,
9727908,1,1225,3904,16,
97280,618,1,1479,3905,
972916,0,618,1,1731,
97303906,16,0,618,1,
97311989,916,1,1990,3907,
973216,0,618,1,236,
97333908,16,0,618,1,
97341756,3909,16,0,618,
97351,96,3910,19,103,
97361,96,3911,5,1,
97371,0,3912,16,0,
9738104,1,97,3913,19,
9739611,1,97,3914,5,
97401,1,0,3915,16,
97410,609,1,98,3916,
974219,636,1,98,3917,
97435,2,1,0,3918,
974416,0,638,1,2695,
97453919,16,0,634,1,
974699,3920,19,633,1,
974799,3921,5,2,1,
97480,3922,16,0,637,
97491,2695,3923,16,0,
9750631,1,100,3924,19,
9751296,1,100,3925,5,
97522,1,0,3926,16,
97530,557,1,2695,3927,
975416,0,294,1,101,
97553928,19,561,1,101,
97563929,5,4,1,0,
97573930,16,0,641,1,
97582695,3931,16,0,641,
97591,2706,3932,16,0,
9760559,1,2636,3933,16,
97610,559,1,102,3934,
976219,591,1,102,3935,
97635,2,1,2470,3936,
976416,0,664,1,2561,
97653937,16,0,589,1,
9766103,3938,19,463,1,
9767103,3939,5,4,1,
97682597,3940,16,0,558,
97691,2521,3941,16,0,
9770558,1,2470,3942,16,
97710,461,1,2561,3943,
977216,0,461,1,104,
97733944,19,141,1,104,
97743945,5,3,1,2642,
97753946,16,0,569,1,
97762506,3947,16,0,317,
97771,10,3948,16,0,
9778139,1,105,3949,19,
9779151,1,105,3950,5,
978017,1,0,3951,16,
97810,254,1,2075,3952,
978216,0,648,1,2337,
97833953,16,0,648,1,
97842413,3954,16,0,648,
97851,10,3955,16,0,
9786336,1,2198,3956,16,
97870,648,1,1901,3957,
978816,0,648,1,2642,
97893958,16,0,336,1,
979021,3959,16,0,149,
97911,2106,3960,16,0,
9792648,1,2506,3961,16,
97930,336,1,1804,3962,
979416,0,648,1,1990,
97953963,16,0,648,1,
97962695,3964,16,0,254,
97971,32,3965,16,0,
9798648,1,1958,3966,16,
97990,648,1,1775,3967,
980016,0,648,1,106,
98013968,19,130,1,106,
98023969,5,18,1,0,
98033970,16,0,128,1,
98042642,3971,16,0,137,
98051,2075,3972,16,0,
9806137,1,2337,3973,16,
98070,137,1,2413,3974,
980816,0,137,1,10,
98093975,16,0,137,1,
98102198,3976,16,0,137,
98111,1901,3977,16,0,
9812137,1,52,3978,16,
98130,193,1,21,3979,
981416,0,137,1,2106,
98153980,16,0,137,1,
98162506,3981,16,0,137,
98171,1804,3982,16,0,
9818137,1,1990,3983,16,
98190,137,1,2695,3984,
982016,0,128,1,32,
98213985,16,0,137,1,
98221958,3986,16,0,137,
98231,1775,3987,16,0,
9824137,1,107,3988,19,
9825658,1,107,3989,5,
98264,1,2597,3990,16,
98270,656,1,2521,3991,
982816,0,656,1,2470,
98293992,16,0,656,1,
98302561,3993,16,0,656,
98311,108,3994,19,335,
98321,108,3995,5,14,
98331,2517,3996,16,0,
9834437,1,2075,3997,16,
98350,506,1,2337,3998,
983616,0,506,1,2413,
98373999,16,0,506,1,
98381901,4000,16,0,506,
98391,2198,4001,16,0,
9840506,1,2106,4002,16,
98410,506,1,2653,4003,
984216,0,571,1,1804,
98434004,16,0,506,1,
98441990,4005,16,0,506,
98451,31,4006,16,0,
9846333,1,32,4007,16,
98470,506,1,1958,4008,
984816,0,506,1,1775,
98494009,16,0,506,1,
9850109,4010,19,302,1,
9851109,4011,5,1,1,
985232,4012,16,0,300,
98531,110,4013,19,261,
98541,110,4014,5,11,
98551,2075,4015,16,0,
9856577,1,2337,4016,16,
98570,265,1,2413,4017,
985816,0,445,1,1901,
98594018,16,0,391,1,
98602198,4019,16,0,319,
98611,2106,4020,16,0,
9862607,1,1804,4021,16,
98630,284,1,1990,4022,
986416,0,494,1,32,
98654023,16,0,329,1,
98661958,4024,16,0,450,
98671,1775,4025,16,0,
9868259,1,111,4026,19,
9869583,1,111,4027,5,
987011,1,2075,4028,16,
98710,581,1,2337,4029,
987216,0,581,1,2413,
98734030,16,0,581,1,
98741901,4031,16,0,581,
98751,2198,4032,16,0,
9876581,1,2106,4033,16,
98770,581,1,1804,4034,
987816,0,581,1,1990,
98794035,16,0,581,1,
988032,4036,16,0,581,
98811,1958,4037,16,0,
9882581,1,1775,4038,16,
98830,581,1,112,4039,
988419,645,1,112,4040,
98855,11,1,2075,4041,
988616,0,643,1,2337,
98874042,16,0,643,1,
98882413,4043,16,0,643,
98891,1901,4044,16,0,
9890643,1,2198,4045,16,
98910,643,1,2106,4046,
989216,0,643,1,1804,
98934047,16,0,643,1,
98941990,4048,16,0,643,
98951,32,4049,16,0,
9896643,1,1958,4050,16,
98970,643,1,1775,4051,
989816,0,643,1,113,
98994052,19,161,1,113,
99004053,5,31,1,1901,
99014054,16,0,647,1,
99021479,4055,16,0,551,
99031,2075,4056,16,0,
9904647,1,1695,4057,16,
99050,189,1,1756,4058,
990616,0,188,1,2413,
99074059,16,0,647,1,
99082198,4060,16,0,647,
99091,1876,4061,16,0,
9910661,1,1659,4062,16,
99110,188,1,1443,4063,
991216,0,522,1,1117,
99134064,16,0,159,1,
99141990,4065,16,0,647,
99151,1189,4066,16,0,
9916240,1,1775,4067,16,
99170,647,1,32,4068,
991816,0,647,1,2106,
99194069,16,0,647,1,
99201515,4070,16,0,579,
99211,2337,4071,16,0,
9922647,1,52,4072,16,
99230,592,1,1804,4073,
992416,0,647,1,1261,
99254074,16,0,298,1,
99261153,4075,16,0,247,
99271,1225,4076,16,0,
9928274,1,1335,4077,16,
99290,443,1,1933,4078,
993016,0,553,1,1834,
99314079,16,0,312,1,
99321297,4080,16,0,323,
99331,1407,4081,16,0,
9934568,1,2318,4082,16,
99350,188,1,1958,4083,
993616,0,647,1,1371,
99374084,16,0,438,1,
9938114,4085,19,531,1,
9939114,4086,5,11,1,
99402075,4087,16,0,529,
99411,2337,4088,16,0,
9942529,1,2413,4089,16,
99430,529,1,1901,4090,
994416,0,529,1,2198,
99454091,16,0,529,1,
99462106,4092,16,0,529,
99471,1804,4093,16,0,
9948529,1,1990,4094,16,
99490,529,1,32,4095,
995016,0,529,1,1958,
99514096,16,0,529,1,
99521775,4097,16,0,529,
99531,115,4098,19,527,
99541,115,4099,5,11,
99551,2075,4100,16,0,
9956525,1,2337,4101,16,
99570,525,1,2413,4102,
995816,0,525,1,1901,
99594103,16,0,525,1,
99602198,4104,16,0,525,
99611,2106,4105,16,0,
9962525,1,1804,4106,16,
99630,525,1,1990,4107,
996416,0,525,1,32,
99654108,16,0,525,1,
99661958,4109,16,0,525,
99671,1775,4110,16,0,
9968525,1,116,4111,19,
9969575,1,116,4112,5,
997011,1,2075,4113,16,
99710,573,1,2337,4114,
997216,0,573,1,2413,
99734115,16,0,573,1,
99741901,4116,16,0,573,
99751,2198,4117,16,0,
9976573,1,2106,4118,16,
99770,573,1,1804,4119,
997816,0,573,1,1990,
99794120,16,0,573,1,
998032,4121,16,0,573,
99811,1958,4122,16,0,
9982573,1,1775,4123,16,
99830,573,1,117,4124,
998419,521,1,117,4125,
99855,11,1,2075,4126,
998616,0,519,1,2337,
99874127,16,0,519,1,
99882413,4128,16,0,519,
99891,1901,4129,16,0,
9990519,1,2198,4130,16,
99910,519,1,2106,4131,
999216,0,519,1,1804,
99934132,16,0,519,1,
99941990,4133,16,0,519,
99951,32,4134,16,0,
9996519,1,1958,4135,16,
99970,519,1,1775,4136,
999816,0,519,1,118,
99994137,19,518,1,118,
100004138,5,11,1,2075,
100014139,16,0,516,1,
100022337,4140,16,0,516,
100031,2413,4141,16,0,
10004516,1,1901,4142,16,
100050,516,1,2198,4143,
1000616,0,516,1,2106,
100074144,16,0,516,1,
100081804,4145,16,0,516,
100091,1990,4146,16,0,
10010516,1,32,4147,16,
100110,516,1,1958,4148,
1001216,0,516,1,1775,
100134149,16,0,516,1,
10014119,4150,19,515,1,
10015119,4151,5,11,1,
100162075,4152,16,0,513,
100171,2337,4153,16,0,
10018513,1,2413,4154,16,
100190,513,1,1901,4155,
1002016,0,513,1,2198,
100214156,16,0,513,1,
100222106,4157,16,0,513,
100231,1804,4158,16,0,
10024513,1,1990,4159,16,
100250,513,1,32,4160,
1002616,0,513,1,1958,
100274161,16,0,513,1,
100281775,4162,16,0,513,
100291,120,4163,19,512,
100301,120,4164,5,11,
100311,2075,4165,16,0,
10032510,1,2337,4166,16,
100330,510,1,2413,4167,
1003416,0,510,1,1901,
100354168,16,0,510,1,
100362198,4169,16,0,510,
100371,2106,4170,16,0,
10038510,1,1804,4171,16,
100390,510,1,1990,4172,
1004016,0,510,1,32,
100414173,16,0,510,1,
100421958,4174,16,0,510,
100431,1775,4175,16,0,
10044510,1,121,4176,19,
10045509,1,121,4177,5,
1004611,1,2075,4178,16,
100470,507,1,2337,4179,
1004816,0,507,1,2413,
100494180,16,0,507,1,
100501901,4181,16,0,507,
100511,2198,4182,16,0,
10052507,1,2106,4183,16,
100530,507,1,1804,4184,
1005416,0,507,1,1990,
100554185,16,0,507,1,
1005632,4186,16,0,507,
100571,1958,4187,16,0,
10058507,1,1775,4188,16,
100590,507,1,122,4189,
1006019,147,1,122,4190,
100615,3,1,1756,4191,
1006216,0,283,1,2318,
100634192,16,0,297,1,
100641659,4193,16,0,145,
100651,123,4194,19,548,
100661,123,4195,5,68,
100671,1901,4196,16,0,
10068546,1,1479,4197,16,
100690,546,1,112,4198,
1007016,0,546,1,2293,
100714199,16,0,546,1,
100721804,4200,16,0,546,
100731,431,4201,16,0,
10074546,1,1443,4202,16,
100750,546,1,1756,4203,
1007616,0,546,1,124,
100774204,16,0,546,1,
10078525,4205,16,0,546,
100791,236,4206,16,0,
10080546,1,346,4207,16,
100810,546,1,1876,4208,
1008216,0,546,1,1659,
100834209,16,0,546,1,
100841225,4210,16,0,546,
100851,1117,4211,16,0,
10086546,1,137,4212,16,
100870,546,1,2318,4213,
1008816,0,546,1,1775,
100894214,16,0,546,1,
1009032,4215,16,0,546,
100911,1407,4216,16,0,
10092546,1,256,4217,16,
100930,546,1,459,4218,
1009416,0,546,1,406,
100954219,16,0,546,1,
1009641,4220,16,0,546,
100971,2658,4221,16,0,
10098546,1,43,4222,16,
100990,546,1,1585,4223,
1010016,0,546,1,1990,
101014224,16,0,546,1,
101022337,4225,16,0,546,
101031,509,4226,16,0,
10104546,1,52,4227,16,
101050,546,1,151,4228,
1010616,0,546,1,447,
101074229,16,0,546,1,
10108166,4230,16,0,546,
101091,462,4231,16,0,
10110546,1,277,4232,16,
101110,546,1,1695,4233,
1011216,0,546,1,62,
101134234,16,0,586,1,
101141153,4235,16,0,546,
101151,381,4236,16,0,
10116546,1,2106,4237,16,
101170,546,1,1335,4238,
1011816,0,546,1,71,
101194239,16,0,546,1,
10120182,4240,16,0,546,
101211,76,4241,16,0,
10122546,1,79,4242,16,
101230,546,1,1933,4243,
1012416,0,546,1,299,
101254244,16,0,546,1,
1012685,4245,16,0,546,
101271,1515,4246,16,0,
10128546,1,2198,4247,16,
101290,546,1,89,4248,
1013016,0,546,1,1834,
101314249,16,0,546,1,
101321622,4250,16,0,546,
101331,2413,4251,16,0,
10134546,1,2075,4252,16,
101350,546,1,1731,4253,
1013616,0,546,1,97,
101374254,16,0,546,1,
101381297,4255,16,0,546,
101391,1189,4256,16,0,
10140546,1,102,4257,16,
101410,546,1,1261,4258,
1014216,0,546,1,322,
101434259,16,0,546,1,
101441958,4260,16,0,546,
101451,199,4261,16,0,
10146546,1,1371,4262,16,
101470,546,1,217,4263,
1014816,0,546,1,124,
101494264,19,602,1,124,
101504265,5,2,1,459,
101514266,16,0,600,1,
1015241,4267,16,0,665,
101531,125,4268,19,606,
101541,125,4269,5,3,
101551,462,4270,16,0,
10156604,1,459,4271,16,
101570,630,1,41,4272,
1015816,0,630,1,126,
101594273,19,4274,4,36,
1016069,0,120,0,112,
101610,114,0,101,0,
10162115,0,115,0,105,
101630,111,0,110,0,
1016465,0,114,0,103,
101650,117,0,109,0,
10166101,0,110,0,116,
101670,1,126,4269,1,
10168127,4275,19,544,1,
10169127,4276,5,68,1,
101701901,4277,16,0,542,
101711,1479,4278,16,0,
10172542,1,112,4279,16,
101730,542,1,2293,4280,
1017416,0,542,1,1804,
101754281,16,0,542,1,
10176431,4282,16,0,542,
101771,1443,4283,16,0,
10178542,1,1756,4284,16,
101790,542,1,124,4285,
1018016,0,542,1,525,
101814286,16,0,542,1,
10182236,4287,16,0,542,
101831,346,4288,16,0,
10184542,1,1876,4289,16,
101850,542,1,1659,4290,
1018616,0,542,1,1225,
101874291,16,0,542,1,
101881117,4292,16,0,542,
101891,137,4293,16,0,
10190542,1,2318,4294,16,
101910,542,1,1775,4295,
1019216,0,542,1,32,
101934296,16,0,542,1,
101941407,4297,16,0,542,
101951,256,4298,16,0,
10196542,1,459,4299,16,
101970,542,1,406,4300,
1019816,0,542,1,41,
101994301,16,0,542,1,
102002658,4302,16,0,542,
102011,43,4303,16,0,
10202542,1,1585,4304,16,
102030,542,1,1990,4305,
1020416,0,542,1,2337,
102054306,16,0,542,1,
10206509,4307,16,0,542,
102071,52,4308,16,0,
10208542,1,151,4309,16,
102090,542,1,447,4310,
1021016,0,542,1,166,
102114311,16,0,542,1,
10212462,4312,16,0,542,
102131,277,4313,16,0,
10214542,1,1695,4314,16,
102150,542,1,62,4315,
1021616,0,587,1,1153,
102174316,16,0,542,1,
10218381,4317,16,0,542,
102191,2106,4318,16,0,
10220542,1,1335,4319,16,
102210,542,1,71,4320,
1022216,0,542,1,182,
102234321,16,0,542,1,
1022476,4322,16,0,542,
102251,79,4323,16,0,
10226542,1,1933,4324,16,
102270,542,1,299,4325,
1022816,0,542,1,85,
102294326,16,0,542,1,
102301515,4327,16,0,542,
102311,2198,4328,16,0,
10232542,1,89,4329,16,
102330,542,1,1834,4330,
1023416,0,542,1,1622,
102354331,16,0,542,1,
102362413,4332,16,0,542,
102371,2075,4333,16,0,
10238542,1,1731,4334,16,
102390,542,1,97,4335,
1024016,0,542,1,1297,
102414336,16,0,542,1,
102421189,4337,16,0,542,
102431,102,4338,16,0,
10244542,1,1261,4339,16,
102450,542,1,322,4340,
1024616,0,542,1,1958,
102474341,16,0,542,1,
10248199,4342,16,0,542,
102491,1371,4343,16,0,
10250542,1,217,4344,16,
102510,542,1,128,4345,
1025219,4346,4,28,86,
102530,101,0,99,0,
10254116,0,111,0,114,
102550,67,0,111,0,
10256110,0,115,0,116,
102570,97,0,110,0,
10258116,0,1,128,4276,
102591,129,4347,19,4348,
102604,32,82,0,111,
102610,116,0,97,0,
10262116,0,105,0,111,
102630,110,0,67,0,
10264111,0,110,0,115, 12328111,0,110,0,115,
102650,116,0,97,0, 123290,116,0,97,0,
10266110,0,116,0,1, 12330110,0,116,0,1,
10267129,4276,1,130,4349, 12331152,4749,1,153,4820,
1026819,4350,4,24,76, 1233219,4821,4,32,82,
102690,105,0,115,0, 123330,111,0,116,0,
10270116,0,67,0,111, 1233497,0,116,0,105,
102710,110,0,115,0, 123350,111,0,110,0,
10272116,0,97,0,110,
102730,116,0,1,130,
102744276,1,131,4351,19,
10275169,1,131,4352,5,
1027667,1,1901,4353,16,
102770,585,1,1479,4354,
1027816,0,533,1,112,
102794355,16,0,249,1,
102802293,4356,16,0,273,
102811,1804,4357,16,0,
10282585,1,431,4358,16,
102830,580,1,1443,4359,
1028416,0,468,1,1756,
102854360,16,0,673,1,
10286124,4361,16,0,258,
102871,525,4362,16,0,
10288305,1,236,4363,16,
102890,341,1,346,4364,
1029016,0,496,1,1876,
102914365,16,0,318,1,
102921659,4366,16,0,673,
102931,1225,4367,16,0,
10294248,1,1117,4368,16,
102950,219,1,137,4369,
1029616,0,272,1,2318,
102974370,16,0,673,1,
102981775,4371,16,0,585,
102991,32,4372,16,0,
10300585,1,1407,4373,16,
103010,487,1,256,4374,
1030216,0,395,1,459,
103034375,16,0,167,1,
10304406,4376,16,0,562,
103051,41,4377,16,0,
10306167,1,2658,4378,16,
103070,659,1,43,4379,
1030816,0,640,1,1990,
103094380,16,0,585,1,
103102337,4381,16,0,585,
103111,509,4382,16,0,
10312655,1,52,4383,16,
103130,594,1,151,4384,
1031416,0,282,1,447,
103154385,16,0,305,1,
10316166,4386,16,0,293,
103171,462,4387,16,0,
10318167,1,277,4388,16,
103190,434,1,1695,4389,
1032016,0,270,1,1261,
103214390,16,0,281,1,
103221153,4391,16,0,174,
103231,381,4392,16,0,
10324550,1,2106,4393,16,
103250,585,1,1335,4394,
1032616,0,326,1,71,
103274395,16,0,203,1,
10328182,4396,16,0,305,
103291,76,4397,16,0,
10330549,1,79,4398,16,
103310,218,1,1933,4399,
1033216,0,407,1,299,
103334400,16,0,444,1,
1033485,4401,16,0,457,
103351,1515,4402,16,0,
10336556,1,2198,4403,16,
103370,585,1,89,4404,
1033816,0,227,1,1834,
103394405,16,0,292,1,
103401622,4406,16,0,654,
103411,2413,4407,16,0,
10342585,1,2075,4408,16,
103430,585,1,1731,4409,
1034416,0,250,1,97,
103454410,16,0,411,1,
103461297,4411,16,0,328,
103471,1189,4412,16,0,
10348217,1,102,4413,16,
103490,238,1,1585,4414,
1035016,0,663,1,322,
103514415,16,0,458,1,
103521958,4416,16,0,585,
103531,199,4417,16,0,
10354316,1,1371,4418,16,
103550,396,1,217,4419,
1035616,0,325,1,132,
103574420,19,4421,4,36,
1035867,0,111,0,110, 1233667,0,111,0,110,
103590,115,0,116,0, 123370,115,0,116,0,
1036097,0,110,0,116, 1233897,0,110,0,116,
103610,69,0,120,0, 123390,1,153,4749,1,
10362112,0,114,0,101, 12340154,4822,19,4823,4,
103630,115,0,115,0, 1234124,76,0,105,0,
10364105,0,111,0,110, 12342115,0,116,0,67,
103650,1,132,4352,1, 123430,111,0,110,0,
10366133,4422,19,4423,4, 12344115,0,116,0,97,
1036730,73,0,100,0, 123450,110,0,116,0,
10368101,0,110,0,116, 123461,154,4749,1,155,
103690,69,0,120,0, 123474824,19,188,1,155,
10370112,0,114,0,101, 123484825,5,67,1,1901,
103710,115,0,115,0, 123494826,16,0,690,1,
10372105,0,111,0,110, 123501479,4827,16,0,611,
103730,1,133,4352,1, 123511,112,4828,16,0,
10374134,4424,19,4425,4, 12352276,1,2293,4829,16,
1037536,73,0,100,0, 123530,302,1,1804,4830,
10376101,0,110,0,116, 1235416,0,690,1,431,
103770,68,0,111,0, 123554831,16,0,685,1,
10378116,0,69,0,120, 123561443,4832,16,0,538,
103790,112,0,114,0, 123571,1756,4833,16,0,
10380101,0,115,0,115, 12358793,1,124,4834,16,
103810,105,0,111,0, 123590,283,1,525,4835,
10382110,0,1,134,4352, 1236016,0,340,1,236,
103831,135,4426,19,4427, 123614836,16,0,377,1,
103844,44,70,0,117, 12362346,4837,16,0,574,
103850,110,0,99,0, 123631,1876,4838,16,0,
10386116,0,105,0,111, 12364353,1,1659,4839,16,
103870,110,0,67,0, 123650,793,1,1225,4840,
1038897,0,108,0,108, 1236616,0,275,1,1117,
103890,69,0,120,0, 123674841,16,0,245,1,
10390112,0,114,0,101, 12368137,4842,16,0,301,
103910,115,0,115,0, 123691,2318,4843,16,0,
10392105,0,111,0,110, 12370793,1,1775,4844,16,
103930,1,135,4352,1, 123710,690,1,32,4845,
10394136,4428,19,4429,4, 1237216,0,690,1,1407,
1039532,66,0,105,0, 123734846,16,0,561,1,
10396110,0,97,0,114, 123742782,4847,16,0,256,
103970,121,0,69,0, 123751,256,4848,16,0,
12376431,1,459,4849,16,
123770,186,1,406,4850,
1237816,0,649,1,41,
123794851,16,0,186,1,
12380151,4852,16,0,315,
123811,43,4853,16,0,
12382738,1,1990,4854,16,
123830,690,1,2337,4855,
1238416,0,690,1,509,
123854856,16,0,762,1,
1238652,4857,16,0,702,
123871,381,4858,16,0,
12388629,1,447,4859,16,
123890,340,1,166,4860,
1239016,0,329,1,462,
123914861,16,0,186,1,
12392277,4862,16,0,476,
123931,1695,4863,16,0,
12394298,1,1261,4864,16,
123950,313,1,1153,4865,
1239616,0,193,1,2106,
123974866,16,0,690,1,
123981335,4867,16,0,362,
123991,71,4868,16,0,
12400229,1,182,4869,16,
124010,340,1,76,4870,
1240216,0,627,1,79,
124034871,16,0,244,1,
124041933,4872,16,0,443,
124051,299,4873,16,0,
12406503,1,85,4874,16,
124070,526,1,1515,4875,
1240816,0,644,1,2198,
124094876,16,0,690,1,
1241089,4877,16,0,257,
124111,1834,4878,16,0,
12412325,1,1622,4879,16,
124130,761,1,2413,4880,
1241416,0,690,1,2075,
124154881,16,0,690,1,
124161731,4882,16,0,277,
124171,97,4883,16,0,
12418447,1,1297,4884,16,
124190,364,1,1189,4885,
1242016,0,243,1,102,
124214886,16,0,265,1,
124221585,4887,16,0,773,
124231,322,4888,16,0,
12424530,1,1958,4889,16,
124250,690,1,199,4890,
1242616,0,351,1,1371,
124274891,16,0,432,1,
12428217,4892,16,0,361,
124291,156,4893,19,4894,
124304,36,67,0,111,
124310,110,0,115,0,
12432116,0,97,0,110,
124330,116,0,69,0,
10398120,0,112,0,114, 12434120,0,112,0,114,
103990,101,0,115,0, 124350,101,0,115,0,
10400115,0,105,0,111, 12436115,0,105,0,111,
104010,110,0,1,136, 124370,110,0,1,156,
104024352,1,137,4430,19, 124384825,1,157,4895,19,
104034431,4,30,85,0, 124394896,4,30,73,0,
10404110,0,97,0,114, 12440100,0,101,0,110,
104050,121,0,69,0, 124410,116,0,69,0,
10406120,0,112,0,114, 12442120,0,112,0,114,
104070,101,0,115,0, 124430,101,0,115,0,
10408115,0,105,0,111, 12444115,0,105,0,111,
104090,110,0,1,137, 124450,110,0,1,157,
104104352,1,138,4432,19, 124464825,1,158,4897,19,
104114433,4,36,84,0, 124474898,4,36,73,0,
10412121,0,112,0,101, 12448100,0,101,0,110,
104130,99,0,97,0, 124490,116,0,68,0,
10414115,0,116,0,69, 12450111,0,116,0,69,
104150,120,0,112,0, 124510,120,0,112,0,
10416114,0,101,0,115, 12452114,0,101,0,115,
104170,115,0,105,0, 124530,115,0,105,0,
10418111,0,110,0,1, 12454111,0,110,0,1,
10419138,4352,1,139,4434, 12455158,4825,1,159,4899,
1042019,4435,4,42,80, 1245619,4900,4,44,70,
104210,97,0,114,0, 124570,117,0,110,0,
10422101,0,110,0,116, 1245899,0,116,0,105,
104230,104,0,101,0, 124590,111,0,110,0,
10424115,0,105,0,115, 1246067,0,97,0,108,
124610,108,0,69,0,
12462120,0,112,0,114,
124630,101,0,115,0,
12464115,0,105,0,111,
124650,110,0,1,159,
124664825,1,160,4901,19,
124674902,4,32,66,0,
12468105,0,110,0,97,
124690,114,0,121,0,
1247069,0,120,0,112,
124710,114,0,101,0,
12472115,0,115,0,105,
124730,111,0,110,0,
124741,160,4825,1,161,
124754903,19,4904,4,30,
1247685,0,110,0,97,
124770,114,0,121,0,
1247869,0,120,0,112,
124790,114,0,101,0,
12480115,0,115,0,105,
124810,111,0,110,0,
124821,161,4825,1,162,
124834905,19,4906,4,36,
1248484,0,121,0,112,
124850,101,0,99,0,
1248697,0,115,0,116,
104250,69,0,120,0, 124870,69,0,120,0,
10426112,0,114,0,101, 12488112,0,114,0,101,
104270,115,0,115,0, 124890,115,0,115,0,
10428105,0,111,0,110, 12490105,0,111,0,110,
104290,1,139,4352,1, 124910,1,162,4825,1,
10430140,4436,19,4437,4, 12492163,4907,19,4908,4,
1043156,73,0,110,0, 1249342,80,0,97,0,
12494114,0,101,0,110,
124950,116,0,104,0,
12496101,0,115,0,105,
124970,115,0,69,0,
12498120,0,112,0,114,
124990,101,0,115,0,
12500115,0,105,0,111,
125010,110,0,1,163,
125024825,1,164,4909,19,
125034910,4,56,73,0,
12504110,0,99,0,114,
125050,101,0,109,0,
12506101,0,110,0,116,
125070,68,0,101,0,
1043299,0,114,0,101, 1250899,0,114,0,101,
104330,109,0,101,0, 125090,109,0,101,0,
10434110,0,116,0,68, 12510110,0,116,0,69,
104350,101,0,99,0, 125110,120,0,112,0,
10436114,0,101,0,109, 12512114,0,101,0,115,
104370,101,0,110,0, 125130,115,0,105,0,
10438116,0,69,0,120, 12514111,0,110,0,1,
104390,112,0,114,0, 12515164,4825,1,166,4911,
10440101,0,115,0,115, 1251619,822,1,166,4255,
104410,105,0,111,0, 125171,167,4912,19,832,
10442110,0,1,140,4352, 125181,167,4255,1,168,
104431,142,4438,19,683, 125194913,19,3549,1,168,
104441,142,3911,1,143, 125204258,1,169,4914,19,
104454439,19,705,1,143, 125213539,1,169,4258,1,
104463911,1,144,4440,19, 12522170,4915,19,3544,1,
104473192,1,144,3914,1, 12523170,4258,1,171,4916,
10448145,4441,19,3187,1, 1252419,3534,1,171,4258,
10449145,3914,1,146,4442, 125251,172,4917,19,3520,
1045019,3198,1,146,3914, 125261,172,4261,1,173,
104511,147,4443,19,3209, 125274918,19,3554,1,173,
104521,147,3914,1,148, 125284261,1,174,4919,19,
104534444,19,3220,1,148, 125293514,1,174,4265,1,
104543917,1,149,4445,19, 12530175,4920,19,3528,1,
104553226,1,149,3917,1, 12531175,4265,1,176,4921,
10456150,4446,19,3214,1, 1253219,805,1,176,4269,
10457150,3921,1,151,4447, 125331,177,4922,19,816,
1045819,3204,1,151,3921, 125341,177,4269,1,178,
104591,152,4448,19,689, 125354923,19,811,1,178,
104601,152,3925,1,153, 125364273,1,179,4924,19,
104614449,19,710,1,153, 12537827,1,179,4273,1,
104623925,1,154,4450,19, 12538180,4925,19,1835,1,
10463695,1,154,3929,1, 12539180,4279,1,181,4926,
10464155,4451,19,700,1, 1254019,1799,1,181,4279,
10465155,3929,1,156,4452, 125411,182,4927,19,1830,
1046619,1636,1,156,3935, 125421,182,4279,1,183,
104671,157,4453,19,1631, 125434928,19,1794,1,183,
104681,157,3935,1,158, 125444279,1,184,4929,19,
104694454,19,1622,1,158, 125451825,1,184,4279,1,
104703939,1,159,4455,19, 12546185,4930,19,1756,1,
104711680,1,159,3945,1, 12547185,4279,1,186,4931,
10472160,4456,19,1657,1, 1254819,1820,1,186,4279,
10473160,3945,1,161,4457, 125491,187,4932,19,1751,
1047419,1117,1,161,3950, 125501,187,4279,1,188,
104751,162,4458,19,902, 125514933,19,1815,1,188,
104761,162,3995,1,163, 125524279,1,189,4934,19,
104774459,19,886,1,163, 125531783,1,189,4279,1,
104783995,1,164,4460,19, 12554190,4935,19,1810,1,
10479892,1,164,4011,1, 12555190,4279,1,191,4936,
10480165,4461,19,880,1, 1255619,1778,1,191,4279,
10481165,4011,1,166,4462, 125571,192,4937,19,1805,
1048219,1145,1,166,4027, 125581,192,4279,1,193,
104831,167,4463,19,782, 125594938,19,1773,1,193,
104841,167,4014,1,168, 125604279,1,194,4939,19,
104854464,19,897,1,168, 125611878,1,194,4279,1,
104864014,1,169,4465,19, 12562195,4940,19,1768,1,
10487777,1,169,4014,1, 12563195,4279,1,196,4941,
10488170,4466,19,802,1, 1256419,1872,1,196,4283,
10489170,4014,1,171,4467, 125651,197,4942,19,1865,
1049019,771,1,171,4014, 125661,197,4289,1,198,
104911,172,4468,19,765, 125674943,19,1841,1,198,
104921,172,4014,1,173, 125684295,1,199,4944,19,
104934469,19,760,1,173, 125691859,1,199,4301,1,
104944014,1,174,4470,19, 12570200,4945,19,1853,1,
10495755,1,174,4014,1, 12571200,4307,1,201,4946,
10496175,4471,19,749,1, 1257219,1847,1,201,4313,
10497175,4014,1,176,4472, 125731,202,4947,19,1789,
1049819,744,1,176,4014, 125741,202,4319,1,203,
104991,177,4473,19,739, 125754948,19,1762,1,203,
105001,177,4014,1,178, 125764325,1,204,4949,19,
105014474,19,734,1,178, 125771941,1,204,4331,1,
105024014,1,179,4475,19, 12578205,4950,19,1907,1,
10503729,1,179,4014,1, 12579205,4331,1,206,4951,
10504180,4476,19,1152,1, 1258019,2302,1,206,4336,
10505180,4099,1,181,4477, 125811,207,4952,19,2294,
1050619,1290,1,181,4112, 125821,207,4339,1,208,
105071,182,4478,19,1139, 125834953,19,2327,1,208,
105081,182,4125,1,183, 125844342,1,209,4954,19,
105094479,19,1278,1,183, 125852285,1,209,4345,1,
105104125,1,184,4480,19, 12586210,4955,19,2279,1,
10511919,1,184,4138,1, 12587210,4348,1,211,4956,
10512185,4481,19,722,1, 1258819,2313,1,211,4351,
10513185,4138,1,186,4482, 125891,212,4957,19,1239,
1051419,817,1,186,4138, 125901,212,4354,1,213,
105151,187,4483,19,845, 125914958,19,1960,1,213,
105161,187,4138,1,188, 125924373,1,214,4959,19,
105174484,19,865,1,188, 125931886,1,214,4377,1,
105184151,1,189,4485,19, 12594215,4960,19,1899,1,
10519911,1,189,4151,1, 12595215,4384,1,216,4961,
10520190,4486,19,825,1, 1259619,1913,1,216,4389,
10521190,4164,1,191,4487, 125971,217,4962,19,1024,
1052219,838,1,191,4164, 125981,217,4461,1,218,
105231,192,4488,19,791, 125994963,19,1008,1,218,
105241,192,4177,1,193, 126004461,1,219,4964,19,
105254489,19,830,1,193, 126011014,1,219,4484,1,
105264177,1,194,4490,19, 12602220,4965,19,1002,1,
105271477,1,194,4190,1, 12603220,4484,1,221,4966,
10528195,4491,19,1158,1, 1260419,1267,1,221,4500,
10529195,4190,1,196,4492, 126051,222,4967,19,904,
1053019,1509,1,196,4190, 126061,222,4487,1,223,
105311,197,4493,19,1541, 126074968,19,1019,1,223,
105321,197,4190,1,198, 126084487,1,224,4969,19,
105334494,19,1406,1,198, 12609899,1,224,4487,1,
105344040,1,199,4495,19, 12610225,4970,19,924,1,
105351466,1,199,4040,1, 12611225,4487,1,226,4971,
10536200,4496,19,1133,1, 1261219,893,1,226,4487,
10537200,4053,1,201,4497, 126131,227,4972,19,887,
1053819,1573,1,201,4053, 126141,227,4487,1,228,
105391,202,4498,19,1504, 126154973,19,882,1,228,
105401,202,4053,1,203, 126164487,1,229,4974,19,
105414499,19,1451,1,203, 12617877,1,229,4487,1,
105424053,1,204,4500,19, 12618230,4975,19,871,1,
105431374,1,204,4053,1, 12619230,4487,1,231,4976,
10544205,4501,19,1300,1, 1262019,866,1,231,4487,
10545205,4053,1,206,4502, 126211,232,4977,19,861,
1054619,1310,1,206,4053, 126221,232,4487,1,233,
105471,207,4503,19,1128, 126234978,19,856,1,233,
105481,207,4053,1,208, 126244487,1,234,4979,19,
105494504,19,1557,1,208, 12625851,1,234,4487,1,
105504053,1,209,4505,19, 12626235,4980,19,1274,1,
105511499,1,209,4053,1, 12627235,4572,1,236,4981,
10552210,4506,19,1441,1, 1262819,1413,1,236,4585,
10553210,4053,1,211,4507, 126291,237,4982,19,1261,
1055419,1363,1,211,4053, 126301,237,4598,1,238,
105551,212,4508,19,1326, 126314983,19,1401,1,238,
105561,212,4053,1,213, 126324598,1,239,4984,19,
105574509,19,1111,1,213, 126331041,1,239,4611,1,
105584053,1,214,4510,19, 12634240,4985,19,844,1,
105591461,1,214,4053,1, 12635240,4611,1,241,4986,
10560215,4511,19,1487,1, 1263619,939,1,241,4611,
10561215,4053,1,216,4512, 126371,242,4987,19,968,
1056219,1434,1,216,4053, 126381,242,4611,1,243,
105631,217,4513,19,1456, 126394988,19,987,1,243,
105641,217,4053,1,218, 126404624,1,244,4989,19,
105654514,19,1266,1,218, 126411033,1,244,4624,1,
105664053,1,219,4515,19, 12642245,4990,19,947,1,
105671170,1,219,4053,1, 12643245,4637,1,246,4991,
10568220,4516,19,1100,1, 1264419,961,1,246,4637,
10569220,4053,1,221,4517, 126451,247,4992,19,913,
1057019,1531,1,221,4053, 126461,247,4650,1,248,
105711,222,4518,19,1482, 126474993,19,952,1,248,
105721,222,4053,1,223, 126484650,1,249,4994,19,
105734519,19,1429,1,223, 126491594,1,249,4663,1,
105744053,1,224,4520,19, 12650250,4995,19,1280,1,
105751295,1,224,4086,1, 12651250,4663,1,251,4996,
10576225,4521,19,1273,1, 1265219,1626,1,251,4663,
10577225,4086,1,226,4522, 126531,252,4997,19,1658,
1057819,1562,1,226,4276, 126541,252,4663,1,253,
105791,227,4523,19,1586, 126554998,19,1524,1,253,
105801,227,4276,1,228, 126564513,1,254,4999,19,
105814524,19,1552,1,228, 126571583,1,254,4513,1,
105824276,1,229,4525,19, 12658255,5000,19,1255,1,
105831547,1,229,4276,1, 12659255,4526,1,256,5001,
10584230,4526,19,1568,1, 1266019,1690,1,256,4526,
10585230,4276,1,231,4527, 126611,257,5002,19,1621,
1058619,1515,1,231,4276, 126621,257,4526,1,258,
105871,232,4528,19,1220, 126635003,19,1568,1,258,
105881,232,4276,1,233, 126644526,1,259,5004,19,
105894529,19,1395,1,233, 126651492,1,259,4526,1,
105904352,1,234,4530,19, 12666260,5005,19,1423,1,
105911181,1,234,4352,1, 12667260,4526,1,261,5006,
10592235,4531,19,1188,1, 1266819,1433,1,261,4526,
10593235,4352,1,236,4532, 126691,262,5007,19,1250,
1059419,1209,1,236,4352, 126701,262,4526,1,263,
105951,237,4533,19,1204, 126715008,19,1674,1,263,
105961,237,4352,1,238, 126724526,1,264,5009,19,
105974534,19,1199,1,238, 126731616,1,264,4526,1,
105984352,1,239,4535,19, 12674265,5010,19,1558,1,
105991194,1,239,4352,1, 12675265,4526,1,266,5011,
10600240,4536,19,1384,1, 1267619,1481,1,266,4526,
10601240,4352,1,241,4537, 126771,267,5012,19,1443,
1060219,1412,1,241,4352, 126781,267,4526,1,268,
106031,242,4538,19,1389, 126795013,19,1233,1,268,
106041,242,4352,1,243, 126804526,1,269,5014,19,
106054539,19,1379,1,243, 126811578,1,269,4526,1,
106064352,1,244,4540,19, 12682270,5015,19,1604,1,
106071369,1,244,4352,1, 12683270,4526,1,271,5016,
10608245,4541,19,1352,1, 1268419,1551,1,271,4526,
10609245,4352,1,246,4542, 126851,272,5017,19,1573,
1061019,1305,1,246,4352, 126861,272,4526,1,273,
106111,247,4543,19,1214, 126875018,19,1389,1,273,
106121,247,4352,1,248, 126884526,1,274,5019,19,
106134544,19,1175,1,248, 126891293,1,274,4526,1,
106144352,1,249,4545,19, 12690275,5020,19,1222,1,
106151123,1,249,4352,1, 12691275,4526,1,276,5021,
10616250,4546,19,1581,1, 1269219,1648,1,276,4526,
10617250,4352,1,251,4547, 126931,277,5022,19,1599,
1061819,1536,1,251,4352, 126941,277,4526,1,278,
106191,252,4548,19,1526, 126955023,19,1546,1,278,
106201,252,4352,1,253, 126964526,1,279,5024,19,
106214549,19,1521,1,253, 126971418,1,279,4559,1,
106224352,1,254,4550,19, 12698280,5025,19,1396,1,
106231472,1,254,4352,1, 12699280,4559,1,281,5026,
10624255,4551,19,1446,1, 1270019,1679,1,281,4749,
10625255,4352,1,256,4552, 127011,282,5027,19,1708,
1062619,1422,1,256,4352, 127021,282,4749,1,283,
106271,257,4553,19,1417, 127035028,19,1669,1,283,
106281,257,4352,1,258, 127044749,1,284,5029,19,
106294554,19,1358,1,258, 127051664,1,284,4749,1,
106304352,1,259,4555,19, 12706285,5030,19,1685,1,
106311334,1,259,4352,1, 12707285,4749,1,286,5031,
10632260,4556,19,1400,1, 1270819,1632,1,286,4749,
10633260,4352,1,261,4557, 127091,287,5032,19,1343,
1063419,1493,1,261,4352, 127101,287,4749,1,288,
106351,262,4558,19,1347, 127115033,19,1513,1,288,
106361,262,4352,1,263, 127124825,1,289,5034,19,
106374559,19,1341,1,263, 127131304,1,289,4825,1,
106384352,1,264,4560,19, 12714290,5035,19,1311,1,
106391321,1,264,4352,1, 12715290,4825,1,291,5036,
10640265,4561,19,1284,1, 1271619,1332,1,291,4825,
10641265,4352,1,266,4562, 127171,292,5037,19,1327,
1064219,1261,1,266,4352, 127181,292,4825,1,293,
106431,267,4563,19,1106, 127195038,19,1322,1,293,
106441,267,4352,1,268, 127204825,1,294,5039,19,
106454564,19,1596,1,268, 127211317,1,294,4825,1,
106464352,1,269,4565,19, 12722295,5040,19,1502,1,
106471226,1,269,4352,1, 12723295,4825,1,296,5041,
10648270,4566,19,1231,1, 1272419,1530,1,296,4825,
10649270,4352,1,271,4567, 127251,297,5042,19,1507,
1065019,1251,1,271,4352, 127261,297,4825,1,298,
106511,272,4568,19,1241, 127275043,19,1497,1,298,
106521,272,4352,1,273, 127284825,1,299,5044,19,
106534569,19,1246,1,273, 127291487,1,299,4825,1,
106544352,1,274,4570,19, 12730300,5045,19,1470,1,
106551236,1,274,4352,1, 12731300,4825,1,301,5046,
10656275,4571,19,1591,1, 1273219,1428,1,301,4825,
10657275,4352,1,276,4572, 127331,302,5047,19,1337,
1065819,1256,1,276,4352, 127341,302,4825,1,303,
106591,277,4573,19,1316, 127355048,19,1298,1,303,
106601,277,4195,1,278, 127364825,1,304,5049,19,
106614574,19,1650,1,278, 127371245,1,304,4825,1,
106624265,1,279,4575,19, 12738305,5050,19,1703,1,
106631686,1,279,4265,1, 12739305,4825,1,306,5051,
10664280,4576,19,1666,1, 1274019,1653,1,306,4825,
10665280,4269,1,281,4577, 127411,307,5052,19,1643,
1066619,1985,1,281,3969, 127421,307,4825,1,308,
106671,282,4578,19,1980, 127435053,19,1638,1,308,
106681,282,3969,1,283, 127444825,1,309,5054,19,
106694579,19,1975,1,283, 127451589,1,309,4825,1,
106703969,1,284,4580,19, 12746310,5055,19,1563,1,
106711970,1,284,3969,1, 12747310,4825,1,311,5056,
10672285,4581,19,1965,1, 1274819,1540,1,311,4825,
10673285,3969,1,286,4582, 127491,312,5057,19,1535,
1067419,1960,1,286,3969, 127501,312,4825,1,313,
106751,287,4583,19,1955, 127515058,19,1476,1,313,
106761,287,3969,1,288, 127524825,1,314,5059,19,
106774584,19,1944,1,288, 127531451,1,314,4825,1,
106783989,1,289,4585,19, 12754315,5060,19,1518,1,
106791939,1,289,3989,1, 12755315,4825,1,316,5061,
10680290,4586,19,1934,1, 1275619,1610,1,316,4825,
10681290,3989,1,291,4587, 127571,317,5062,19,1465,
1068219,1929,1,291,3989, 127581,317,4825,1,318,
106831,292,4588,19,1924, 127595063,19,1458,1,318,
106841,292,3989,1,293, 127604825,1,319,5064,19,
106854589,19,1919,1,293, 127611438,1,319,4825,1,
106863989,1,294,4590,19, 12762320,5065,19,1407,1,
106871914,1,294,3989,1, 12763320,4825,1,321,5066,
10688295,4591,19,1909,1, 1276419,1384,1,321,4825,
10689295,3989,1,296,4592, 127651,322,5067,19,1228,
1069019,1904,1,296,3989, 127661,322,4825,1,323,
106911,297,4593,19,1739, 127675068,19,1718,1,323,
106921,297,3989,1,298, 127684825,1,324,5069,19,
106934594,19,1898,1,298, 127691349,1,324,4825,1,
106943989,1,299,4595,19, 12770325,5070,19,1354,1,
106951893,1,299,3989,1, 12771325,4825,1,326,5071,
10696300,4596,19,1888,1, 1277219,1374,1,326,4825,
10697300,3989,1,301,4597, 127731,327,5072,19,1364,
1069819,1732,1,301,3989, 127741,327,4825,1,328,
106991,302,4598,19,1883, 127755073,19,1369,1,328,
107001,302,3989,1,303, 127764825,1,329,5074,19,
107014599,19,1878,1,303, 127771359,1,329,4825,1,
107023989,1,304,4600,19, 12778330,5075,19,1713,1,
107031873,1,304,3989,1, 12779330,4825,1,331,5076,
10704305,4601,19,1868,1, 1278019,1379,1,331,4825,
10705305,3989,1,306,4602, 127811,332,5077,19,1698,
1070619,1863,1,306,3989, 127821,332,4668,1,333,
107071,307,4603,19,1858, 127835078,19,1954,1,333,
107081,307,3989,1,308, 127844738,1,334,5079,19,
107094604,19,1725,1,308, 127851947,1,334,4738,1,
107103989,1,309,4605,19, 12786335,5080,19,1924,1,
107111852,1,309,3989,1, 12787335,4742,1,336,5081,
10712310,4606,19,1847,1, 1278819,2270,1,336,4393,
10713310,3989,1,311,4607, 127891,337,5082,19,2265,
1071419,1842,1,311,3989, 127901,337,4393,1,338,
107151,312,4608,19,1719, 127915083,19,2260,1,338,
107161,312,3989,1,313, 127924393,1,339,5084,19,
107174609,19,1836,1,313, 127932255,1,339,4393,1,
107183989,1,314,4610,19, 12794340,5085,19,2250,1,
107191767,1,314,3989,1, 12795340,4393,1,341,5086,
10720315,4611,19,1831,1, 1279619,2245,1,341,4393,
10721315,3989,1,316,4612, 127971,342,5087,19,2240,
1072219,1826,1,316,3989, 127981,342,4393,1,343,
107231,317,4613,19,1821, 127995088,19,2229,1,343,
107241,317,3989,1,318, 128004413,1,344,5089,19,
107254614,19,1816,1,318, 128012224,1,344,4413,1,
107263989,1,319,4615,19, 12802345,5090,19,2219,1,
107271811,1,319,3989,1, 12803345,4413,1,346,5091,
10728320,4616,19,1806,1, 1280419,2214,1,346,4413,
10729320,3989,1,321,4617, 128051,347,5092,19,2209,
1073019,1801,1,321,3989, 128061,347,4413,1,348,
107311,322,4618,19,4619, 128075093,19,2204,1,348,
128084413,1,349,5094,19,
128092199,1,349,4413,1,
12810350,5095,19,2194,1,
12811350,4413,1,351,5096,
1281219,2188,1,351,4419,
128131,352,5097,19,2014,
128141,352,4419,1,353,
128155098,19,2182,1,353,
128164419,1,354,5099,19,
128172177,1,354,4419,1,
12818355,5100,19,2172,1,
12819355,4419,1,356,5101,
1282019,2007,1,356,4419,
128211,357,5102,19,2167,
128221,357,4419,1,358,
128235103,19,2162,1,358,
128244419,1,359,5104,19,
128252157,1,359,4425,1,
12826360,5105,19,2152,1,
12827360,4425,1,361,5106,
1282819,2146,1,361,4431,
128291,362,5107,19,2141,
128301,362,4431,1,363,
128315108,19,1998,1,363,
128324431,1,364,5109,19,
128332135,1,364,4431,1,
12834365,5110,19,2130,1,
12835365,4431,1,366,5111,
1283619,2125,1,366,4431,
128371,367,5112,19,1992,
128381,367,4431,1,368,
128395113,19,2119,1,368,
128404431,1,369,5114,19,
128412047,1,369,4431,1,
12842370,5115,19,2114,1,
12843370,4431,1,371,5116,
1284419,2109,1,371,4437,
128451,372,5117,19,2104,
128461,372,4437,1,373,
128475118,19,2099,1,373,
128484437,1,374,5119,19,
128492093,1,374,4443,1,
12850375,5120,19,2087,1,
12851375,4449,1,376,5121,
1285219,2081,1,376,4455,
128531,377,5122,19,5123,
107324,50,65,0,114, 128544,50,65,0,114,
107330,103,0,117,0, 128550,103,0,117,0,
10734109,0,101,0,110, 12856109,0,101,0,110,
@@ -10739,16 +12861,16 @@ public yyLSLSyntax
107390,111,0,110,0, 128610,111,0,110,0,
1074076,0,105,0,115, 1286276,0,105,0,115,
107410,116,0,95,0, 128630,116,0,95,0,
1074251,0,1,322,3945, 1286451,0,1,377,4331,
107431,323,4620,19,4621, 128651,378,5124,19,5125,
107444,28,65,0,114, 128664,28,65,0,114,
107450,103,0,117,0, 128670,103,0,117,0,
10746109,0,101,0,110, 12868109,0,101,0,110,
107470,116,0,76,0, 128690,116,0,76,0,
10748105,0,115,0,116, 12870105,0,115,0,116,
107490,95,0,51,0, 128710,95,0,51,0,
107501,323,4265,1,324, 128721,378,4738,1,379,
107514622,19,4623,4,50, 128735126,19,5127,4,50,
1075265,0,114,0,103, 1287465,0,114,0,103,
107530,117,0,109,0, 128750,117,0,109,0,
10754101,0,110,0,116, 12876101,0,110,0,116,
@@ -10759,16 +12881,16 @@ public yyLSLSyntax
107590,110,0,76,0, 128810,110,0,76,0,
10760105,0,115,0,116, 12882105,0,115,0,116,
107610,95,0,52,0, 128830,95,0,52,0,
107621,324,3945,1,325, 128841,379,4331,1,380,
107634624,19,4625,4,28, 128855128,19,5129,4,28,
1076465,0,114,0,103, 1288665,0,114,0,103,
107650,117,0,109,0, 128870,117,0,109,0,
10766101,0,110,0,116, 12888101,0,110,0,116,
107670,76,0,105,0, 128890,76,0,105,0,
10768115,0,116,0,95, 12890115,0,116,0,95,
107690,52,0,1,325, 128910,52,0,1,380,
107704265,1,326,4626,19, 128924738,1,381,5130,19,
107714627,4,50,65,0, 128935131,4,50,65,0,
10772114,0,103,0,117, 12894114,0,103,0,117,
107730,109,0,101,0, 128950,109,0,101,0,
10774110,0,116,0,68, 12896110,0,116,0,68,
@@ -10778,13 +12900,18 @@ public yyLSLSyntax
10778105,0,111,0,110, 12900105,0,111,0,110,
107790,76,0,105,0, 129010,76,0,105,0,
10780115,0,116,0,95, 12902115,0,116,0,95,
107810,53,0,1,326, 129030,53,0,1,381,
107823945,2,0,0}; 129044331,2,0,0};
10783new Sfactory(this,"ExpressionArgument_1",new SCreator(ExpressionArgument_1_factory)); 12905new Sfactory(this,"ExpressionArgument_1",new SCreator(ExpressionArgument_1_factory));
10784new Sfactory(this,"SimpleAssignment_8",new SCreator(SimpleAssignment_8_factory)); 12906new Sfactory(this,"VectorArgStateEvent",new SCreator(VectorArgStateEvent_factory));
12907new Sfactory(this,"IntVecVecArgStateEvent",new SCreator(IntVecVecArgStateEvent_factory));
12908new Sfactory(this,"IntArgStateEvent_1",new SCreator(IntArgStateEvent_1_factory));
12909new Sfactory(this,"SimpleAssignment_9",new SCreator(SimpleAssignment_9_factory));
10785new Sfactory(this,"StatementList_1",new SCreator(StatementList_1_factory)); 12910new Sfactory(this,"StatementList_1",new SCreator(StatementList_1_factory));
12911new Sfactory(this,"RotDeclaration_1",new SCreator(RotDeclaration_1_factory));
12912new Sfactory(this,"IntRotRotArgEvent_1",new SCreator(IntRotRotArgEvent_1_factory));
10786new Sfactory(this,"StateChange_1",new SCreator(StateChange_1_factory)); 12913new Sfactory(this,"StateChange_1",new SCreator(StateChange_1_factory));
10787new Sfactory(this,"StateChange_2",new SCreator(StateChange_2_factory)); 12914new Sfactory(this,"EmptyStatement",new SCreator(EmptyStatement_factory));
10788new Sfactory(this,"Declaration",new SCreator(Declaration_factory)); 12915new Sfactory(this,"Declaration",new SCreator(Declaration_factory));
10789new Sfactory(this,"IdentExpression",new SCreator(IdentExpression_factory)); 12916new Sfactory(this,"IdentExpression",new SCreator(IdentExpression_factory));
10790new Sfactory(this,"error",new SCreator(error_factory)); 12917new Sfactory(this,"error",new SCreator(error_factory));
@@ -10797,20 +12924,25 @@ new Sfactory(this,"SimpleAssignment_19",new SCreator(SimpleAssignment_19_factory
10797new Sfactory(this,"BinaryExpression_9",new SCreator(BinaryExpression_9_factory)); 12924new Sfactory(this,"BinaryExpression_9",new SCreator(BinaryExpression_9_factory));
10798new Sfactory(this,"VectorConstant_1",new SCreator(VectorConstant_1_factory)); 12925new Sfactory(this,"VectorConstant_1",new SCreator(VectorConstant_1_factory));
10799new Sfactory(this,"ParenthesisExpression",new SCreator(ParenthesisExpression_factory)); 12926new Sfactory(this,"ParenthesisExpression",new SCreator(ParenthesisExpression_factory));
12927new Sfactory(this,"StatementList",new SCreator(StatementList_factory));
12928new Sfactory(this,"IntRotRotArgEvent",new SCreator(IntRotRotArgEvent_factory));
10800new Sfactory(this,"UnaryExpression",new SCreator(UnaryExpression_factory)); 12929new Sfactory(this,"UnaryExpression",new SCreator(UnaryExpression_factory));
10801new Sfactory(this,"IdentDotExpression_1",new SCreator(IdentDotExpression_1_factory)); 12930new Sfactory(this,"IdentDotExpression_1",new SCreator(IdentDotExpression_1_factory));
10802new Sfactory(this,"ArgumentList_4",new SCreator(ArgumentList_4_factory)); 12931new Sfactory(this,"ArgumentList_4",new SCreator(ArgumentList_4_factory));
10803new Sfactory(this,"Typename",new SCreator(Typename_factory)); 12932new Sfactory(this,"Typename",new SCreator(Typename_factory));
10804new Sfactory(this,"IfStatement_1",new SCreator(IfStatement_1_factory)); 12933new Sfactory(this,"IfStatement_1",new SCreator(IfStatement_1_factory));
12934new Sfactory(this,"RotationConstant_1",new SCreator(RotationConstant_1_factory));
10805new Sfactory(this,"Assignment",new SCreator(Assignment_factory)); 12935new Sfactory(this,"Assignment",new SCreator(Assignment_factory));
12936new Sfactory(this,"IfStatement_4",new SCreator(IfStatement_4_factory));
10806new Sfactory(this,"CompoundStatement_1",new SCreator(CompoundStatement_1_factory)); 12937new Sfactory(this,"CompoundStatement_1",new SCreator(CompoundStatement_1_factory));
10807new Sfactory(this,"CompoundStatement_2",new SCreator(CompoundStatement_2_factory)); 12938new Sfactory(this,"CompoundStatement_2",new SCreator(CompoundStatement_2_factory));
12939new Sfactory(this,"KeyIntIntArgumentDeclarationList_1",new SCreator(KeyIntIntArgumentDeclarationList_1_factory));
10808new Sfactory(this,"BinaryExpression_8",new SCreator(BinaryExpression_8_factory)); 12940new Sfactory(this,"BinaryExpression_8",new SCreator(BinaryExpression_8_factory));
12941new Sfactory(this,"VectorArgEvent",new SCreator(VectorArgEvent_factory));
10809new Sfactory(this,"ReturnStatement_1",new SCreator(ReturnStatement_1_factory)); 12942new Sfactory(this,"ReturnStatement_1",new SCreator(ReturnStatement_1_factory));
10810new Sfactory(this,"IdentDotExpression",new SCreator(IdentDotExpression_factory)); 12943new Sfactory(this,"IdentDotExpression",new SCreator(IdentDotExpression_factory));
10811new Sfactory(this,"Argument",new SCreator(Argument_factory)); 12944new Sfactory(this,"Argument",new SCreator(Argument_factory));
10812new Sfactory(this,"State_2",new SCreator(State_2_factory)); 12945new Sfactory(this,"State_2",new SCreator(State_2_factory));
10813new Sfactory(this,"WhileStatement_1",new SCreator(WhileStatement_1_factory));
10814new Sfactory(this,"GlobalDefinitions_3",new SCreator(GlobalDefinitions_3_factory)); 12946new Sfactory(this,"GlobalDefinitions_3",new SCreator(GlobalDefinitions_3_factory));
10815new Sfactory(this,"GlobalDefinitions_4",new SCreator(GlobalDefinitions_4_factory)); 12947new Sfactory(this,"GlobalDefinitions_4",new SCreator(GlobalDefinitions_4_factory));
10816new Sfactory(this,"Event_1",new SCreator(Event_1_factory)); 12948new Sfactory(this,"Event_1",new SCreator(Event_1_factory));
@@ -10820,9 +12952,9 @@ new Sfactory(this,"Event_4",new SCreator(Event_4_factory));
10820new Sfactory(this,"Event_5",new SCreator(Event_5_factory)); 12952new Sfactory(this,"Event_5",new SCreator(Event_5_factory));
10821new Sfactory(this,"SimpleAssignment_5",new SCreator(SimpleAssignment_5_factory)); 12953new Sfactory(this,"SimpleAssignment_5",new SCreator(SimpleAssignment_5_factory));
10822new Sfactory(this,"Typename_1",new SCreator(Typename_1_factory)); 12954new Sfactory(this,"Typename_1",new SCreator(Typename_1_factory));
10823new Sfactory(this,"Typename_2",new SCreator(Typename_2_factory)); 12955new Sfactory(this,"VoidArgStateEvent_1",new SCreator(VoidArgStateEvent_1_factory));
10824new Sfactory(this,"Typename_3",new SCreator(Typename_3_factory)); 12956new Sfactory(this,"Typename_3",new SCreator(Typename_3_factory));
10825new Sfactory(this,"Typename_4",new SCreator(Typename_4_factory)); 12957new Sfactory(this,"IntRotRotArgStateEvent",new SCreator(IntRotRotArgStateEvent_factory));
10826new Sfactory(this,"Typename_5",new SCreator(Typename_5_factory)); 12958new Sfactory(this,"Typename_5",new SCreator(Typename_5_factory));
10827new Sfactory(this,"Typename_6",new SCreator(Typename_6_factory)); 12959new Sfactory(this,"Typename_6",new SCreator(Typename_6_factory));
10828new Sfactory(this,"Typename_7",new SCreator(Typename_7_factory)); 12960new Sfactory(this,"Typename_7",new SCreator(Typename_7_factory));
@@ -10830,10 +12962,16 @@ new Sfactory(this,"ArgumentDeclarationList",new SCreator(ArgumentDeclarationList
10830new Sfactory(this,"ConstantExpression",new SCreator(ConstantExpression_factory)); 12962new Sfactory(this,"ConstantExpression",new SCreator(ConstantExpression_factory));
10831new Sfactory(this,"LSLProgramRoot_1",new SCreator(LSLProgramRoot_1_factory)); 12963new Sfactory(this,"LSLProgramRoot_1",new SCreator(LSLProgramRoot_1_factory));
10832new Sfactory(this,"LSLProgramRoot_2",new SCreator(LSLProgramRoot_2_factory)); 12964new Sfactory(this,"LSLProgramRoot_2",new SCreator(LSLProgramRoot_2_factory));
12965new Sfactory(this,"KeyIntIntArgEvent_1",new SCreator(KeyIntIntArgEvent_1_factory));
10833new Sfactory(this,"States_1",new SCreator(States_1_factory)); 12966new Sfactory(this,"States_1",new SCreator(States_1_factory));
10834new Sfactory(this,"States_2",new SCreator(States_2_factory)); 12967new Sfactory(this,"States_2",new SCreator(States_2_factory));
10835new Sfactory(this,"FunctionCallExpression_1",new SCreator(FunctionCallExpression_1_factory)); 12968new Sfactory(this,"FunctionCallExpression_1",new SCreator(FunctionCallExpression_1_factory));
12969new Sfactory(this,"KeyArgEvent_1",new SCreator(KeyArgEvent_1_factory));
10836new Sfactory(this,"ForLoopStatement",new SCreator(ForLoopStatement_factory)); 12970new Sfactory(this,"ForLoopStatement",new SCreator(ForLoopStatement_factory));
12971new Sfactory(this,"IntArgStateEvent",new SCreator(IntArgStateEvent_factory));
12972new Sfactory(this,"StateBody_15",new SCreator(StateBody_15_factory));
12973new Sfactory(this,"IntRotRotArgumentDeclarationList_1",new SCreator(IntRotRotArgumentDeclarationList_1_factory));
12974new Sfactory(this,"IntArgEvent_9",new SCreator(IntArgEvent_9_factory));
10837new Sfactory(this,"DoWhileStatement_1",new SCreator(DoWhileStatement_1_factory)); 12975new Sfactory(this,"DoWhileStatement_1",new SCreator(DoWhileStatement_1_factory));
10838new Sfactory(this,"DoWhileStatement_2",new SCreator(DoWhileStatement_2_factory)); 12976new Sfactory(this,"DoWhileStatement_2",new SCreator(DoWhileStatement_2_factory));
10839new Sfactory(this,"ForLoopStatement_4",new SCreator(ForLoopStatement_4_factory)); 12977new Sfactory(this,"ForLoopStatement_4",new SCreator(ForLoopStatement_4_factory));
@@ -10842,74 +12980,93 @@ new Sfactory(this,"SimpleAssignment_12",new SCreator(SimpleAssignment_12_factory
10842new Sfactory(this,"SimpleAssignment_13",new SCreator(SimpleAssignment_13_factory)); 12980new Sfactory(this,"SimpleAssignment_13",new SCreator(SimpleAssignment_13_factory));
10843new Sfactory(this,"JumpLabel",new SCreator(JumpLabel_factory)); 12981new Sfactory(this,"JumpLabel",new SCreator(JumpLabel_factory));
10844new Sfactory(this,"SimpleAssignment_15",new SCreator(SimpleAssignment_15_factory)); 12982new Sfactory(this,"SimpleAssignment_15",new SCreator(SimpleAssignment_15_factory));
10845new Sfactory(this,"SimpleAssignment_17",new SCreator(SimpleAssignment_17_factory)); 12983new Sfactory(this,"IntVecVecArgEvent",new SCreator(IntVecVecArgEvent_factory));
10846new Sfactory(this,"SimpleAssignment_18",new SCreator(SimpleAssignment_18_factory)); 12984new Sfactory(this,"VecDeclaration",new SCreator(VecDeclaration_factory));
10847new Sfactory(this,"JumpStatement_1",new SCreator(JumpStatement_1_factory)); 12985new Sfactory(this,"StateBody_14",new SCreator(StateBody_14_factory));
10848new Sfactory(this,"GlobalDefinitions",new SCreator(GlobalDefinitions_factory)); 12986new Sfactory(this,"GlobalDefinitions",new SCreator(GlobalDefinitions_factory));
12987new Sfactory(this,"StateBody_16",new SCreator(StateBody_16_factory));
12988new Sfactory(this,"KeyIntIntArgumentDeclarationList",new SCreator(KeyIntIntArgumentDeclarationList_factory));
12989new Sfactory(this,"ConstantExpression_1",new SCreator(ConstantExpression_1_factory));
12990new Sfactory(this,"VoidArgEvent_4",new SCreator(VoidArgEvent_4_factory));
10849new Sfactory(this,"FunctionCall_1",new SCreator(FunctionCall_1_factory)); 12991new Sfactory(this,"FunctionCall_1",new SCreator(FunctionCall_1_factory));
10850new Sfactory(this,"ArgumentList_3",new SCreator(ArgumentList_3_factory)); 12992new Sfactory(this,"Assignment_1",new SCreator(Assignment_1_factory));
10851new Sfactory(this,"Assignment_2",new SCreator(Assignment_2_factory)); 12993new Sfactory(this,"Assignment_2",new SCreator(Assignment_2_factory));
12994new Sfactory(this,"IntVecVecArgEvent_1",new SCreator(IntVecVecArgEvent_1_factory));
10852new Sfactory(this,"TypecastExpression_1",new SCreator(TypecastExpression_1_factory)); 12995new Sfactory(this,"TypecastExpression_1",new SCreator(TypecastExpression_1_factory));
10853new Sfactory(this,"SimpleAssignment_21",new SCreator(SimpleAssignment_21_factory)); 12996new Sfactory(this,"SimpleAssignment_21",new SCreator(SimpleAssignment_21_factory));
10854new Sfactory(this,"SimpleAssignment_22",new SCreator(SimpleAssignment_22_factory)); 12997new Sfactory(this,"SimpleAssignment_22",new SCreator(SimpleAssignment_22_factory));
10855new Sfactory(this,"SimpleAssignment_23",new SCreator(SimpleAssignment_23_factory)); 12998new Sfactory(this,"KeyIntIntArgStateEvent",new SCreator(KeyIntIntArgStateEvent_factory));
10856new Sfactory(this,"TypecastExpression_9",new SCreator(TypecastExpression_9_factory)); 12999new Sfactory(this,"TypecastExpression_9",new SCreator(TypecastExpression_9_factory));
13000new Sfactory(this,"VoidArgEvent_2",new SCreator(VoidArgEvent_2_factory));
13001new Sfactory(this,"VoidArgEvent_3",new SCreator(VoidArgEvent_3_factory));
10857new Sfactory(this,"ArgumentDeclarationList_1",new SCreator(ArgumentDeclarationList_1_factory)); 13002new Sfactory(this,"ArgumentDeclarationList_1",new SCreator(ArgumentDeclarationList_1_factory));
10858new Sfactory(this,"ArgumentDeclarationList_2",new SCreator(ArgumentDeclarationList_2_factory)); 13003new Sfactory(this,"ArgumentDeclarationList_2",new SCreator(ArgumentDeclarationList_2_factory));
10859new Sfactory(this,"ArgumentDeclarationList_3",new SCreator(ArgumentDeclarationList_3_factory));
10860new Sfactory(this,"GlobalDefinitions_1",new SCreator(GlobalDefinitions_1_factory)); 13004new Sfactory(this,"GlobalDefinitions_1",new SCreator(GlobalDefinitions_1_factory));
10861new Sfactory(this,"GlobalDefinitions_2",new SCreator(GlobalDefinitions_2_factory)); 13005new Sfactory(this,"GlobalDefinitions_2",new SCreator(GlobalDefinitions_2_factory));
10862new Sfactory(this,"IncrementDecrementExpression",new SCreator(IncrementDecrementExpression_factory)); 13006new Sfactory(this,"IncrementDecrementExpression",new SCreator(IncrementDecrementExpression_factory));
10863new Sfactory(this,"GlobalVariableDeclaration",new SCreator(GlobalVariableDeclaration_factory)); 13007new Sfactory(this,"GlobalVariableDeclaration",new SCreator(GlobalVariableDeclaration_factory));
10864new Sfactory(this,"Event_11",new SCreator(Event_11_factory)); 13008new Sfactory(this,"IntArgumentDeclarationList_1",new SCreator(IntArgumentDeclarationList_1_factory));
13009new Sfactory(this,"IntDeclaration_1",new SCreator(IntDeclaration_1_factory));
13010new Sfactory(this,"ArgumentDeclarationList_5",new SCreator(ArgumentDeclarationList_5_factory));
13011new Sfactory(this,"IntVecVecArgumentDeclarationList",new SCreator(IntVecVecArgumentDeclarationList_factory));
13012new Sfactory(this,"VectorArgumentDeclarationList_1",new SCreator(VectorArgumentDeclarationList_1_factory));
13013new Sfactory(this,"KeyArgumentDeclarationList",new SCreator(KeyArgumentDeclarationList_factory));
10865new Sfactory(this,"TypecastExpression_2",new SCreator(TypecastExpression_2_factory)); 13014new Sfactory(this,"TypecastExpression_2",new SCreator(TypecastExpression_2_factory));
10866new Sfactory(this,"TypecastExpression_3",new SCreator(TypecastExpression_3_factory)); 13015new Sfactory(this,"KeyArgStateEvent",new SCreator(KeyArgStateEvent_factory));
10867new Sfactory(this,"TypecastExpression_5",new SCreator(TypecastExpression_5_factory)); 13016new Sfactory(this,"TypecastExpression_5",new SCreator(TypecastExpression_5_factory));
10868new Sfactory(this,"TypecastExpression_8",new SCreator(TypecastExpression_8_factory)); 13017new Sfactory(this,"TypecastExpression_8",new SCreator(TypecastExpression_8_factory));
10869new Sfactory(this,"Constant_1",new SCreator(Constant_1_factory)); 13018new Sfactory(this,"Constant_1",new SCreator(Constant_1_factory));
10870new Sfactory(this,"Expression",new SCreator(Expression_factory)); 13019new Sfactory(this,"Expression",new SCreator(Expression_factory));
10871new Sfactory(this,"Constant_3",new SCreator(Constant_3_factory)); 13020new Sfactory(this,"Constant_3",new SCreator(Constant_3_factory));
10872new Sfactory(this,"Constant_4",new SCreator(Constant_4_factory)); 13021new Sfactory(this,"Constant_4",new SCreator(Constant_4_factory));
13022new Sfactory(this,"IntArgEvent_5",new SCreator(IntArgEvent_5_factory));
10873new Sfactory(this,"BinaryExpression_1",new SCreator(BinaryExpression_1_factory)); 13023new Sfactory(this,"BinaryExpression_1",new SCreator(BinaryExpression_1_factory));
10874new Sfactory(this,"IfStatement_2",new SCreator(IfStatement_2_factory)); 13024new Sfactory(this,"IfStatement_2",new SCreator(IfStatement_2_factory));
10875new Sfactory(this,"IfStatement_3",new SCreator(IfStatement_3_factory)); 13025new Sfactory(this,"IfStatement_3",new SCreator(IfStatement_3_factory));
10876new Sfactory(this,"IfStatement_4",new SCreator(IfStatement_4_factory)); 13026new Sfactory(this,"KeyArgEvent",new SCreator(KeyArgEvent_factory));
10877new Sfactory(this,"ReturnStatement",new SCreator(ReturnStatement_factory));
10878new Sfactory(this,"Event_2",new SCreator(Event_2_factory)); 13027new Sfactory(this,"Event_2",new SCreator(Event_2_factory));
13028new Sfactory(this,"JumpLabel_1",new SCreator(JumpLabel_1_factory));
10879new Sfactory(this,"RotationConstant",new SCreator(RotationConstant_factory)); 13029new Sfactory(this,"RotationConstant",new SCreator(RotationConstant_factory));
10880new Sfactory(this,"Statement_12",new SCreator(Statement_12_factory)); 13030new Sfactory(this,"Statement_12",new SCreator(Statement_12_factory));
13031new Sfactory(this,"Statement_13",new SCreator(Statement_13_factory));
10881new Sfactory(this,"UnaryExpression_1",new SCreator(UnaryExpression_1_factory)); 13032new Sfactory(this,"UnaryExpression_1",new SCreator(UnaryExpression_1_factory));
10882new Sfactory(this,"UnaryExpression_2",new SCreator(UnaryExpression_2_factory)); 13033new Sfactory(this,"UnaryExpression_2",new SCreator(UnaryExpression_2_factory));
10883new Sfactory(this,"UnaryExpression_3",new SCreator(UnaryExpression_3_factory)); 13034new Sfactory(this,"UnaryExpression_3",new SCreator(UnaryExpression_3_factory));
10884new Sfactory(this,"ArgumentList_1",new SCreator(ArgumentList_1_factory)); 13035new Sfactory(this,"ArgumentList_1",new SCreator(ArgumentList_1_factory));
10885new Sfactory(this,"ArgumentList_2",new SCreator(ArgumentList_2_factory)); 13036new Sfactory(this,"KeyIntIntArgEvent",new SCreator(KeyIntIntArgEvent_factory));
13037new Sfactory(this,"ArgumentList_3",new SCreator(ArgumentList_3_factory));
10886new Sfactory(this,"Constant",new SCreator(Constant_factory)); 13038new Sfactory(this,"Constant",new SCreator(Constant_factory));
10887new Sfactory(this,"State",new SCreator(State_factory)); 13039new Sfactory(this,"State",new SCreator(State_factory));
10888new Sfactory(this,"Event_13",new SCreator(Event_13_factory)); 13040new Sfactory(this,"StateBody_13",new SCreator(StateBody_13_factory));
13041new Sfactory(this,"KeyArgStateEvent_1",new SCreator(KeyArgStateEvent_1_factory));
13042new Sfactory(this,"SimpleAssignment_8",new SCreator(SimpleAssignment_8_factory));
10889new Sfactory(this,"LSLProgramRoot",new SCreator(LSLProgramRoot_factory)); 13043new Sfactory(this,"LSLProgramRoot",new SCreator(LSLProgramRoot_factory));
10890new Sfactory(this,"StateChange",new SCreator(StateChange_factory)); 13044new Sfactory(this,"StateChange",new SCreator(StateChange_factory));
10891new Sfactory(this,"IncrementDecrementExpression_2",new SCreator(IncrementDecrementExpression_2_factory)); 13045new Sfactory(this,"VecDeclaration_1",new SCreator(VecDeclaration_1_factory));
10892new Sfactory(this,"GlobalVariableDeclaration_1",new SCreator(GlobalVariableDeclaration_1_factory)); 13046new Sfactory(this,"GlobalVariableDeclaration_1",new SCreator(GlobalVariableDeclaration_1_factory));
10893new Sfactory(this,"GlobalVariableDeclaration_2",new SCreator(GlobalVariableDeclaration_2_factory)); 13047new Sfactory(this,"GlobalVariableDeclaration_2",new SCreator(GlobalVariableDeclaration_2_factory));
10894new Sfactory(this,"IncrementDecrementExpression_5",new SCreator(IncrementDecrementExpression_5_factory)); 13048new Sfactory(this,"IncrementDecrementExpression_5",new SCreator(IncrementDecrementExpression_5_factory));
10895new Sfactory(this,"GlobalFunctionDefinition_2",new SCreator(GlobalFunctionDefinition_2_factory)); 13049new Sfactory(this,"ReturnStatement",new SCreator(ReturnStatement_factory));
10896new Sfactory(this,"IncrementDecrementExpression_7",new SCreator(IncrementDecrementExpression_7_factory)); 13050new Sfactory(this,"StateBody_10",new SCreator(StateBody_10_factory));
10897new Sfactory(this,"IncrementDecrementExpression_8",new SCreator(IncrementDecrementExpression_8_factory)); 13051new Sfactory(this,"StateBody_11",new SCreator(StateBody_11_factory));
10898new Sfactory(this,"Assignment_1",new SCreator(Assignment_1_factory)); 13052new Sfactory(this,"StateBody_12",new SCreator(StateBody_12_factory));
10899new Sfactory(this,"Event_21",new SCreator(Event_21_factory)); 13053new Sfactory(this,"IntVecVecArgStateEvent_1",new SCreator(IntVecVecArgStateEvent_1_factory));
10900new Sfactory(this,"Event_22",new SCreator(Event_22_factory)); 13054new Sfactory(this,"KeyDeclaration",new SCreator(KeyDeclaration_factory));
13055new Sfactory(this,"IntArgEvent_6",new SCreator(IntArgEvent_6_factory));
13056new Sfactory(this,"ArgumentDeclarationList_3",new SCreator(ArgumentDeclarationList_3_factory));
13057new Sfactory(this,"ArgumentList_2",new SCreator(ArgumentList_2_factory));
13058new Sfactory(this,"IntArgEvent_10",new SCreator(IntArgEvent_10_factory));
10901new Sfactory(this,"CompoundStatement",new SCreator(CompoundStatement_factory)); 13059new Sfactory(this,"CompoundStatement",new SCreator(CompoundStatement_factory));
10902new Sfactory(this,"RotationConstant_1",new SCreator(RotationConstant_1_factory)); 13060new Sfactory(this,"TypecastExpression_3",new SCreator(TypecastExpression_3_factory));
10903new Sfactory(this,"TypecastExpression",new SCreator(TypecastExpression_factory)); 13061new Sfactory(this,"IntArgumentDeclarationList",new SCreator(IntArgumentDeclarationList_factory));
13062new Sfactory(this,"ArgumentDeclarationList_4",new SCreator(ArgumentDeclarationList_4_factory));
10904new Sfactory(this,"SimpleAssignment_3",new SCreator(SimpleAssignment_3_factory)); 13063new Sfactory(this,"SimpleAssignment_3",new SCreator(SimpleAssignment_3_factory));
10905new Sfactory(this,"SimpleAssignment_4",new SCreator(SimpleAssignment_4_factory)); 13064new Sfactory(this,"SimpleAssignment_4",new SCreator(SimpleAssignment_4_factory));
10906new Sfactory(this,"Statement_1",new SCreator(Statement_1_factory)); 13065new Sfactory(this,"Statement_1",new SCreator(Statement_1_factory));
10907new Sfactory(this,"Statement_2",new SCreator(Statement_2_factory)); 13066new Sfactory(this,"Statement_2",new SCreator(Statement_2_factory));
10908new Sfactory(this,"Statement_3",new SCreator(Statement_3_factory));
10909new Sfactory(this,"Statement_4",new SCreator(Statement_4_factory)); 13067new Sfactory(this,"Statement_4",new SCreator(Statement_4_factory));
10910new Sfactory(this,"Statement_5",new SCreator(Statement_5_factory)); 13068new Sfactory(this,"Statement_5",new SCreator(Statement_5_factory));
10911new Sfactory(this,"Statement_6",new SCreator(Statement_6_factory)); 13069new Sfactory(this,"Statement_6",new SCreator(Statement_6_factory));
10912new Sfactory(this,"Statement_7",new SCreator(Statement_7_factory));
10913new Sfactory(this,"Statement_8",new SCreator(Statement_8_factory)); 13070new Sfactory(this,"Statement_8",new SCreator(Statement_8_factory));
10914new Sfactory(this,"Statement_9",new SCreator(Statement_9_factory)); 13071new Sfactory(this,"Statement_9",new SCreator(Statement_9_factory));
10915new Sfactory(this,"ExpressionArgument",new SCreator(ExpressionArgument_factory)); 13072new Sfactory(this,"ExpressionArgument",new SCreator(ExpressionArgument_factory));
@@ -10922,27 +13079,35 @@ new Sfactory(this,"StateBody",new SCreator(StateBody_factory));
10922new Sfactory(this,"Event_7",new SCreator(Event_7_factory)); 13079new Sfactory(this,"Event_7",new SCreator(Event_7_factory));
10923new Sfactory(this,"Event_8",new SCreator(Event_8_factory)); 13080new Sfactory(this,"Event_8",new SCreator(Event_8_factory));
10924new Sfactory(this,"IncrementDecrementExpression_1",new SCreator(IncrementDecrementExpression_1_factory)); 13081new Sfactory(this,"IncrementDecrementExpression_1",new SCreator(IncrementDecrementExpression_1_factory));
10925new Sfactory(this,"IncrementDecrementExpression_3",new SCreator(IncrementDecrementExpression_3_factory)); 13082new Sfactory(this,"IncrementDecrementExpression_2",new SCreator(IncrementDecrementExpression_2_factory));
13083new Sfactory(this,"IntVecVecArgumentDeclarationList_1",new SCreator(IntVecVecArgumentDeclarationList_1_factory));
10926new Sfactory(this,"IncrementDecrementExpression_4",new SCreator(IncrementDecrementExpression_4_factory)); 13084new Sfactory(this,"IncrementDecrementExpression_4",new SCreator(IncrementDecrementExpression_4_factory));
10927new Sfactory(this,"IncrementDecrementExpression_6",new SCreator(IncrementDecrementExpression_6_factory)); 13085new Sfactory(this,"IncrementDecrementExpression_6",new SCreator(IncrementDecrementExpression_6_factory));
13086new Sfactory(this,"IncrementDecrementExpression_7",new SCreator(IncrementDecrementExpression_7_factory));
10928new Sfactory(this,"StateEvent",new SCreator(StateEvent_factory)); 13087new Sfactory(this,"StateEvent",new SCreator(StateEvent_factory));
10929new Sfactory(this,"Event_20",new SCreator(Event_20_factory)); 13088new Sfactory(this,"IntArgEvent_3",new SCreator(IntArgEvent_3_factory));
10930new Sfactory(this,"Event_23",new SCreator(Event_23_factory)); 13089new Sfactory(this,"IntArgEvent_4",new SCreator(IntArgEvent_4_factory));
10931new Sfactory(this,"Event_24",new SCreator(Event_24_factory)); 13090new Sfactory(this,"KeyDeclaration_1",new SCreator(KeyDeclaration_1_factory));
10932new Sfactory(this,"Event_26",new SCreator(Event_26_factory)); 13091new Sfactory(this,"Statement_3",new SCreator(Statement_3_factory));
13092new Sfactory(this,"IntArgEvent_7",new SCreator(IntArgEvent_7_factory));
13093new Sfactory(this,"IntArgEvent_8",new SCreator(IntArgEvent_8_factory));
10933new Sfactory(this,"SimpleAssignment_10",new SCreator(SimpleAssignment_10_factory)); 13094new Sfactory(this,"SimpleAssignment_10",new SCreator(SimpleAssignment_10_factory));
13095new Sfactory(this,"StatementList_2",new SCreator(StatementList_2_factory));
13096new Sfactory(this,"IntRotRotArgStateEvent_1",new SCreator(IntRotRotArgStateEvent_1_factory));
13097new Sfactory(this,"VectorArgEvent_2",new SCreator(VectorArgEvent_2_factory));
10934new Sfactory(this,"Event",new SCreator(Event_factory)); 13098new Sfactory(this,"Event",new SCreator(Event_factory));
10935new Sfactory(this,"SimpleAssignment_14",new SCreator(SimpleAssignment_14_factory)); 13099new Sfactory(this,"SimpleAssignment_14",new SCreator(SimpleAssignment_14_factory));
10936new Sfactory(this,"SimpleAssignment_16",new SCreator(SimpleAssignment_16_factory)); 13100new Sfactory(this,"SimpleAssignment_16",new SCreator(SimpleAssignment_16_factory));
13101new Sfactory(this,"SimpleAssignment_17",new SCreator(SimpleAssignment_17_factory));
13102new Sfactory(this,"SimpleAssignment_18",new SCreator(SimpleAssignment_18_factory));
10937new Sfactory(this,"Statement_10",new SCreator(Statement_10_factory)); 13103new Sfactory(this,"Statement_10",new SCreator(Statement_10_factory));
10938new Sfactory(this,"Statement_11",new SCreator(Statement_11_factory)); 13104new Sfactory(this,"Statement_11",new SCreator(Statement_11_factory));
10939new Sfactory(this,"SimpleAssignment",new SCreator(SimpleAssignment_factory)); 13105new Sfactory(this,"SimpleAssignment",new SCreator(SimpleAssignment_factory));
10940new Sfactory(this,"Statement_13",new SCreator(Statement_13_factory)); 13106new Sfactory(this,"TypecastExpression",new SCreator(TypecastExpression_factory));
10941new Sfactory(this,"Event_15",new SCreator(Event_15_factory)); 13107new Sfactory(this,"JumpStatement_1",new SCreator(JumpStatement_1_factory));
10942new Sfactory(this,"Event_16",new SCreator(Event_16_factory));
10943new Sfactory(this,"Event_32",new SCreator(Event_32_factory));
10944new Sfactory(this,"Event_34",new SCreator(Event_34_factory));
10945new Sfactory(this,"SimpleAssignment_20",new SCreator(SimpleAssignment_20_factory)); 13108new Sfactory(this,"SimpleAssignment_20",new SCreator(SimpleAssignment_20_factory));
13109new Sfactory(this,"Statement_7",new SCreator(Statement_7_factory));
13110new Sfactory(this,"SimpleAssignment_23",new SCreator(SimpleAssignment_23_factory));
10946new Sfactory(this,"SimpleAssignment_24",new SCreator(SimpleAssignment_24_factory)); 13111new Sfactory(this,"SimpleAssignment_24",new SCreator(SimpleAssignment_24_factory));
10947new Sfactory(this,"SimpleAssignment_1",new SCreator(SimpleAssignment_1_factory)); 13112new Sfactory(this,"SimpleAssignment_1",new SCreator(SimpleAssignment_1_factory));
10948new Sfactory(this,"SimpleAssignment_2",new SCreator(SimpleAssignment_2_factory)); 13113new Sfactory(this,"SimpleAssignment_2",new SCreator(SimpleAssignment_2_factory));
@@ -10950,73 +13115,90 @@ new Sfactory(this,"BinaryExpression",new SCreator(BinaryExpression_factory));
10950new Sfactory(this,"FunctionCallExpression",new SCreator(FunctionCallExpression_factory)); 13115new Sfactory(this,"FunctionCallExpression",new SCreator(FunctionCallExpression_factory));
10951new Sfactory(this,"SimpleAssignment_6",new SCreator(SimpleAssignment_6_factory)); 13116new Sfactory(this,"SimpleAssignment_6",new SCreator(SimpleAssignment_6_factory));
10952new Sfactory(this,"StateBody_1",new SCreator(StateBody_1_factory)); 13117new Sfactory(this,"StateBody_1",new SCreator(StateBody_1_factory));
10953new Sfactory(this,"StatementList_2",new SCreator(StatementList_2_factory)); 13118new Sfactory(this,"StateBody_2",new SCreator(StateBody_2_factory));
10954new Sfactory(this,"SimpleAssignment_9",new SCreator(SimpleAssignment_9_factory)); 13119new Sfactory(this,"StateBody_3",new SCreator(StateBody_3_factory));
10955new Sfactory(this,"BinaryExpression_15",new SCreator(BinaryExpression_15_factory)); 13120new Sfactory(this,"StateBody_4",new SCreator(StateBody_4_factory));
10956new Sfactory(this,"BinaryExpression_16",new SCreator(BinaryExpression_16_factory)); 13121new Sfactory(this,"StateBody_5",new SCreator(StateBody_5_factory));
10957new Sfactory(this,"BinaryExpression_17",new SCreator(BinaryExpression_17_factory)); 13122new Sfactory(this,"StateBody_6",new SCreator(StateBody_6_factory));
10958new Sfactory(this,"BinaryExpression_18",new SCreator(BinaryExpression_18_factory)); 13123new Sfactory(this,"StateBody_7",new SCreator(StateBody_7_factory));
10959new Sfactory(this,"Event_25",new SCreator(Event_25_factory)); 13124new Sfactory(this,"StateBody_8",new SCreator(StateBody_8_factory));
10960new Sfactory(this,"Event_9",new SCreator(Event_9_factory)); 13125new Sfactory(this,"StateBody_9",new SCreator(StateBody_9_factory));
10961new Sfactory(this,"Statement",new SCreator(Statement_factory)); 13126new Sfactory(this,"Statement",new SCreator(Statement_factory));
13127new Sfactory(this,"IncrementDecrementExpression_3",new SCreator(IncrementDecrementExpression_3_factory));
10962new Sfactory(this,"JumpStatement",new SCreator(JumpStatement_factory)); 13128new Sfactory(this,"JumpStatement",new SCreator(JumpStatement_factory));
10963new Sfactory(this,"BinaryExpression_11",new SCreator(BinaryExpression_11_factory)); 13129new Sfactory(this,"BinaryExpression_11",new SCreator(BinaryExpression_11_factory));
10964new Sfactory(this,"BinaryExpression_12",new SCreator(BinaryExpression_12_factory)); 13130new Sfactory(this,"IntArgEvent",new SCreator(IntArgEvent_factory));
10965new Sfactory(this,"BinaryExpression_13",new SCreator(BinaryExpression_13_factory)); 13131new Sfactory(this,"IncrementDecrementExpression_8",new SCreator(IncrementDecrementExpression_8_factory));
10966new Sfactory(this,"BinaryExpression_14",new SCreator(BinaryExpression_14_factory)); 13132new Sfactory(this,"BinaryExpression_14",new SCreator(BinaryExpression_14_factory));
13133new Sfactory(this,"BinaryExpression_15",new SCreator(BinaryExpression_15_factory));
13134new Sfactory(this,"BinaryExpression_16",new SCreator(BinaryExpression_16_factory));
10967new Sfactory(this,"BinaryExpression_6",new SCreator(BinaryExpression_6_factory)); 13135new Sfactory(this,"BinaryExpression_6",new SCreator(BinaryExpression_6_factory));
10968new Sfactory(this,"BinaryExpression_7",new SCreator(BinaryExpression_7_factory)); 13136new Sfactory(this,"BinaryExpression_7",new SCreator(BinaryExpression_7_factory));
13137new Sfactory(this,"Typename_2",new SCreator(Typename_2_factory));
13138new Sfactory(this,"Typename_4",new SCreator(Typename_4_factory));
10969new Sfactory(this,"ArgumentList",new SCreator(ArgumentList_factory)); 13139new Sfactory(this,"ArgumentList",new SCreator(ArgumentList_factory));
10970new Sfactory(this,"Event_10",new SCreator(Event_10_factory)); 13140new Sfactory(this,"BinaryExpression_12",new SCreator(BinaryExpression_12_factory));
10971new Sfactory(this,"ConstantExpression_1",new SCreator(ConstantExpression_1_factory)); 13141new Sfactory(this,"BinaryExpression_13",new SCreator(BinaryExpression_13_factory));
10972new Sfactory(this,"Event_12",new SCreator(Event_12_factory)); 13142new Sfactory(this,"GlobalFunctionDefinition_2",new SCreator(GlobalFunctionDefinition_2_factory));
10973new Sfactory(this,"Event_14",new SCreator(Event_14_factory)); 13143new Sfactory(this,"StateChange_2",new SCreator(StateChange_2_factory));
10974new Sfactory(this,"Event_17",new SCreator(Event_17_factory)); 13144new Sfactory(this,"VoidArgEvent_1",new SCreator(VoidArgEvent_1_factory));
10975new Sfactory(this,"Event_18",new SCreator(Event_18_factory));
10976new Sfactory(this,"Event_19",new SCreator(Event_19_factory));
10977new Sfactory(this,"BinaryExpression_10",new SCreator(BinaryExpression_10_factory)); 13145new Sfactory(this,"BinaryExpression_10",new SCreator(BinaryExpression_10_factory));
13146new Sfactory(this,"VoidArgEvent_5",new SCreator(VoidArgEvent_5_factory));
13147new Sfactory(this,"VoidArgEvent_6",new SCreator(VoidArgEvent_6_factory));
13148new Sfactory(this,"VoidArgEvent_7",new SCreator(VoidArgEvent_7_factory));
13149new Sfactory(this,"VoidArgEvent_8",new SCreator(VoidArgEvent_8_factory));
13150new Sfactory(this,"BinaryExpression_17",new SCreator(BinaryExpression_17_factory));
10978new Sfactory(this,"StateEvent_1",new SCreator(StateEvent_1_factory)); 13151new Sfactory(this,"StateEvent_1",new SCreator(StateEvent_1_factory));
10979new Sfactory(this,"VectorConstant",new SCreator(VectorConstant_factory)); 13152new Sfactory(this,"VectorConstant",new SCreator(VectorConstant_factory));
10980new Sfactory(this,"EmptyStatement_1",new SCreator(EmptyStatement_1_factory)); 13153new Sfactory(this,"VectorArgEvent_1",new SCreator(VectorArgEvent_1_factory));
13154new Sfactory(this,"IntDeclaration",new SCreator(IntDeclaration_factory));
13155new Sfactory(this,"VectorArgEvent_3",new SCreator(VectorArgEvent_3_factory));
10981new Sfactory(this,"TypecastExpression_4",new SCreator(TypecastExpression_4_factory)); 13156new Sfactory(this,"TypecastExpression_4",new SCreator(TypecastExpression_4_factory));
10982new Sfactory(this,"TypecastExpression_6",new SCreator(TypecastExpression_6_factory)); 13157new Sfactory(this,"TypecastExpression_6",new SCreator(TypecastExpression_6_factory));
10983new Sfactory(this,"TypecastExpression_7",new SCreator(TypecastExpression_7_factory)); 13158new Sfactory(this,"TypecastExpression_7",new SCreator(TypecastExpression_7_factory));
10984new Sfactory(this,"FunctionCall",new SCreator(FunctionCall_factory)); 13159new Sfactory(this,"FunctionCall",new SCreator(FunctionCall_factory));
10985new Sfactory(this,"Event_27",new SCreator(Event_27_factory));
10986new Sfactory(this,"Event_28",new SCreator(Event_28_factory));
10987new Sfactory(this,"Event_29",new SCreator(Event_29_factory));
10988new Sfactory(this,"ListConstant_1",new SCreator(ListConstant_1_factory)); 13160new Sfactory(this,"ListConstant_1",new SCreator(ListConstant_1_factory));
13161new Sfactory(this,"BinaryExpression_18",new SCreator(BinaryExpression_18_factory));
10989new Sfactory(this,"Event_6",new SCreator(Event_6_factory)); 13162new Sfactory(this,"Event_6",new SCreator(Event_6_factory));
13163new Sfactory(this,"KeyArgEvent_2",new SCreator(KeyArgEvent_2_factory));
10990new Sfactory(this,"Declaration_1",new SCreator(Declaration_1_factory)); 13164new Sfactory(this,"Declaration_1",new SCreator(Declaration_1_factory));
13165new Sfactory(this,"EmptyStatement_1",new SCreator(EmptyStatement_1_factory));
10991new Sfactory(this,"SimpleAssignment_7",new SCreator(SimpleAssignment_7_factory)); 13166new Sfactory(this,"SimpleAssignment_7",new SCreator(SimpleAssignment_7_factory));
10992new Sfactory(this,"ForLoop",new SCreator(ForLoop_factory)); 13167new Sfactory(this,"ForLoop",new SCreator(ForLoop_factory));
10993new Sfactory(this,"ForLoop_2",new SCreator(ForLoop_2_factory)); 13168new Sfactory(this,"ForLoop_2",new SCreator(ForLoop_2_factory));
10994new Sfactory(this,"Event_30",new SCreator(Event_30_factory)); 13169new Sfactory(this,"KeyIntIntArgStateEvent_1",new SCreator(KeyIntIntArgStateEvent_1_factory));
10995new Sfactory(this,"Event_31",new SCreator(Event_31_factory)); 13170new Sfactory(this,"KeyArgumentDeclarationList_1",new SCreator(KeyArgumentDeclarationList_1_factory));
10996new Sfactory(this,"Event_33",new SCreator(Event_33_factory));
10997new Sfactory(this,"GlobalFunctionDefinition_1",new SCreator(GlobalFunctionDefinition_1_factory)); 13171new Sfactory(this,"GlobalFunctionDefinition_1",new SCreator(GlobalFunctionDefinition_1_factory));
10998new Sfactory(this,"JumpLabel_1",new SCreator(JumpLabel_1_factory));
10999new Sfactory(this,"IfStatement",new SCreator(IfStatement_factory)); 13172new Sfactory(this,"IfStatement",new SCreator(IfStatement_factory));
11000new Sfactory(this,"ForLoopStatement_1",new SCreator(ForLoopStatement_1_factory)); 13173new Sfactory(this,"ForLoopStatement_1",new SCreator(ForLoopStatement_1_factory));
11001new Sfactory(this,"ForLoopStatement_2",new SCreator(ForLoopStatement_2_factory)); 13174new Sfactory(this,"ForLoopStatement_2",new SCreator(ForLoopStatement_2_factory));
11002new Sfactory(this,"ForLoopStatement_3",new SCreator(ForLoopStatement_3_factory)); 13175new Sfactory(this,"ForLoopStatement_3",new SCreator(ForLoopStatement_3_factory));
11003new Sfactory(this,"ArgumentDeclarationList_4",new SCreator(ArgumentDeclarationList_4_factory)); 13176new Sfactory(this,"IntRotRotArgumentDeclarationList",new SCreator(IntRotRotArgumentDeclarationList_factory));
11004new Sfactory(this,"ArgumentDeclarationList_5",new SCreator(ArgumentDeclarationList_5_factory)); 13177new Sfactory(this,"IntArgEvent_1",new SCreator(IntArgEvent_1_factory));
11005new Sfactory(this,"EmptyStatement",new SCreator(EmptyStatement_factory)); 13178new Sfactory(this,"IntArgEvent_2",new SCreator(IntArgEvent_2_factory));
11006new Sfactory(this,"WhileStatement",new SCreator(WhileStatement_factory)); 13179new Sfactory(this,"WhileStatement",new SCreator(WhileStatement_factory));
11007new Sfactory(this,"ForLoop_1",new SCreator(ForLoop_1_factory)); 13180new Sfactory(this,"ForLoop_1",new SCreator(ForLoop_1_factory));
11008new Sfactory(this,"Constant_2",new SCreator(Constant_2_factory)); 13181new Sfactory(this,"Constant_2",new SCreator(Constant_2_factory));
11009new Sfactory(this,"StatementList",new SCreator(StatementList_factory)); 13182new Sfactory(this,"VoidArgEvent",new SCreator(VoidArgEvent_factory));
11010new Sfactory(this,"StateBody_2",new SCreator(StateBody_2_factory)); 13183new Sfactory(this,"RotDeclaration",new SCreator(RotDeclaration_factory));
13184new Sfactory(this,"WhileStatement_1",new SCreator(WhileStatement_1_factory));
11011new Sfactory(this,"WhileStatement_2",new SCreator(WhileStatement_2_factory)); 13185new Sfactory(this,"WhileStatement_2",new SCreator(WhileStatement_2_factory));
13186new Sfactory(this,"VectorArgStateEvent_1",new SCreator(VectorArgStateEvent_1_factory));
11012new Sfactory(this,"IdentExpression_1",new SCreator(IdentExpression_1_factory)); 13187new Sfactory(this,"IdentExpression_1",new SCreator(IdentExpression_1_factory));
13188new Sfactory(this,"VectorArgumentDeclarationList",new SCreator(VectorArgumentDeclarationList_factory));
11013new Sfactory(this,"States",new SCreator(States_factory)); 13189new Sfactory(this,"States",new SCreator(States_factory));
13190new Sfactory(this,"VoidArgStateEvent",new SCreator(VoidArgStateEvent_factory));
11014} 13191}
11015public static object ExpressionArgument_1_factory(Parser yyp) { return new ExpressionArgument_1(yyp); } 13192public static object ExpressionArgument_1_factory(Parser yyp) { return new ExpressionArgument_1(yyp); }
11016public static object SimpleAssignment_8_factory(Parser yyp) { return new SimpleAssignment_8(yyp); } 13193public static object VectorArgStateEvent_factory(Parser yyp) { return new VectorArgStateEvent(yyp); }
13194public static object IntVecVecArgStateEvent_factory(Parser yyp) { return new IntVecVecArgStateEvent(yyp); }
13195public static object IntArgStateEvent_1_factory(Parser yyp) { return new IntArgStateEvent_1(yyp); }
13196public static object SimpleAssignment_9_factory(Parser yyp) { return new SimpleAssignment_9(yyp); }
11017public static object StatementList_1_factory(Parser yyp) { return new StatementList_1(yyp); } 13197public static object StatementList_1_factory(Parser yyp) { return new StatementList_1(yyp); }
13198public static object RotDeclaration_1_factory(Parser yyp) { return new RotDeclaration_1(yyp); }
13199public static object IntRotRotArgEvent_1_factory(Parser yyp) { return new IntRotRotArgEvent_1(yyp); }
11018public static object StateChange_1_factory(Parser yyp) { return new StateChange_1(yyp); } 13200public static object StateChange_1_factory(Parser yyp) { return new StateChange_1(yyp); }
11019public static object StateChange_2_factory(Parser yyp) { return new StateChange_2(yyp); } 13201public static object EmptyStatement_factory(Parser yyp) { return new EmptyStatement(yyp); }
11020public static object Declaration_factory(Parser yyp) { return new Declaration(yyp); } 13202public static object Declaration_factory(Parser yyp) { return new Declaration(yyp); }
11021public static object IdentExpression_factory(Parser yyp) { return new IdentExpression(yyp); } 13203public static object IdentExpression_factory(Parser yyp) { return new IdentExpression(yyp); }
11022public static object error_factory(Parser yyp) { return new error(yyp); } 13204public static object error_factory(Parser yyp) { return new error(yyp); }
@@ -11029,20 +13211,25 @@ public static object SimpleAssignment_19_factory(Parser yyp) { return new Simple
11029public static object BinaryExpression_9_factory(Parser yyp) { return new BinaryExpression_9(yyp); } 13211public static object BinaryExpression_9_factory(Parser yyp) { return new BinaryExpression_9(yyp); }
11030public static object VectorConstant_1_factory(Parser yyp) { return new VectorConstant_1(yyp); } 13212public static object VectorConstant_1_factory(Parser yyp) { return new VectorConstant_1(yyp); }
11031public static object ParenthesisExpression_factory(Parser yyp) { return new ParenthesisExpression(yyp); } 13213public static object ParenthesisExpression_factory(Parser yyp) { return new ParenthesisExpression(yyp); }
13214public static object StatementList_factory(Parser yyp) { return new StatementList(yyp); }
13215public static object IntRotRotArgEvent_factory(Parser yyp) { return new IntRotRotArgEvent(yyp); }
11032public static object UnaryExpression_factory(Parser yyp) { return new UnaryExpression(yyp); } 13216public static object UnaryExpression_factory(Parser yyp) { return new UnaryExpression(yyp); }
11033public static object IdentDotExpression_1_factory(Parser yyp) { return new IdentDotExpression_1(yyp); } 13217public static object IdentDotExpression_1_factory(Parser yyp) { return new IdentDotExpression_1(yyp); }
11034public static object ArgumentList_4_factory(Parser yyp) { return new ArgumentList_4(yyp); } 13218public static object ArgumentList_4_factory(Parser yyp) { return new ArgumentList_4(yyp); }
11035public static object Typename_factory(Parser yyp) { return new Typename(yyp); } 13219public static object Typename_factory(Parser yyp) { return new Typename(yyp); }
11036public static object IfStatement_1_factory(Parser yyp) { return new IfStatement_1(yyp); } 13220public static object IfStatement_1_factory(Parser yyp) { return new IfStatement_1(yyp); }
13221public static object RotationConstant_1_factory(Parser yyp) { return new RotationConstant_1(yyp); }
11037public static object Assignment_factory(Parser yyp) { return new Assignment(yyp); } 13222public static object Assignment_factory(Parser yyp) { return new Assignment(yyp); }
13223public static object IfStatement_4_factory(Parser yyp) { return new IfStatement_4(yyp); }
11038public static object CompoundStatement_1_factory(Parser yyp) { return new CompoundStatement_1(yyp); } 13224public static object CompoundStatement_1_factory(Parser yyp) { return new CompoundStatement_1(yyp); }
11039public static object CompoundStatement_2_factory(Parser yyp) { return new CompoundStatement_2(yyp); } 13225public static object CompoundStatement_2_factory(Parser yyp) { return new CompoundStatement_2(yyp); }
13226public static object KeyIntIntArgumentDeclarationList_1_factory(Parser yyp) { return new KeyIntIntArgumentDeclarationList_1(yyp); }
11040public static object BinaryExpression_8_factory(Parser yyp) { return new BinaryExpression_8(yyp); } 13227public static object BinaryExpression_8_factory(Parser yyp) { return new BinaryExpression_8(yyp); }
13228public static object VectorArgEvent_factory(Parser yyp) { return new VectorArgEvent(yyp); }
11041public static object ReturnStatement_1_factory(Parser yyp) { return new ReturnStatement_1(yyp); } 13229public static object ReturnStatement_1_factory(Parser yyp) { return new ReturnStatement_1(yyp); }
11042public static object IdentDotExpression_factory(Parser yyp) { return new IdentDotExpression(yyp); } 13230public static object IdentDotExpression_factory(Parser yyp) { return new IdentDotExpression(yyp); }
11043public static object Argument_factory(Parser yyp) { return new Argument(yyp); } 13231public static object Argument_factory(Parser yyp) { return new Argument(yyp); }
11044public static object State_2_factory(Parser yyp) { return new State_2(yyp); } 13232public static object State_2_factory(Parser yyp) { return new State_2(yyp); }
11045public static object WhileStatement_1_factory(Parser yyp) { return new WhileStatement_1(yyp); }
11046public static object GlobalDefinitions_3_factory(Parser yyp) { return new GlobalDefinitions_3(yyp); } 13233public static object GlobalDefinitions_3_factory(Parser yyp) { return new GlobalDefinitions_3(yyp); }
11047public static object GlobalDefinitions_4_factory(Parser yyp) { return new GlobalDefinitions_4(yyp); } 13234public static object GlobalDefinitions_4_factory(Parser yyp) { return new GlobalDefinitions_4(yyp); }
11048public static object Event_1_factory(Parser yyp) { return new Event_1(yyp); } 13235public static object Event_1_factory(Parser yyp) { return new Event_1(yyp); }
@@ -11052,9 +13239,9 @@ public static object Event_4_factory(Parser yyp) { return new Event_4(yyp); }
11052public static object Event_5_factory(Parser yyp) { return new Event_5(yyp); } 13239public static object Event_5_factory(Parser yyp) { return new Event_5(yyp); }
11053public static object SimpleAssignment_5_factory(Parser yyp) { return new SimpleAssignment_5(yyp); } 13240public static object SimpleAssignment_5_factory(Parser yyp) { return new SimpleAssignment_5(yyp); }
11054public static object Typename_1_factory(Parser yyp) { return new Typename_1(yyp); } 13241public static object Typename_1_factory(Parser yyp) { return new Typename_1(yyp); }
11055public static object Typename_2_factory(Parser yyp) { return new Typename_2(yyp); } 13242public static object VoidArgStateEvent_1_factory(Parser yyp) { return new VoidArgStateEvent_1(yyp); }
11056public static object Typename_3_factory(Parser yyp) { return new Typename_3(yyp); } 13243public static object Typename_3_factory(Parser yyp) { return new Typename_3(yyp); }
11057public static object Typename_4_factory(Parser yyp) { return new Typename_4(yyp); } 13244public static object IntRotRotArgStateEvent_factory(Parser yyp) { return new IntRotRotArgStateEvent(yyp); }
11058public static object Typename_5_factory(Parser yyp) { return new Typename_5(yyp); } 13245public static object Typename_5_factory(Parser yyp) { return new Typename_5(yyp); }
11059public static object Typename_6_factory(Parser yyp) { return new Typename_6(yyp); } 13246public static object Typename_6_factory(Parser yyp) { return new Typename_6(yyp); }
11060public static object Typename_7_factory(Parser yyp) { return new Typename_7(yyp); } 13247public static object Typename_7_factory(Parser yyp) { return new Typename_7(yyp); }
@@ -11062,10 +13249,16 @@ public static object ArgumentDeclarationList_factory(Parser yyp) { return new Ar
11062public static object ConstantExpression_factory(Parser yyp) { return new ConstantExpression(yyp); } 13249public static object ConstantExpression_factory(Parser yyp) { return new ConstantExpression(yyp); }
11063public static object LSLProgramRoot_1_factory(Parser yyp) { return new LSLProgramRoot_1(yyp); } 13250public static object LSLProgramRoot_1_factory(Parser yyp) { return new LSLProgramRoot_1(yyp); }
11064public static object LSLProgramRoot_2_factory(Parser yyp) { return new LSLProgramRoot_2(yyp); } 13251public static object LSLProgramRoot_2_factory(Parser yyp) { return new LSLProgramRoot_2(yyp); }
13252public static object KeyIntIntArgEvent_1_factory(Parser yyp) { return new KeyIntIntArgEvent_1(yyp); }
11065public static object States_1_factory(Parser yyp) { return new States_1(yyp); } 13253public static object States_1_factory(Parser yyp) { return new States_1(yyp); }
11066public static object States_2_factory(Parser yyp) { return new States_2(yyp); } 13254public static object States_2_factory(Parser yyp) { return new States_2(yyp); }
11067public static object FunctionCallExpression_1_factory(Parser yyp) { return new FunctionCallExpression_1(yyp); } 13255public static object FunctionCallExpression_1_factory(Parser yyp) { return new FunctionCallExpression_1(yyp); }
13256public static object KeyArgEvent_1_factory(Parser yyp) { return new KeyArgEvent_1(yyp); }
11068public static object ForLoopStatement_factory(Parser yyp) { return new ForLoopStatement(yyp); } 13257public static object ForLoopStatement_factory(Parser yyp) { return new ForLoopStatement(yyp); }
13258public static object IntArgStateEvent_factory(Parser yyp) { return new IntArgStateEvent(yyp); }
13259public static object StateBody_15_factory(Parser yyp) { return new StateBody_15(yyp); }
13260public static object IntRotRotArgumentDeclarationList_1_factory(Parser yyp) { return new IntRotRotArgumentDeclarationList_1(yyp); }
13261public static object IntArgEvent_9_factory(Parser yyp) { return new IntArgEvent_9(yyp); }
11069public static object DoWhileStatement_1_factory(Parser yyp) { return new DoWhileStatement_1(yyp); } 13262public static object DoWhileStatement_1_factory(Parser yyp) { return new DoWhileStatement_1(yyp); }
11070public static object DoWhileStatement_2_factory(Parser yyp) { return new DoWhileStatement_2(yyp); } 13263public static object DoWhileStatement_2_factory(Parser yyp) { return new DoWhileStatement_2(yyp); }
11071public static object ForLoopStatement_4_factory(Parser yyp) { return new ForLoopStatement_4(yyp); } 13264public static object ForLoopStatement_4_factory(Parser yyp) { return new ForLoopStatement_4(yyp); }
@@ -11074,74 +13267,93 @@ public static object SimpleAssignment_12_factory(Parser yyp) { return new Simple
11074public static object SimpleAssignment_13_factory(Parser yyp) { return new SimpleAssignment_13(yyp); } 13267public static object SimpleAssignment_13_factory(Parser yyp) { return new SimpleAssignment_13(yyp); }
11075public static object JumpLabel_factory(Parser yyp) { return new JumpLabel(yyp); } 13268public static object JumpLabel_factory(Parser yyp) { return new JumpLabel(yyp); }
11076public static object SimpleAssignment_15_factory(Parser yyp) { return new SimpleAssignment_15(yyp); } 13269public static object SimpleAssignment_15_factory(Parser yyp) { return new SimpleAssignment_15(yyp); }
11077public static object SimpleAssignment_17_factory(Parser yyp) { return new SimpleAssignment_17(yyp); } 13270public static object IntVecVecArgEvent_factory(Parser yyp) { return new IntVecVecArgEvent(yyp); }
11078public static object SimpleAssignment_18_factory(Parser yyp) { return new SimpleAssignment_18(yyp); } 13271public static object VecDeclaration_factory(Parser yyp) { return new VecDeclaration(yyp); }
11079public static object JumpStatement_1_factory(Parser yyp) { return new JumpStatement_1(yyp); } 13272public static object StateBody_14_factory(Parser yyp) { return new StateBody_14(yyp); }
11080public static object GlobalDefinitions_factory(Parser yyp) { return new GlobalDefinitions(yyp); } 13273public static object GlobalDefinitions_factory(Parser yyp) { return new GlobalDefinitions(yyp); }
13274public static object StateBody_16_factory(Parser yyp) { return new StateBody_16(yyp); }
13275public static object KeyIntIntArgumentDeclarationList_factory(Parser yyp) { return new KeyIntIntArgumentDeclarationList(yyp); }
13276public static object ConstantExpression_1_factory(Parser yyp) { return new ConstantExpression_1(yyp); }
13277public static object VoidArgEvent_4_factory(Parser yyp) { return new VoidArgEvent_4(yyp); }
11081public static object FunctionCall_1_factory(Parser yyp) { return new FunctionCall_1(yyp); } 13278public static object FunctionCall_1_factory(Parser yyp) { return new FunctionCall_1(yyp); }
11082public static object ArgumentList_3_factory(Parser yyp) { return new ArgumentList_3(yyp); } 13279public static object Assignment_1_factory(Parser yyp) { return new Assignment_1(yyp); }
11083public static object Assignment_2_factory(Parser yyp) { return new Assignment_2(yyp); } 13280public static object Assignment_2_factory(Parser yyp) { return new Assignment_2(yyp); }
13281public static object IntVecVecArgEvent_1_factory(Parser yyp) { return new IntVecVecArgEvent_1(yyp); }
11084public static object TypecastExpression_1_factory(Parser yyp) { return new TypecastExpression_1(yyp); } 13282public static object TypecastExpression_1_factory(Parser yyp) { return new TypecastExpression_1(yyp); }
11085public static object SimpleAssignment_21_factory(Parser yyp) { return new SimpleAssignment_21(yyp); } 13283public static object SimpleAssignment_21_factory(Parser yyp) { return new SimpleAssignment_21(yyp); }
11086public static object SimpleAssignment_22_factory(Parser yyp) { return new SimpleAssignment_22(yyp); } 13284public static object SimpleAssignment_22_factory(Parser yyp) { return new SimpleAssignment_22(yyp); }
11087public static object SimpleAssignment_23_factory(Parser yyp) { return new SimpleAssignment_23(yyp); } 13285public static object KeyIntIntArgStateEvent_factory(Parser yyp) { return new KeyIntIntArgStateEvent(yyp); }
11088public static object TypecastExpression_9_factory(Parser yyp) { return new TypecastExpression_9(yyp); } 13286public static object TypecastExpression_9_factory(Parser yyp) { return new TypecastExpression_9(yyp); }
13287public static object VoidArgEvent_2_factory(Parser yyp) { return new VoidArgEvent_2(yyp); }
13288public static object VoidArgEvent_3_factory(Parser yyp) { return new VoidArgEvent_3(yyp); }
11089public static object ArgumentDeclarationList_1_factory(Parser yyp) { return new ArgumentDeclarationList_1(yyp); } 13289public static object ArgumentDeclarationList_1_factory(Parser yyp) { return new ArgumentDeclarationList_1(yyp); }
11090public static object ArgumentDeclarationList_2_factory(Parser yyp) { return new ArgumentDeclarationList_2(yyp); } 13290public static object ArgumentDeclarationList_2_factory(Parser yyp) { return new ArgumentDeclarationList_2(yyp); }
11091public static object ArgumentDeclarationList_3_factory(Parser yyp) { return new ArgumentDeclarationList_3(yyp); }
11092public static object GlobalDefinitions_1_factory(Parser yyp) { return new GlobalDefinitions_1(yyp); } 13291public static object GlobalDefinitions_1_factory(Parser yyp) { return new GlobalDefinitions_1(yyp); }
11093public static object GlobalDefinitions_2_factory(Parser yyp) { return new GlobalDefinitions_2(yyp); } 13292public static object GlobalDefinitions_2_factory(Parser yyp) { return new GlobalDefinitions_2(yyp); }
11094public static object IncrementDecrementExpression_factory(Parser yyp) { return new IncrementDecrementExpression(yyp); } 13293public static object IncrementDecrementExpression_factory(Parser yyp) { return new IncrementDecrementExpression(yyp); }
11095public static object GlobalVariableDeclaration_factory(Parser yyp) { return new GlobalVariableDeclaration(yyp); } 13294public static object GlobalVariableDeclaration_factory(Parser yyp) { return new GlobalVariableDeclaration(yyp); }
11096public static object Event_11_factory(Parser yyp) { return new Event_11(yyp); } 13295public static object IntArgumentDeclarationList_1_factory(Parser yyp) { return new IntArgumentDeclarationList_1(yyp); }
13296public static object IntDeclaration_1_factory(Parser yyp) { return new IntDeclaration_1(yyp); }
13297public static object ArgumentDeclarationList_5_factory(Parser yyp) { return new ArgumentDeclarationList_5(yyp); }
13298public static object IntVecVecArgumentDeclarationList_factory(Parser yyp) { return new IntVecVecArgumentDeclarationList(yyp); }
13299public static object VectorArgumentDeclarationList_1_factory(Parser yyp) { return new VectorArgumentDeclarationList_1(yyp); }
13300public static object KeyArgumentDeclarationList_factory(Parser yyp) { return new KeyArgumentDeclarationList(yyp); }
11097public static object TypecastExpression_2_factory(Parser yyp) { return new TypecastExpression_2(yyp); } 13301public static object TypecastExpression_2_factory(Parser yyp) { return new TypecastExpression_2(yyp); }
11098public static object TypecastExpression_3_factory(Parser yyp) { return new TypecastExpression_3(yyp); } 13302public static object KeyArgStateEvent_factory(Parser yyp) { return new KeyArgStateEvent(yyp); }
11099public static object TypecastExpression_5_factory(Parser yyp) { return new TypecastExpression_5(yyp); } 13303public static object TypecastExpression_5_factory(Parser yyp) { return new TypecastExpression_5(yyp); }
11100public static object TypecastExpression_8_factory(Parser yyp) { return new TypecastExpression_8(yyp); } 13304public static object TypecastExpression_8_factory(Parser yyp) { return new TypecastExpression_8(yyp); }
11101public static object Constant_1_factory(Parser yyp) { return new Constant_1(yyp); } 13305public static object Constant_1_factory(Parser yyp) { return new Constant_1(yyp); }
11102public static object Expression_factory(Parser yyp) { return new Expression(yyp); } 13306public static object Expression_factory(Parser yyp) { return new Expression(yyp); }
11103public static object Constant_3_factory(Parser yyp) { return new Constant_3(yyp); } 13307public static object Constant_3_factory(Parser yyp) { return new Constant_3(yyp); }
11104public static object Constant_4_factory(Parser yyp) { return new Constant_4(yyp); } 13308public static object Constant_4_factory(Parser yyp) { return new Constant_4(yyp); }
13309public static object IntArgEvent_5_factory(Parser yyp) { return new IntArgEvent_5(yyp); }
11105public static object BinaryExpression_1_factory(Parser yyp) { return new BinaryExpression_1(yyp); } 13310public static object BinaryExpression_1_factory(Parser yyp) { return new BinaryExpression_1(yyp); }
11106public static object IfStatement_2_factory(Parser yyp) { return new IfStatement_2(yyp); } 13311public static object IfStatement_2_factory(Parser yyp) { return new IfStatement_2(yyp); }
11107public static object IfStatement_3_factory(Parser yyp) { return new IfStatement_3(yyp); } 13312public static object IfStatement_3_factory(Parser yyp) { return new IfStatement_3(yyp); }
11108public static object IfStatement_4_factory(Parser yyp) { return new IfStatement_4(yyp); } 13313public static object KeyArgEvent_factory(Parser yyp) { return new KeyArgEvent(yyp); }
11109public static object ReturnStatement_factory(Parser yyp) { return new ReturnStatement(yyp); }
11110public static object Event_2_factory(Parser yyp) { return new Event_2(yyp); } 13314public static object Event_2_factory(Parser yyp) { return new Event_2(yyp); }
13315public static object JumpLabel_1_factory(Parser yyp) { return new JumpLabel_1(yyp); }
11111public static object RotationConstant_factory(Parser yyp) { return new RotationConstant(yyp); } 13316public static object RotationConstant_factory(Parser yyp) { return new RotationConstant(yyp); }
11112public static object Statement_12_factory(Parser yyp) { return new Statement_12(yyp); } 13317public static object Statement_12_factory(Parser yyp) { return new Statement_12(yyp); }
13318public static object Statement_13_factory(Parser yyp) { return new Statement_13(yyp); }
11113public static object UnaryExpression_1_factory(Parser yyp) { return new UnaryExpression_1(yyp); } 13319public static object UnaryExpression_1_factory(Parser yyp) { return new UnaryExpression_1(yyp); }
11114public static object UnaryExpression_2_factory(Parser yyp) { return new UnaryExpression_2(yyp); } 13320public static object UnaryExpression_2_factory(Parser yyp) { return new UnaryExpression_2(yyp); }
11115public static object UnaryExpression_3_factory(Parser yyp) { return new UnaryExpression_3(yyp); } 13321public static object UnaryExpression_3_factory(Parser yyp) { return new UnaryExpression_3(yyp); }
11116public static object ArgumentList_1_factory(Parser yyp) { return new ArgumentList_1(yyp); } 13322public static object ArgumentList_1_factory(Parser yyp) { return new ArgumentList_1(yyp); }
11117public static object ArgumentList_2_factory(Parser yyp) { return new ArgumentList_2(yyp); } 13323public static object KeyIntIntArgEvent_factory(Parser yyp) { return new KeyIntIntArgEvent(yyp); }
13324public static object ArgumentList_3_factory(Parser yyp) { return new ArgumentList_3(yyp); }
11118public static object Constant_factory(Parser yyp) { return new Constant(yyp); } 13325public static object Constant_factory(Parser yyp) { return new Constant(yyp); }
11119public static object State_factory(Parser yyp) { return new State(yyp); } 13326public static object State_factory(Parser yyp) { return new State(yyp); }
11120public static object Event_13_factory(Parser yyp) { return new Event_13(yyp); } 13327public static object StateBody_13_factory(Parser yyp) { return new StateBody_13(yyp); }
13328public static object KeyArgStateEvent_1_factory(Parser yyp) { return new KeyArgStateEvent_1(yyp); }
13329public static object SimpleAssignment_8_factory(Parser yyp) { return new SimpleAssignment_8(yyp); }
11121public static object LSLProgramRoot_factory(Parser yyp) { return new LSLProgramRoot(yyp); } 13330public static object LSLProgramRoot_factory(Parser yyp) { return new LSLProgramRoot(yyp); }
11122public static object StateChange_factory(Parser yyp) { return new StateChange(yyp); } 13331public static object StateChange_factory(Parser yyp) { return new StateChange(yyp); }
11123public static object IncrementDecrementExpression_2_factory(Parser yyp) { return new IncrementDecrementExpression_2(yyp); } 13332public static object VecDeclaration_1_factory(Parser yyp) { return new VecDeclaration_1(yyp); }
11124public static object GlobalVariableDeclaration_1_factory(Parser yyp) { return new GlobalVariableDeclaration_1(yyp); } 13333public static object GlobalVariableDeclaration_1_factory(Parser yyp) { return new GlobalVariableDeclaration_1(yyp); }
11125public static object GlobalVariableDeclaration_2_factory(Parser yyp) { return new GlobalVariableDeclaration_2(yyp); } 13334public static object GlobalVariableDeclaration_2_factory(Parser yyp) { return new GlobalVariableDeclaration_2(yyp); }
11126public static object IncrementDecrementExpression_5_factory(Parser yyp) { return new IncrementDecrementExpression_5(yyp); } 13335public static object IncrementDecrementExpression_5_factory(Parser yyp) { return new IncrementDecrementExpression_5(yyp); }
11127public static object GlobalFunctionDefinition_2_factory(Parser yyp) { return new GlobalFunctionDefinition_2(yyp); } 13336public static object ReturnStatement_factory(Parser yyp) { return new ReturnStatement(yyp); }
11128public static object IncrementDecrementExpression_7_factory(Parser yyp) { return new IncrementDecrementExpression_7(yyp); } 13337public static object StateBody_10_factory(Parser yyp) { return new StateBody_10(yyp); }
11129public static object IncrementDecrementExpression_8_factory(Parser yyp) { return new IncrementDecrementExpression_8(yyp); } 13338public static object StateBody_11_factory(Parser yyp) { return new StateBody_11(yyp); }
11130public static object Assignment_1_factory(Parser yyp) { return new Assignment_1(yyp); } 13339public static object StateBody_12_factory(Parser yyp) { return new StateBody_12(yyp); }
11131public static object Event_21_factory(Parser yyp) { return new Event_21(yyp); } 13340public static object IntVecVecArgStateEvent_1_factory(Parser yyp) { return new IntVecVecArgStateEvent_1(yyp); }
11132public static object Event_22_factory(Parser yyp) { return new Event_22(yyp); } 13341public static object KeyDeclaration_factory(Parser yyp) { return new KeyDeclaration(yyp); }
13342public static object IntArgEvent_6_factory(Parser yyp) { return new IntArgEvent_6(yyp); }
13343public static object ArgumentDeclarationList_3_factory(Parser yyp) { return new ArgumentDeclarationList_3(yyp); }
13344public static object ArgumentList_2_factory(Parser yyp) { return new ArgumentList_2(yyp); }
13345public static object IntArgEvent_10_factory(Parser yyp) { return new IntArgEvent_10(yyp); }
11133public static object CompoundStatement_factory(Parser yyp) { return new CompoundStatement(yyp); } 13346public static object CompoundStatement_factory(Parser yyp) { return new CompoundStatement(yyp); }
11134public static object RotationConstant_1_factory(Parser yyp) { return new RotationConstant_1(yyp); } 13347public static object TypecastExpression_3_factory(Parser yyp) { return new TypecastExpression_3(yyp); }
11135public static object TypecastExpression_factory(Parser yyp) { return new TypecastExpression(yyp); } 13348public static object IntArgumentDeclarationList_factory(Parser yyp) { return new IntArgumentDeclarationList(yyp); }
13349public static object ArgumentDeclarationList_4_factory(Parser yyp) { return new ArgumentDeclarationList_4(yyp); }
11136public static object SimpleAssignment_3_factory(Parser yyp) { return new SimpleAssignment_3(yyp); } 13350public static object SimpleAssignment_3_factory(Parser yyp) { return new SimpleAssignment_3(yyp); }
11137public static object SimpleAssignment_4_factory(Parser yyp) { return new SimpleAssignment_4(yyp); } 13351public static object SimpleAssignment_4_factory(Parser yyp) { return new SimpleAssignment_4(yyp); }
11138public static object Statement_1_factory(Parser yyp) { return new Statement_1(yyp); } 13352public static object Statement_1_factory(Parser yyp) { return new Statement_1(yyp); }
11139public static object Statement_2_factory(Parser yyp) { return new Statement_2(yyp); } 13353public static object Statement_2_factory(Parser yyp) { return new Statement_2(yyp); }
11140public static object Statement_3_factory(Parser yyp) { return new Statement_3(yyp); }
11141public static object Statement_4_factory(Parser yyp) { return new Statement_4(yyp); } 13354public static object Statement_4_factory(Parser yyp) { return new Statement_4(yyp); }
11142public static object Statement_5_factory(Parser yyp) { return new Statement_5(yyp); } 13355public static object Statement_5_factory(Parser yyp) { return new Statement_5(yyp); }
11143public static object Statement_6_factory(Parser yyp) { return new Statement_6(yyp); } 13356public static object Statement_6_factory(Parser yyp) { return new Statement_6(yyp); }
11144public static object Statement_7_factory(Parser yyp) { return new Statement_7(yyp); }
11145public static object Statement_8_factory(Parser yyp) { return new Statement_8(yyp); } 13357public static object Statement_8_factory(Parser yyp) { return new Statement_8(yyp); }
11146public static object Statement_9_factory(Parser yyp) { return new Statement_9(yyp); } 13358public static object Statement_9_factory(Parser yyp) { return new Statement_9(yyp); }
11147public static object ExpressionArgument_factory(Parser yyp) { return new ExpressionArgument(yyp); } 13359public static object ExpressionArgument_factory(Parser yyp) { return new ExpressionArgument(yyp); }
@@ -11154,27 +13366,35 @@ public static object StateBody_factory(Parser yyp) { return new StateBody(yyp);
11154public static object Event_7_factory(Parser yyp) { return new Event_7(yyp); } 13366public static object Event_7_factory(Parser yyp) { return new Event_7(yyp); }
11155public static object Event_8_factory(Parser yyp) { return new Event_8(yyp); } 13367public static object Event_8_factory(Parser yyp) { return new Event_8(yyp); }
11156public static object IncrementDecrementExpression_1_factory(Parser yyp) { return new IncrementDecrementExpression_1(yyp); } 13368public static object IncrementDecrementExpression_1_factory(Parser yyp) { return new IncrementDecrementExpression_1(yyp); }
11157public static object IncrementDecrementExpression_3_factory(Parser yyp) { return new IncrementDecrementExpression_3(yyp); } 13369public static object IncrementDecrementExpression_2_factory(Parser yyp) { return new IncrementDecrementExpression_2(yyp); }
13370public static object IntVecVecArgumentDeclarationList_1_factory(Parser yyp) { return new IntVecVecArgumentDeclarationList_1(yyp); }
11158public static object IncrementDecrementExpression_4_factory(Parser yyp) { return new IncrementDecrementExpression_4(yyp); } 13371public static object IncrementDecrementExpression_4_factory(Parser yyp) { return new IncrementDecrementExpression_4(yyp); }
11159public static object IncrementDecrementExpression_6_factory(Parser yyp) { return new IncrementDecrementExpression_6(yyp); } 13372public static object IncrementDecrementExpression_6_factory(Parser yyp) { return new IncrementDecrementExpression_6(yyp); }
13373public static object IncrementDecrementExpression_7_factory(Parser yyp) { return new IncrementDecrementExpression_7(yyp); }
11160public static object StateEvent_factory(Parser yyp) { return new StateEvent(yyp); } 13374public static object StateEvent_factory(Parser yyp) { return new StateEvent(yyp); }
11161public static object Event_20_factory(Parser yyp) { return new Event_20(yyp); } 13375public static object IntArgEvent_3_factory(Parser yyp) { return new IntArgEvent_3(yyp); }
11162public static object Event_23_factory(Parser yyp) { return new Event_23(yyp); } 13376public static object IntArgEvent_4_factory(Parser yyp) { return new IntArgEvent_4(yyp); }
11163public static object Event_24_factory(Parser yyp) { return new Event_24(yyp); } 13377public static object KeyDeclaration_1_factory(Parser yyp) { return new KeyDeclaration_1(yyp); }
11164public static object Event_26_factory(Parser yyp) { return new Event_26(yyp); } 13378public static object Statement_3_factory(Parser yyp) { return new Statement_3(yyp); }
13379public static object IntArgEvent_7_factory(Parser yyp) { return new IntArgEvent_7(yyp); }
13380public static object IntArgEvent_8_factory(Parser yyp) { return new IntArgEvent_8(yyp); }
11165public static object SimpleAssignment_10_factory(Parser yyp) { return new SimpleAssignment_10(yyp); } 13381public static object SimpleAssignment_10_factory(Parser yyp) { return new SimpleAssignment_10(yyp); }
13382public static object StatementList_2_factory(Parser yyp) { return new StatementList_2(yyp); }
13383public static object IntRotRotArgStateEvent_1_factory(Parser yyp) { return new IntRotRotArgStateEvent_1(yyp); }
13384public static object VectorArgEvent_2_factory(Parser yyp) { return new VectorArgEvent_2(yyp); }
11166public static object Event_factory(Parser yyp) { return new Event(yyp); } 13385public static object Event_factory(Parser yyp) { return new Event(yyp); }
11167public static object SimpleAssignment_14_factory(Parser yyp) { return new SimpleAssignment_14(yyp); } 13386public static object SimpleAssignment_14_factory(Parser yyp) { return new SimpleAssignment_14(yyp); }
11168public static object SimpleAssignment_16_factory(Parser yyp) { return new SimpleAssignment_16(yyp); } 13387public static object SimpleAssignment_16_factory(Parser yyp) { return new SimpleAssignment_16(yyp); }
13388public static object SimpleAssignment_17_factory(Parser yyp) { return new SimpleAssignment_17(yyp); }
13389public static object SimpleAssignment_18_factory(Parser yyp) { return new SimpleAssignment_18(yyp); }
11169public static object Statement_10_factory(Parser yyp) { return new Statement_10(yyp); } 13390public static object Statement_10_factory(Parser yyp) { return new Statement_10(yyp); }
11170public static object Statement_11_factory(Parser yyp) { return new Statement_11(yyp); } 13391public static object Statement_11_factory(Parser yyp) { return new Statement_11(yyp); }
11171public static object SimpleAssignment_factory(Parser yyp) { return new SimpleAssignment(yyp); } 13392public static object SimpleAssignment_factory(Parser yyp) { return new SimpleAssignment(yyp); }
11172public static object Statement_13_factory(Parser yyp) { return new Statement_13(yyp); } 13393public static object TypecastExpression_factory(Parser yyp) { return new TypecastExpression(yyp); }
11173public static object Event_15_factory(Parser yyp) { return new Event_15(yyp); } 13394public static object JumpStatement_1_factory(Parser yyp) { return new JumpStatement_1(yyp); }
11174public static object Event_16_factory(Parser yyp) { return new Event_16(yyp); }
11175public static object Event_32_factory(Parser yyp) { return new Event_32(yyp); }
11176public static object Event_34_factory(Parser yyp) { return new Event_34(yyp); }
11177public static object SimpleAssignment_20_factory(Parser yyp) { return new SimpleAssignment_20(yyp); } 13395public static object SimpleAssignment_20_factory(Parser yyp) { return new SimpleAssignment_20(yyp); }
13396public static object Statement_7_factory(Parser yyp) { return new Statement_7(yyp); }
13397public static object SimpleAssignment_23_factory(Parser yyp) { return new SimpleAssignment_23(yyp); }
11178public static object SimpleAssignment_24_factory(Parser yyp) { return new SimpleAssignment_24(yyp); } 13398public static object SimpleAssignment_24_factory(Parser yyp) { return new SimpleAssignment_24(yyp); }
11179public static object SimpleAssignment_1_factory(Parser yyp) { return new SimpleAssignment_1(yyp); } 13399public static object SimpleAssignment_1_factory(Parser yyp) { return new SimpleAssignment_1(yyp); }
11180public static object SimpleAssignment_2_factory(Parser yyp) { return new SimpleAssignment_2(yyp); } 13400public static object SimpleAssignment_2_factory(Parser yyp) { return new SimpleAssignment_2(yyp); }
@@ -11182,67 +13402,79 @@ public static object BinaryExpression_factory(Parser yyp) { return new BinaryExp
11182public static object FunctionCallExpression_factory(Parser yyp) { return new FunctionCallExpression(yyp); } 13402public static object FunctionCallExpression_factory(Parser yyp) { return new FunctionCallExpression(yyp); }
11183public static object SimpleAssignment_6_factory(Parser yyp) { return new SimpleAssignment_6(yyp); } 13403public static object SimpleAssignment_6_factory(Parser yyp) { return new SimpleAssignment_6(yyp); }
11184public static object StateBody_1_factory(Parser yyp) { return new StateBody_1(yyp); } 13404public static object StateBody_1_factory(Parser yyp) { return new StateBody_1(yyp); }
11185public static object StatementList_2_factory(Parser yyp) { return new StatementList_2(yyp); } 13405public static object StateBody_2_factory(Parser yyp) { return new StateBody_2(yyp); }
11186public static object SimpleAssignment_9_factory(Parser yyp) { return new SimpleAssignment_9(yyp); } 13406public static object StateBody_3_factory(Parser yyp) { return new StateBody_3(yyp); }
11187public static object BinaryExpression_15_factory(Parser yyp) { return new BinaryExpression_15(yyp); } 13407public static object StateBody_4_factory(Parser yyp) { return new StateBody_4(yyp); }
11188public static object BinaryExpression_16_factory(Parser yyp) { return new BinaryExpression_16(yyp); } 13408public static object StateBody_5_factory(Parser yyp) { return new StateBody_5(yyp); }
11189public static object BinaryExpression_17_factory(Parser yyp) { return new BinaryExpression_17(yyp); } 13409public static object StateBody_6_factory(Parser yyp) { return new StateBody_6(yyp); }
11190public static object BinaryExpression_18_factory(Parser yyp) { return new BinaryExpression_18(yyp); } 13410public static object StateBody_7_factory(Parser yyp) { return new StateBody_7(yyp); }
11191public static object Event_25_factory(Parser yyp) { return new Event_25(yyp); } 13411public static object StateBody_8_factory(Parser yyp) { return new StateBody_8(yyp); }
11192public static object Event_9_factory(Parser yyp) { return new Event_9(yyp); } 13412public static object StateBody_9_factory(Parser yyp) { return new StateBody_9(yyp); }
11193public static object Statement_factory(Parser yyp) { return new Statement(yyp); } 13413public static object Statement_factory(Parser yyp) { return new Statement(yyp); }
13414public static object IncrementDecrementExpression_3_factory(Parser yyp) { return new IncrementDecrementExpression_3(yyp); }
11194public static object JumpStatement_factory(Parser yyp) { return new JumpStatement(yyp); } 13415public static object JumpStatement_factory(Parser yyp) { return new JumpStatement(yyp); }
11195public static object BinaryExpression_11_factory(Parser yyp) { return new BinaryExpression_11(yyp); } 13416public static object BinaryExpression_11_factory(Parser yyp) { return new BinaryExpression_11(yyp); }
11196public static object BinaryExpression_12_factory(Parser yyp) { return new BinaryExpression_12(yyp); } 13417public static object IntArgEvent_factory(Parser yyp) { return new IntArgEvent(yyp); }
11197public static object BinaryExpression_13_factory(Parser yyp) { return new BinaryExpression_13(yyp); } 13418public static object IncrementDecrementExpression_8_factory(Parser yyp) { return new IncrementDecrementExpression_8(yyp); }
11198public static object BinaryExpression_14_factory(Parser yyp) { return new BinaryExpression_14(yyp); } 13419public static object BinaryExpression_14_factory(Parser yyp) { return new BinaryExpression_14(yyp); }
13420public static object BinaryExpression_15_factory(Parser yyp) { return new BinaryExpression_15(yyp); }
13421public static object BinaryExpression_16_factory(Parser yyp) { return new BinaryExpression_16(yyp); }
11199public static object BinaryExpression_6_factory(Parser yyp) { return new BinaryExpression_6(yyp); } 13422public static object BinaryExpression_6_factory(Parser yyp) { return new BinaryExpression_6(yyp); }
11200public static object BinaryExpression_7_factory(Parser yyp) { return new BinaryExpression_7(yyp); } 13423public static object BinaryExpression_7_factory(Parser yyp) { return new BinaryExpression_7(yyp); }
13424public static object Typename_2_factory(Parser yyp) { return new Typename_2(yyp); }
13425public static object Typename_4_factory(Parser yyp) { return new Typename_4(yyp); }
11201public static object ArgumentList_factory(Parser yyp) { return new ArgumentList(yyp); } 13426public static object ArgumentList_factory(Parser yyp) { return new ArgumentList(yyp); }
11202public static object Event_10_factory(Parser yyp) { return new Event_10(yyp); } 13427public static object BinaryExpression_12_factory(Parser yyp) { return new BinaryExpression_12(yyp); }
11203public static object ConstantExpression_1_factory(Parser yyp) { return new ConstantExpression_1(yyp); } 13428public static object BinaryExpression_13_factory(Parser yyp) { return new BinaryExpression_13(yyp); }
11204public static object Event_12_factory(Parser yyp) { return new Event_12(yyp); } 13429public static object GlobalFunctionDefinition_2_factory(Parser yyp) { return new GlobalFunctionDefinition_2(yyp); }
11205public static object Event_14_factory(Parser yyp) { return new Event_14(yyp); } 13430public static object StateChange_2_factory(Parser yyp) { return new StateChange_2(yyp); }
11206public static object Event_17_factory(Parser yyp) { return new Event_17(yyp); } 13431public static object VoidArgEvent_1_factory(Parser yyp) { return new VoidArgEvent_1(yyp); }
11207public static object Event_18_factory(Parser yyp) { return new Event_18(yyp); }
11208public static object Event_19_factory(Parser yyp) { return new Event_19(yyp); }
11209public static object BinaryExpression_10_factory(Parser yyp) { return new BinaryExpression_10(yyp); } 13432public static object BinaryExpression_10_factory(Parser yyp) { return new BinaryExpression_10(yyp); }
13433public static object VoidArgEvent_5_factory(Parser yyp) { return new VoidArgEvent_5(yyp); }
13434public static object VoidArgEvent_6_factory(Parser yyp) { return new VoidArgEvent_6(yyp); }
13435public static object VoidArgEvent_7_factory(Parser yyp) { return new VoidArgEvent_7(yyp); }
13436public static object VoidArgEvent_8_factory(Parser yyp) { return new VoidArgEvent_8(yyp); }
13437public static object BinaryExpression_17_factory(Parser yyp) { return new BinaryExpression_17(yyp); }
11210public static object StateEvent_1_factory(Parser yyp) { return new StateEvent_1(yyp); } 13438public static object StateEvent_1_factory(Parser yyp) { return new StateEvent_1(yyp); }
11211public static object VectorConstant_factory(Parser yyp) { return new VectorConstant(yyp); } 13439public static object VectorConstant_factory(Parser yyp) { return new VectorConstant(yyp); }
11212public static object EmptyStatement_1_factory(Parser yyp) { return new EmptyStatement_1(yyp); } 13440public static object VectorArgEvent_1_factory(Parser yyp) { return new VectorArgEvent_1(yyp); }
13441public static object IntDeclaration_factory(Parser yyp) { return new IntDeclaration(yyp); }
13442public static object VectorArgEvent_3_factory(Parser yyp) { return new VectorArgEvent_3(yyp); }
11213public static object TypecastExpression_4_factory(Parser yyp) { return new TypecastExpression_4(yyp); } 13443public static object TypecastExpression_4_factory(Parser yyp) { return new TypecastExpression_4(yyp); }
11214public static object TypecastExpression_6_factory(Parser yyp) { return new TypecastExpression_6(yyp); } 13444public static object TypecastExpression_6_factory(Parser yyp) { return new TypecastExpression_6(yyp); }
11215public static object TypecastExpression_7_factory(Parser yyp) { return new TypecastExpression_7(yyp); } 13445public static object TypecastExpression_7_factory(Parser yyp) { return new TypecastExpression_7(yyp); }
11216public static object FunctionCall_factory(Parser yyp) { return new FunctionCall(yyp); } 13446public static object FunctionCall_factory(Parser yyp) { return new FunctionCall(yyp); }
11217public static object Event_27_factory(Parser yyp) { return new Event_27(yyp); }
11218public static object Event_28_factory(Parser yyp) { return new Event_28(yyp); }
11219public static object Event_29_factory(Parser yyp) { return new Event_29(yyp); }
11220public static object ListConstant_1_factory(Parser yyp) { return new ListConstant_1(yyp); } 13447public static object ListConstant_1_factory(Parser yyp) { return new ListConstant_1(yyp); }
13448public static object BinaryExpression_18_factory(Parser yyp) { return new BinaryExpression_18(yyp); }
11221public static object Event_6_factory(Parser yyp) { return new Event_6(yyp); } 13449public static object Event_6_factory(Parser yyp) { return new Event_6(yyp); }
13450public static object KeyArgEvent_2_factory(Parser yyp) { return new KeyArgEvent_2(yyp); }
11222public static object Declaration_1_factory(Parser yyp) { return new Declaration_1(yyp); } 13451public static object Declaration_1_factory(Parser yyp) { return new Declaration_1(yyp); }
13452public static object EmptyStatement_1_factory(Parser yyp) { return new EmptyStatement_1(yyp); }
11223public static object SimpleAssignment_7_factory(Parser yyp) { return new SimpleAssignment_7(yyp); } 13453public static object SimpleAssignment_7_factory(Parser yyp) { return new SimpleAssignment_7(yyp); }
11224public static object ForLoop_factory(Parser yyp) { return new ForLoop(yyp); } 13454public static object ForLoop_factory(Parser yyp) { return new ForLoop(yyp); }
11225public static object ForLoop_2_factory(Parser yyp) { return new ForLoop_2(yyp); } 13455public static object ForLoop_2_factory(Parser yyp) { return new ForLoop_2(yyp); }
11226public static object Event_30_factory(Parser yyp) { return new Event_30(yyp); } 13456public static object KeyIntIntArgStateEvent_1_factory(Parser yyp) { return new KeyIntIntArgStateEvent_1(yyp); }
11227public static object Event_31_factory(Parser yyp) { return new Event_31(yyp); } 13457public static object KeyArgumentDeclarationList_1_factory(Parser yyp) { return new KeyArgumentDeclarationList_1(yyp); }
11228public static object Event_33_factory(Parser yyp) { return new Event_33(yyp); }
11229public static object GlobalFunctionDefinition_1_factory(Parser yyp) { return new GlobalFunctionDefinition_1(yyp); } 13458public static object GlobalFunctionDefinition_1_factory(Parser yyp) { return new GlobalFunctionDefinition_1(yyp); }
11230public static object JumpLabel_1_factory(Parser yyp) { return new JumpLabel_1(yyp); }
11231public static object IfStatement_factory(Parser yyp) { return new IfStatement(yyp); } 13459public static object IfStatement_factory(Parser yyp) { return new IfStatement(yyp); }
11232public static object ForLoopStatement_1_factory(Parser yyp) { return new ForLoopStatement_1(yyp); } 13460public static object ForLoopStatement_1_factory(Parser yyp) { return new ForLoopStatement_1(yyp); }
11233public static object ForLoopStatement_2_factory(Parser yyp) { return new ForLoopStatement_2(yyp); } 13461public static object ForLoopStatement_2_factory(Parser yyp) { return new ForLoopStatement_2(yyp); }
11234public static object ForLoopStatement_3_factory(Parser yyp) { return new ForLoopStatement_3(yyp); } 13462public static object ForLoopStatement_3_factory(Parser yyp) { return new ForLoopStatement_3(yyp); }
11235public static object ArgumentDeclarationList_4_factory(Parser yyp) { return new ArgumentDeclarationList_4(yyp); } 13463public static object IntRotRotArgumentDeclarationList_factory(Parser yyp) { return new IntRotRotArgumentDeclarationList(yyp); }
11236public static object ArgumentDeclarationList_5_factory(Parser yyp) { return new ArgumentDeclarationList_5(yyp); } 13464public static object IntArgEvent_1_factory(Parser yyp) { return new IntArgEvent_1(yyp); }
11237public static object EmptyStatement_factory(Parser yyp) { return new EmptyStatement(yyp); } 13465public static object IntArgEvent_2_factory(Parser yyp) { return new IntArgEvent_2(yyp); }
11238public static object WhileStatement_factory(Parser yyp) { return new WhileStatement(yyp); } 13466public static object WhileStatement_factory(Parser yyp) { return new WhileStatement(yyp); }
11239public static object ForLoop_1_factory(Parser yyp) { return new ForLoop_1(yyp); } 13467public static object ForLoop_1_factory(Parser yyp) { return new ForLoop_1(yyp); }
11240public static object Constant_2_factory(Parser yyp) { return new Constant_2(yyp); } 13468public static object Constant_2_factory(Parser yyp) { return new Constant_2(yyp); }
11241public static object StatementList_factory(Parser yyp) { return new StatementList(yyp); } 13469public static object VoidArgEvent_factory(Parser yyp) { return new VoidArgEvent(yyp); }
11242public static object StateBody_2_factory(Parser yyp) { return new StateBody_2(yyp); } 13470public static object RotDeclaration_factory(Parser yyp) { return new RotDeclaration(yyp); }
13471public static object WhileStatement_1_factory(Parser yyp) { return new WhileStatement_1(yyp); }
11243public static object WhileStatement_2_factory(Parser yyp) { return new WhileStatement_2(yyp); } 13472public static object WhileStatement_2_factory(Parser yyp) { return new WhileStatement_2(yyp); }
13473public static object VectorArgStateEvent_1_factory(Parser yyp) { return new VectorArgStateEvent_1(yyp); }
11244public static object IdentExpression_1_factory(Parser yyp) { return new IdentExpression_1(yyp); } 13474public static object IdentExpression_1_factory(Parser yyp) { return new IdentExpression_1(yyp); }
13475public static object VectorArgumentDeclarationList_factory(Parser yyp) { return new VectorArgumentDeclarationList(yyp); }
11245public static object States_factory(Parser yyp) { return new States(yyp); } 13476public static object States_factory(Parser yyp) { return new States(yyp); }
13477public static object VoidArgStateEvent_factory(Parser yyp) { return new VoidArgStateEvent(yyp); }
11246} 13478}
11247public class LSLSyntax 13479public class LSLSyntax
11248: Parser { 13480: Parser {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
index 48964b6..815d11b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index a2ac9c5..275b608 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -243,7 +243,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
243 if (Engine.Config.GetString("ScriptStopStrategy", "abort") == "co-op") 243 if (Engine.Config.GetString("ScriptStopStrategy", "abort") == "co-op")
244 { 244 {
245 m_coopTermination = true; 245 m_coopTermination = true;
246 m_coopSleepHandle = new AutoResetEvent(false); 246 m_coopSleepHandle = new XEngineEventWaitHandle(false, EventResetMode.AutoReset);
247 } 247 }
248 } 248 }
249 249
@@ -529,8 +529,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
529 { 529 {
530 File.Delete(savedState); 530 File.Delete(savedState);
531 } 531 }
532 catch(Exception) 532 catch (Exception e)
533 { 533 {
534 m_log.Warn(
535 string.Format(
536 "[SCRIPT INSTANCE]: Could not delete script state {0} for script {1} (id {2}) in part {3} (id {4}) in object {5} in {6}. Exception ",
537 savedState, ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name),
538 e);
534 } 539 }
535 } 540 }
536 541
@@ -568,9 +573,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
568 573
569 public bool Stop(int timeout) 574 public bool Stop(int timeout)
570 { 575 {
571// m_log.DebugFormat( 576 if (DebugLevel >= 1)
572// "[SCRIPT INSTANCE]: Stopping script {0} {1} in {2} {3} with timeout {4} {5} {6}", 577 m_log.DebugFormat(
573// ScriptName, ItemID, PrimName, ObjectID, timeout, m_InSelfDelete, DateTime.Now.Ticks); 578 "[SCRIPT INSTANCE]: Stopping script {0} {1} in {2} {3} with timeout {4} {5} {6}",
579 ScriptName, ItemID, PrimName, ObjectID, timeout, m_InSelfDelete, DateTime.Now.Ticks);
574 580
575 IScriptWorkItem workItem; 581 IScriptWorkItem workItem;
576 582
@@ -1216,4 +1222,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1216 Suspended = false; 1222 Suspended = false;
1217 } 1223 }
1218 } 1224 }
1225
1226 /// <summary>
1227 /// Xengine event wait handle.
1228 /// </summary>
1229 /// <remarks>
1230 /// This class exists becase XEngineScriptBase gets a reference to this wait handle. We need to make sure that
1231 /// when scripts are running in different AppDomains the lease does not expire.
1232 /// FIXME: Like LSL_Api, etc., this effectively leaks memory since the GC will never collect it. To avoid this,
1233 /// proper remoting sponsorship needs to be implemented across the board.
1234 /// </remarks>
1235 public class XEngineEventWaitHandle : EventWaitHandle
1236 {
1237 public XEngineEventWaitHandle(bool initialState, EventResetMode mode) : base(initialState, mode) {}
1238
1239 public override Object InitializeLifetimeService()
1240 {
1241 return null;
1242 }
1243 }
1219} 1244}
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index b524a18..4ba0e64 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -371,6 +371,31 @@ namespace OpenSim.Region.ScriptEngine.Shared
371 371
372 #endregion 372 #endregion
373 373
374 #region Methods
375 public Quaternion Normalize()
376 {
377 double length = Math.Sqrt(x * x + y * y + z * z + s * s);
378 if (length < float.Epsilon)
379 {
380 x = 0;
381 y = 0;
382 z = 0;
383 s = 1;
384 }
385 else
386 {
387
388 double invLength = 1.0 / length;
389 x *= invLength;
390 y *= invLength;
391 z *= invLength;
392 s *= invLength;
393 }
394
395 return this;
396 }
397 #endregion
398
374 #region Overriders 399 #region Overriders
375 400
376 public override int GetHashCode() 401 public override int GetHashCode()
@@ -546,21 +571,33 @@ namespace OpenSim.Region.ScriptEngine.Shared
546 571
547 set {m_data = value; } 572 set {m_data = value; }
548 } 573 }
549 // Function to obtain LSL type from an index. This is needed 574
550 // because LSL lists allow for multiple types, and safely 575 /// <summary>
551 // iterating in them requires a type check. 576 /// Obtain LSL type from an index.
577 /// </summary>
578 /// <remarks>
579 /// This is needed because LSL lists allow for multiple types, and safely
580 /// iterating in them requires a type check.
581 /// </remarks>
582 /// <returns></returns>
583 /// <param name='itemIndex'></param>
552 public Type GetLSLListItemType(int itemIndex) 584 public Type GetLSLListItemType(int itemIndex)
553 { 585 {
554 return m_data[itemIndex].GetType(); 586 return m_data[itemIndex].GetType();
555 } 587 }
556 588
557 // Member functions to obtain item as specific types. 589 /// <summary>
558 // For cases where implicit conversions would apply if items 590 /// Obtain float from an index.
559 // were not in a list (e.g. integer to float, but not float 591 /// </summary>
560 // to integer) functions check for alternate types so as to 592 /// <remarks>
561 // down-cast from Object to the correct type. 593 /// For cases where implicit conversions would apply if items
562 // Note: no checks for item index being valid are performed 594 /// were not in a list (e.g. integer to float, but not float
563 595 /// to integer) functions check for alternate types so as to
596 /// down-cast from Object to the correct type.
597 /// Note: no checks for item index being valid are performed
598 /// </remarks>
599 /// <returns></returns>
600 /// <param name='itemIndex'></param>
564 public LSL_Types.LSLFloat GetLSLFloatItem(int itemIndex) 601 public LSL_Types.LSLFloat GetLSLFloatItem(int itemIndex)
565 { 602 {
566 if (m_data[itemIndex] is LSL_Types.LSLInteger) 603 if (m_data[itemIndex] is LSL_Types.LSLInteger)
@@ -591,26 +628,14 @@ namespace OpenSim.Region.ScriptEngine.Shared
591 628
592 public LSL_Types.LSLString GetLSLStringItem(int itemIndex) 629 public LSL_Types.LSLString GetLSLStringItem(int itemIndex)
593 { 630 {
594 if (m_data[itemIndex] is LSL_Types.key) 631 if (m_data[itemIndex] is LSL_Types.key)
595 { 632 {
596 return (LSL_Types.key)m_data[itemIndex]; 633 return (LSL_Types.key)m_data[itemIndex];
597 } 634 }
598 else if (m_data[itemIndex] is String) 635 else
599 { 636 {
600 return new LSL_Types.LSLString((string)m_data[itemIndex]); 637 return new LSL_Types.LSLString(m_data[itemIndex].ToString());
601 } 638 }
602 else if (m_data[itemIndex] is LSL_Types.LSLFloat)
603 {
604 return new LSL_Types.LSLString((LSLFloat)m_data[itemIndex]);
605 }
606 else if (m_data[itemIndex] is LSL_Types.LSLInteger)
607 {
608 return new LSL_Types.LSLString((LSLInteger)m_data[itemIndex]);
609 }
610 else
611 {
612 return (LSL_Types.LSLString)m_data[itemIndex];
613 }
614 } 639 }
615 640
616 public LSL_Types.LSLInteger GetLSLIntegerItem(int itemIndex) 641 public LSL_Types.LSLInteger GetLSLIntegerItem(int itemIndex)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs
index c92bcdb..42d1b3b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs
@@ -75,7 +75,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
75 { 75 {
76 TestHelpers.InMethod(); 76 TestHelpers.InMethod();
77 77
78 string[] ncLines = { "One", "Two", "Three" }; 78 string[] ncLines = { "One", "Twoè", "Three" };
79 79
80 TaskInventoryItem ncItem 80 TaskInventoryItem ncItem
81 = TaskInventoryHelpers.AddNotecard(m_scene, m_so.RootPart, "nc", "1", "10", string.Join("\n", ncLines)); 81 = TaskInventoryHelpers.AddNotecard(m_scene, m_so.RootPart, "nc", "1", "10", string.Join("\n", ncLines));
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs
new file mode 100644
index 0000000..ed61dc0
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs
@@ -0,0 +1,399 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text;
32using log4net;
33using Nini.Config;
34using NUnit.Framework;
35using OpenMetaverse;
36using OpenMetaverse.Assets;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework;
39using OpenSim.Region.CoreModules.Avatar.AvatarFactory;
40using OpenSim.Region.OptionalModules.World.NPC;
41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.ScriptEngine.Shared;
43using OpenSim.Region.ScriptEngine.Shared.Api;
44using OpenSim.Region.ScriptEngine.Shared.Instance;
45using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
46using OpenSim.Services.Interfaces;
47using OpenSim.Tests.Common;
48using OpenSim.Tests.Common.Mock;
49using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
50using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
51
52namespace OpenSim.Region.ScriptEngine.Shared.Tests
53{
54 [TestFixture]
55 public class LSL_ApiObjectTests : OpenSimTestCase
56 {
57 private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d;
58 private const float FLOAT_ACCURACY = 0.00005f;
59
60 protected Scene m_scene;
61 protected XEngine.XEngine m_engine;
62
63 [SetUp]
64 public override void SetUp()
65 {
66 base.SetUp();
67
68 IConfigSource initConfigSource = new IniConfigSource();
69 IConfig config = initConfigSource.AddConfig("XEngine");
70 config.Set("Enabled", "true");
71
72 m_scene = new SceneHelpers().SetupScene();
73 SceneHelpers.SetupSceneModules(m_scene, initConfigSource);
74
75 m_engine = new XEngine.XEngine();
76 m_engine.Initialise(initConfigSource);
77 m_engine.AddRegion(m_scene);
78 }
79
80 [Test]
81 public void TestllGetLinkPrimitiveParams()
82 {
83 TestHelpers.InMethod();
84 TestHelpers.EnableLogging();
85
86 UUID ownerId = TestHelpers.ParseTail(0x1);
87
88 SceneObjectGroup grp1 = SceneHelpers.CreateSceneObject(2, ownerId, "grp1-", 0x10);
89 grp1.AbsolutePosition = new Vector3(10, 11, 12);
90 m_scene.AddSceneObject(grp1);
91
92 LSL_Api apiGrp1 = new LSL_Api();
93 apiGrp1.Initialize(m_engine, grp1.RootPart, null, null);
94
95 // Check simple 1 prim case
96 {
97 LSL_List resList
98 = apiGrp1.llGetLinkPrimitiveParams(1, new LSL_List(new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
99
100 Assert.That(resList.Length, Is.EqualTo(1));
101 }
102
103 // Check 2 prim case
104 {
105 LSL_List resList
106 = apiGrp1.llGetLinkPrimitiveParams(
107 1,
108 new LSL_List(
109 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION),
110 new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET),
111 new LSL_Integer(2),
112 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
113
114 Assert.That(resList.Length, Is.EqualTo(2));
115 }
116
117 // Check invalid parameters are ignored
118 {
119 LSL_List resList
120 = apiGrp1.llGetLinkPrimitiveParams(3, new LSL_List(new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
121
122 Assert.That(resList.Length, Is.EqualTo(0));
123 }
124
125 // Check all parameters are ignored if an initial bad link is given
126 {
127 LSL_List resList
128 = apiGrp1.llGetLinkPrimitiveParams(
129 3,
130 new LSL_List(
131 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION),
132 new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET),
133 new LSL_Integer(1),
134 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
135
136 Assert.That(resList.Length, Is.EqualTo(0));
137 }
138
139 // Check only subsequent parameters are ignored when we hit the first bad link number
140 {
141 LSL_List resList
142 = apiGrp1.llGetLinkPrimitiveParams(
143 1,
144 new LSL_List(
145 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION),
146 new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET),
147 new LSL_Integer(3),
148 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
149
150 Assert.That(resList.Length, Is.EqualTo(1));
151 }
152 }
153
154 [Test]
155 // llSetPrimitiveParams and llGetPrimitiveParams test.
156 public void TestllSetPrimitiveParams()
157 {
158 TestHelpers.InMethod();
159
160 // Create Prim1.
161 Scene scene = new SceneHelpers().SetupScene();
162 string obj1Name = "Prim1";
163 UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001");
164 SceneObjectPart part1 =
165 new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default,
166 Vector3.Zero, Quaternion.Identity,
167 Vector3.Zero) { Name = obj1Name, UUID = objUuid };
168 Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part1), false), Is.True);
169
170 LSL_Api apiGrp1 = new LSL_Api();
171 apiGrp1.Initialize(m_engine, part1, null, null);
172
173 // Note that prim hollow check is passed with the other prim params in order to allow the
174 // specification of a different check value from the prim param. A cylinder, prism, sphere,
175 // torus or ring, with a hole shape of square, is limited to a hollow of 70%. Test 5 below
176 // specifies a value of 95% and checks to see if 70% was properly returned.
177
178 // Test a sphere.
179 CheckllSetPrimitiveParams(
180 apiGrp1,
181 "test 1", // Prim test identification string
182 new LSL_Types.Vector3(6.0d, 9.9d, 9.9d), // Prim size
183 ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type
184 ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type
185 new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut
186 0.80f, // Prim hollow
187 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
188 new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple
189 0.80f); // Prim hollow check
190
191 // Test a prism.
192 CheckllSetPrimitiveParams(
193 apiGrp1,
194 "test 2", // Prim test identification string
195 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
196 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
197 ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type
198 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
199 0.90f, // Prim hollow
200 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
201 new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper
202 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
203 0.90f); // Prim hollow check
204
205 // Test a box.
206 CheckllSetPrimitiveParams(
207 apiGrp1,
208 "test 3", // Prim test identification string
209 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
210 ScriptBaseClass.PRIM_TYPE_BOX, // Prim type
211 ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type
212 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
213 0.95f, // Prim hollow
214 new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist
215 new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper
216 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
217 0.95f); // Prim hollow check
218
219 // Test a tube.
220 CheckllSetPrimitiveParams(
221 apiGrp1,
222 "test 4", // Prim test identification string
223 new LSL_Types.Vector3(4.2d, 4.2d, 4.2d), // Prim size
224 ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type
225 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
226 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
227 0.00f, // Prim hollow
228 new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist
229 new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size
230 // Expression for y selected to test precision problems during byte
231 // cast in SetPrimitiveShapeParams.
232 new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear
233 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut
234 // Expression for y selected to test precision problems during sbyte
235 // cast in SetPrimitiveShapeParams.
236 new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper
237 1.11f, // Prim revolutions
238 0.88f, // Prim radius
239 0.95f, // Prim skew
240 0.00f); // Prim hollow check
241
242 // Test a prism.
243 CheckllSetPrimitiveParams(
244 apiGrp1,
245 "test 5", // Prim test identification string
246 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
247 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
248 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
249 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
250 0.95f, // Prim hollow
251 // Expression for x selected to test precision problems during sbyte
252 // cast in SetPrimitiveShapeBlockParams.
253 new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist
254 // Expression for y selected to test precision problems during sbyte
255 // cast in SetPrimitiveShapeParams.
256 new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper
257 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
258 0.70f); // Prim hollow check
259
260 // Test a sculpted prim.
261 CheckllSetPrimitiveParams(
262 apiGrp1,
263 "test 6", // Prim test identification string
264 new LSL_Types.Vector3(2.0d, 2.0d, 2.0d), // Prim size
265 ScriptBaseClass.PRIM_TYPE_SCULPT, // Prim type
266 "be293869-d0d9-0a69-5989-ad27f1946fd4", // Prim map
267 ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE); // Prim sculpt type
268 }
269
270 // Set prim params for a box, cylinder or prism and check results.
271 public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
272 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
273 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear,
274 float primHollowCheck)
275 {
276 // Set the prim params.
277 api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
278 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
279 primCut, primHollow, primTwist, primTaper, primShear));
280
281 // Get params for prim to validate settings.
282 LSL_Types.list primParams =
283 api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
284
285 // Validate settings.
286 CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
287 Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
288 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
289 Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2),
290 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
291 CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut");
292 Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY,
293 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
294 CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist");
295 CheckllSetPrimitiveParamsVector(primTaper, api.llList2Vector(primParams, 6), primTest + " prim taper");
296 CheckllSetPrimitiveParamsVector(primShear, api.llList2Vector(primParams, 7), primTest + " prim shear");
297 }
298
299 // Set prim params for a sphere and check results.
300 public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
301 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
302 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck)
303 {
304 // Set the prim params.
305 api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
306 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
307 primCut, primHollow, primTwist, primDimple));
308
309 // Get params for prim to validate settings.
310 LSL_Types.list primParams =
311 api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
312
313 // Validate settings.
314 CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
315 Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
316 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
317 Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2),
318 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
319 CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut");
320 Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY,
321 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
322 CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist");
323 CheckllSetPrimitiveParamsVector(primDimple, api.llList2Vector(primParams, 6), primTest + " prim dimple");
324 }
325
326 // Set prim params for a torus, tube or ring and check results.
327 public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
328 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
329 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize,
330 LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper,
331 float primRev, float primRadius, float primSkew, float primHollowCheck)
332 {
333 // Set the prim params.
334 api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
335 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
336 primCut, primHollow, primTwist, primHoleSize, primShear, primProfCut,
337 primTaper, primRev, primRadius, primSkew));
338
339 // Get params for prim to validate settings.
340 LSL_Types.list primParams =
341 api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
342
343 // Valdate settings.
344 CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
345 Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
346 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
347 Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2),
348 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
349 CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut");
350 Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY,
351 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
352 CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist");
353 CheckllSetPrimitiveParamsVector(primHoleSize, api.llList2Vector(primParams, 6), primTest + " prim hole size");
354 CheckllSetPrimitiveParamsVector(primShear, api.llList2Vector(primParams, 7), primTest + " prim shear");
355 CheckllSetPrimitiveParamsVector(primProfCut, api.llList2Vector(primParams, 8), primTest + " prim profile cut");
356 CheckllSetPrimitiveParamsVector(primTaper, api.llList2Vector(primParams, 9), primTest + " prim taper");
357 Assert.AreEqual(primRev, api.llList2Float(primParams, 10), FLOAT_ACCURACY,
358 "TestllSetPrimitiveParams " + primTest + " prim revolutions fail");
359 Assert.AreEqual(primRadius, api.llList2Float(primParams, 11), FLOAT_ACCURACY,
360 "TestllSetPrimitiveParams " + primTest + " prim radius fail");
361 Assert.AreEqual(primSkew, api.llList2Float(primParams, 12), FLOAT_ACCURACY,
362 "TestllSetPrimitiveParams " + primTest + " prim skew fail");
363 }
364
365 // Set prim params for a sculpted prim and check results.
366 public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
367 LSL_Types.Vector3 primSize, int primType, string primMap, int primSculptType)
368 {
369 // Set the prim params.
370 api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
371 ScriptBaseClass.PRIM_TYPE, primType, primMap, primSculptType));
372
373 // Get params for prim to validate settings.
374 LSL_Types.list primParams =
375 api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
376
377 // Validate settings.
378 CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
379 Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
380 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
381 Assert.AreEqual(primMap, (string)api.llList2String(primParams, 2),
382 "TestllSetPrimitiveParams " + primTest + " prim map check fail");
383 Assert.AreEqual(primSculptType, api.llList2Integer(primParams, 3),
384 "TestllSetPrimitiveParams " + primTest + " prim type scuplt check fail");
385 }
386
387 public void CheckllSetPrimitiveParamsVector(LSL_Types.Vector3 vecCheck, LSL_Types.Vector3 vecReturned, string msg)
388 {
389 // Check each vector component against expected result.
390 Assert.AreEqual(vecCheck.x, vecReturned.x, VECTOR_COMPONENT_ACCURACY,
391 "TestllSetPrimitiveParams " + msg + " vector check fail on x component");
392 Assert.AreEqual(vecCheck.y, vecReturned.y, VECTOR_COMPONENT_ACCURACY,
393 "TestllSetPrimitiveParams " + msg + " vector check fail on y component");
394 Assert.AreEqual(vecCheck.z, vecReturned.z, VECTOR_COMPONENT_ACCURACY,
395 "TestllSetPrimitiveParams " + msg + " vector check fail on z component");
396 }
397
398 }
399} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
index e97ae06..7e3726a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
@@ -47,9 +47,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
47 [TestFixture, LongRunning] 47 [TestFixture, LongRunning]
48 public class LSL_ApiTest 48 public class LSL_ApiTest
49 { 49 {
50 private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
51 private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d; 50 private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d;
52 private const float FLOAT_ACCURACY = 0.00005f; 51 private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
53 private LSL_Api m_lslApi; 52 private LSL_Api m_lslApi;
54 53
55 [SetUp] 54 [SetUp]
@@ -255,241 +254,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
255 } 254 }
256 255
257 [Test] 256 [Test]
258 // llSetPrimitiveParams and llGetPrimitiveParams test.
259 public void TestllSetPrimitiveParams()
260 {
261 TestHelpers.InMethod();
262
263 // Create Prim1.
264 Scene scene = new SceneHelpers().SetupScene();
265 string obj1Name = "Prim1";
266 UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001");
267 SceneObjectPart part1 =
268 new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default,
269 Vector3.Zero, Quaternion.Identity,
270 Vector3.Zero) { Name = obj1Name, UUID = objUuid };
271 Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part1), false), Is.True);
272
273 // Note that prim hollow check is passed with the other prim params in order to allow the
274 // specification of a different check value from the prim param. A cylinder, prism, sphere,
275 // torus or ring, with a hole shape of square, is limited to a hollow of 70%. Test 5 below
276 // specifies a value of 95% and checks to see if 70% was properly returned.
277
278 // Test a sphere.
279 CheckllSetPrimitiveParams(
280 "test 1", // Prim test identification string
281 new LSL_Types.Vector3(6.0d, 9.9d, 9.9d), // Prim size
282 ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type
283 ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type
284 new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut
285 0.80f, // Prim hollow
286 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
287 new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple
288 0.80f); // Prim hollow check
289
290 // Test a prism.
291 CheckllSetPrimitiveParams(
292 "test 2", // Prim test identification string
293 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
294 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
295 ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type
296 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
297 0.90f, // Prim hollow
298 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
299 new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper
300 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
301 0.90f); // Prim hollow check
302
303 // Test a box.
304 CheckllSetPrimitiveParams(
305 "test 3", // Prim test identification string
306 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
307 ScriptBaseClass.PRIM_TYPE_BOX, // Prim type
308 ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type
309 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
310 0.95f, // Prim hollow
311 new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist
312 new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper
313 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
314 0.95f); // Prim hollow check
315
316 // Test a tube.
317 CheckllSetPrimitiveParams(
318 "test 4", // Prim test identification string
319 new LSL_Types.Vector3(4.2d, 4.2d, 4.2d), // Prim size
320 ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type
321 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
322 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
323 0.00f, // Prim hollow
324 new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist
325 new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size
326 // Expression for y selected to test precision problems during byte
327 // cast in SetPrimitiveShapeParams.
328 new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear
329 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut
330 // Expression for y selected to test precision problems during sbyte
331 // cast in SetPrimitiveShapeParams.
332 new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper
333 1.11f, // Prim revolutions
334 0.88f, // Prim radius
335 0.95f, // Prim skew
336 0.00f); // Prim hollow check
337
338 // Test a prism.
339 CheckllSetPrimitiveParams(
340 "test 5", // Prim test identification string
341 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
342 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
343 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
344 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
345 0.95f, // Prim hollow
346 // Expression for x selected to test precision problems during sbyte
347 // cast in SetPrimitiveShapeBlockParams.
348 new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist
349 // Expression for y selected to test precision problems during sbyte
350 // cast in SetPrimitiveShapeParams.
351 new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper
352 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
353 0.70f); // Prim hollow check
354
355 // Test a sculpted prim.
356 CheckllSetPrimitiveParams(
357 "test 6", // Prim test identification string
358 new LSL_Types.Vector3(2.0d, 2.0d, 2.0d), // Prim size
359 ScriptBaseClass.PRIM_TYPE_SCULPT, // Prim type
360 "be293869-d0d9-0a69-5989-ad27f1946fd4", // Prim map
361 ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE); // Prim sculpt type
362 }
363
364 // Set prim params for a box, cylinder or prism and check results.
365 public void CheckllSetPrimitiveParams(string primTest,
366 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
367 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear,
368 float primHollowCheck)
369 {
370 // Set the prim params.
371 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
372 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
373 primCut, primHollow, primTwist, primTaper, primShear));
374
375 // Get params for prim to validate settings.
376 LSL_Types.list primParams =
377 m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
378
379 // Validate settings.
380 CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
381 Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
382 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
383 Assert.AreEqual(primHoleType, m_lslApi.llList2Integer(primParams, 2),
384 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
385 CheckllSetPrimitiveParamsVector(primCut, m_lslApi.llList2Vector(primParams, 3), primTest + " prim cut");
386 Assert.AreEqual(primHollowCheck, m_lslApi.llList2Float(primParams, 4), FLOAT_ACCURACY,
387 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
388 CheckllSetPrimitiveParamsVector(primTwist, m_lslApi.llList2Vector(primParams, 5), primTest + " prim twist");
389 CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 6), primTest + " prim taper");
390 CheckllSetPrimitiveParamsVector(primShear, m_lslApi.llList2Vector(primParams, 7), primTest + " prim shear");
391 }
392
393 // Set prim params for a sphere and check results.
394 public void CheckllSetPrimitiveParams(string primTest,
395 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
396 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck)
397 {
398 // Set the prim params.
399 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
400 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
401 primCut, primHollow, primTwist, primDimple));
402
403 // Get params for prim to validate settings.
404 LSL_Types.list primParams =
405 m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
406
407 // Validate settings.
408 CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
409 Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
410 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
411 Assert.AreEqual(primHoleType, m_lslApi.llList2Integer(primParams, 2),
412 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
413 CheckllSetPrimitiveParamsVector(primCut, m_lslApi.llList2Vector(primParams, 3), primTest + " prim cut");
414 Assert.AreEqual(primHollowCheck, m_lslApi.llList2Float(primParams, 4), FLOAT_ACCURACY,
415 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
416 CheckllSetPrimitiveParamsVector(primTwist, m_lslApi.llList2Vector(primParams, 5), primTest + " prim twist");
417 CheckllSetPrimitiveParamsVector(primDimple, m_lslApi.llList2Vector(primParams, 6), primTest + " prim dimple");
418 }
419
420 // Set prim params for a torus, tube or ring and check results.
421 public void CheckllSetPrimitiveParams(string primTest,
422 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
423 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize,
424 LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper,
425 float primRev, float primRadius, float primSkew, float primHollowCheck)
426 {
427 // Set the prim params.
428 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
429 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
430 primCut, primHollow, primTwist, primHoleSize, primShear, primProfCut,
431 primTaper, primRev, primRadius, primSkew));
432
433 // Get params for prim to validate settings.
434 LSL_Types.list primParams =
435 m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
436
437 // Valdate settings.
438 CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
439 Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
440 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
441 Assert.AreEqual(primHoleType, m_lslApi.llList2Integer(primParams, 2),
442 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
443 CheckllSetPrimitiveParamsVector(primCut, m_lslApi.llList2Vector(primParams, 3), primTest + " prim cut");
444 Assert.AreEqual(primHollowCheck, m_lslApi.llList2Float(primParams, 4), FLOAT_ACCURACY,
445 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
446 CheckllSetPrimitiveParamsVector(primTwist, m_lslApi.llList2Vector(primParams, 5), primTest + " prim twist");
447 CheckllSetPrimitiveParamsVector(primHoleSize, m_lslApi.llList2Vector(primParams, 6), primTest + " prim hole size");
448 CheckllSetPrimitiveParamsVector(primShear, m_lslApi.llList2Vector(primParams, 7), primTest + " prim shear");
449 CheckllSetPrimitiveParamsVector(primProfCut, m_lslApi.llList2Vector(primParams, 8), primTest + " prim profile cut");
450 CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper");
451 Assert.AreEqual(primRev, m_lslApi.llList2Float(primParams, 10), FLOAT_ACCURACY,
452 "TestllSetPrimitiveParams " + primTest + " prim revolutions fail");
453 Assert.AreEqual(primRadius, m_lslApi.llList2Float(primParams, 11), FLOAT_ACCURACY,
454 "TestllSetPrimitiveParams " + primTest + " prim radius fail");
455 Assert.AreEqual(primSkew, m_lslApi.llList2Float(primParams, 12), FLOAT_ACCURACY,
456 "TestllSetPrimitiveParams " + primTest + " prim skew fail");
457 }
458
459 // Set prim params for a sculpted prim and check results.
460 public void CheckllSetPrimitiveParams(string primTest,
461 LSL_Types.Vector3 primSize, int primType, string primMap, int primSculptType)
462 {
463 // Set the prim params.
464 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
465 ScriptBaseClass.PRIM_TYPE, primType, primMap, primSculptType));
466
467 // Get params for prim to validate settings.
468 LSL_Types.list primParams =
469 m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
470
471 // Validate settings.
472 CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
473 Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
474 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
475 Assert.AreEqual(primMap, (string)m_lslApi.llList2String(primParams, 2),
476 "TestllSetPrimitiveParams " + primTest + " prim map check fail");
477 Assert.AreEqual(primSculptType, m_lslApi.llList2Integer(primParams, 3),
478 "TestllSetPrimitiveParams " + primTest + " prim type scuplt check fail");
479 }
480
481 public void CheckllSetPrimitiveParamsVector(LSL_Types.Vector3 vecCheck, LSL_Types.Vector3 vecReturned, string msg)
482 {
483 // Check each vector component against expected result.
484 Assert.AreEqual(vecCheck.x, vecReturned.x, VECTOR_COMPONENT_ACCURACY,
485 "TestllSetPrimitiveParams " + msg + " vector check fail on x component");
486 Assert.AreEqual(vecCheck.y, vecReturned.y, VECTOR_COMPONENT_ACCURACY,
487 "TestllSetPrimitiveParams " + msg + " vector check fail on y component");
488 Assert.AreEqual(vecCheck.z, vecReturned.z, VECTOR_COMPONENT_ACCURACY,
489 "TestllSetPrimitiveParams " + msg + " vector check fail on z component");
490 }
491
492 [Test]
493 public void TestllVecNorm() 257 public void TestllVecNorm()
494 { 258 {
495 TestHelpers.InMethod(); 259 TestHelpers.InMethod();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
index 74f010e..495e684 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
@@ -180,6 +180,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
180 public void TestOsNpcLoadAppearance() 180 public void TestOsNpcLoadAppearance()
181 { 181 {
182 TestHelpers.InMethod(); 182 TestHelpers.InMethod();
183 //TestHelpers.EnableLogging();
183 184
184 // Store an avatar with a different height from default in a notecard. 185 // Store an avatar with a different height from default in a notecard.
185 UUID userId = TestHelpers.ParseTail(0x1); 186 UUID userId = TestHelpers.ParseTail(0x1);
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
index f0640da..87ea9c4 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 61985e8..2713080 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -551,7 +551,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
551 /// <param name="instance"></param> 551 /// <param name="instance"></param>
552 /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param> 552 /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param>
553 private void HandleScriptsAction<TKey>( 553 private void HandleScriptsAction<TKey>(
554 string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector) 554 string[] cmdparams, Action<IScriptInstance> action, System.Func<IScriptInstance, TKey> keySelector)
555 { 555 {
556 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) 556 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
557 return; 557 return;
@@ -1633,7 +1633,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1633 startInfo.MaxWorkerThreads = maxThreads; 1633 startInfo.MaxWorkerThreads = maxThreads;
1634 startInfo.MinWorkerThreads = minThreads; 1634 startInfo.MinWorkerThreads = minThreads;
1635 startInfo.ThreadPriority = threadPriority;; 1635 startInfo.ThreadPriority = threadPriority;;
1636 startInfo.StackSize = stackSize; 1636 startInfo.MaxStackSize = stackSize;
1637 startInfo.StartSuspended = true; 1637 startInfo.StartSuspended = true;
1638 1638
1639 m_ThreadPool = new SmartThreadPool(startInfo); 1639 m_ThreadPool = new SmartThreadPool(startInfo);
@@ -1827,9 +1827,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1827 public bool GetScriptState(UUID itemID) 1827 public bool GetScriptState(UUID itemID)
1828 { 1828 {
1829 IScriptInstance instance = GetInstance(itemID); 1829 IScriptInstance instance = GetInstance(itemID);
1830 if (instance != null) 1830 return instance != null && instance.Running;
1831 return instance.Running;
1832 return false;
1833 } 1831 }
1834 1832
1835 [DebuggerNonUserCode] 1833 [DebuggerNonUserCode]
@@ -1874,9 +1872,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1874 public DetectParams GetDetectParams(UUID itemID, int idx) 1872 public DetectParams GetDetectParams(UUID itemID, int idx)
1875 { 1873 {
1876 IScriptInstance instance = GetInstance(itemID); 1874 IScriptInstance instance = GetInstance(itemID);
1877 if (instance != null) 1875 return instance != null ? instance.GetDetectParams(idx) : null;
1878 return instance.GetDetectParams(idx);
1879 return null;
1880 } 1876 }
1881 1877
1882 public void SetMinEventDelay(UUID itemID, double delay) 1878 public void SetMinEventDelay(UUID itemID, double delay)
@@ -1889,9 +1885,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1889 public UUID GetDetectID(UUID itemID, int idx) 1885 public UUID GetDetectID(UUID itemID, int idx)
1890 { 1886 {
1891 IScriptInstance instance = GetInstance(itemID); 1887 IScriptInstance instance = GetInstance(itemID);
1892 if (instance != null) 1888 return instance != null ? instance.GetDetectID(idx) : UUID.Zero;
1893 return instance.GetDetectID(idx);
1894 return UUID.Zero;
1895 } 1889 }
1896 1890
1897 [DebuggerNonUserCode] 1891 [DebuggerNonUserCode]
@@ -1906,9 +1900,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1906 public int GetStartParameter(UUID itemID) 1900 public int GetStartParameter(UUID itemID)
1907 { 1901 {
1908 IScriptInstance instance = GetInstance(itemID); 1902 IScriptInstance instance = GetInstance(itemID);
1909 if (instance == null) 1903 return instance == null ? 0 : instance.StartParam;
1910 return 0;
1911 return instance.StartParam;
1912 } 1904 }
1913 1905
1914 public void OnShutdown() 1906 public void OnShutdown()
@@ -1941,9 +1933,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1941 public IScriptApi GetApi(UUID itemID, string name) 1933 public IScriptApi GetApi(UUID itemID, string name)
1942 { 1934 {
1943 IScriptInstance instance = GetInstance(itemID); 1935 IScriptInstance instance = GetInstance(itemID);
1944 if (instance == null) 1936 return instance == null ? null : instance.GetApi(name);
1945 return null;
1946 return instance.GetApi(name);
1947 } 1937 }
1948 1938
1949 public void OnGetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) 1939 public void OnGetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID)
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
index 8dd7677..9d9dee1 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
@@ -52,16 +52,16 @@ namespace OpenSim.Region.ScriptEngine.XEngine
52 return wr.Cancel(); 52 return wr.Cancel();
53 } 53 }
54 54
55 public void Abort() 55 public bool Abort()
56 { 56 {
57 wr.Abort(); 57 return wr.Cancel(true);
58 } 58 }
59 59
60 public bool Wait(int t) 60 public bool Wait(int t)
61 { 61 {
62 // We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the 62 // We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the
63 // TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an 63 // TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an
64 // int (32-bit) we can end up with bad values. This occurs on Windows though curious not on Mono 2.10.8 64 // int (32-bit) we can end up with bad values. This occurs on Windows though curiously not on Mono 2.10.8
65 // (or very likely other versions of Mono at least up until 3.0.3). 65 // (or very likely other versions of Mono at least up until 3.0.3).
66 return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false); 66 return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false);
67 } 67 }
diff --git a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
index 1fff12a..f2d3255 100644
--- a/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/UserStatistics/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Server/Base/Properties/AssemblyInfo.cs b/OpenSim/Server/Base/Properties/AssemblyInfo.cs
index b4732b8..67340c7 100644
--- a/OpenSim/Server/Base/Properties/AssemblyInfo.cs
+++ b/OpenSim/Server/Base/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs
index 210a314..08ba50d 100644
--- a/OpenSim/Server/Base/ServerUtils.cs
+++ b/OpenSim/Server/Base/ServerUtils.cs
@@ -286,6 +286,7 @@ namespace OpenSim.Server.Base
286 e.InnerException == null ? e.Message : e.InnerException.Message, 286 e.InnerException == null ? e.Message : e.InnerException.Message,
287 e.StackTrace); 287 e.StackTrace);
288 } 288 }
289 m_log.ErrorFormat("[SERVER UTILS]: Error loading plugin {0}: {1} args.Length {2}", dllName, e.Message, args.Length);
289 return null; 290 return null;
290 } 291 }
291 292
diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs
index 7c8e6b7..667cef8 100644
--- a/OpenSim/Server/Base/ServicesServerBase.cs
+++ b/OpenSim/Server/Base/ServicesServerBase.cs
@@ -34,6 +34,7 @@ using System.Text;
34using System.Xml; 34using System.Xml;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Console; 36using OpenSim.Framework.Console;
37using OpenSim.Framework.Monitoring;
37using OpenSim.Framework.Servers; 38using OpenSim.Framework.Servers;
38using log4net; 39using log4net;
39using log4net.Config; 40using log4net.Config;
@@ -171,11 +172,6 @@ namespace OpenSim.Server.Base
171 172
172 m_console = MainConsole.Instance; 173 m_console = MainConsole.Instance;
173 174
174 // Configure the appenders for log4net
175 //
176 OpenSimAppender consoleAppender = null;
177 FileAppender fileAppender = null;
178
179 if (logConfig != null) 175 if (logConfig != null)
180 { 176 {
181 FileInfo cfg = new FileInfo(logConfig); 177 FileInfo cfg = new FileInfo(logConfig);
@@ -195,16 +191,7 @@ namespace OpenSim.Server.Base
195 } 191 }
196 192
197 RegisterCommonCommands(); 193 RegisterCommonCommands();
198 194 RegisterCommonComponents(Config);
199 // Register the quit command
200 //
201 MainConsole.Instance.Commands.AddCommand("General", false, "quit",
202 "quit",
203 "Quit the application", HandleQuit);
204
205 MainConsole.Instance.Commands.AddCommand("General", false, "shutdown",
206 "shutdown",
207 "Quit the application", HandleQuit);
208 195
209 // Allow derived classes to perform initialization that 196 // Allow derived classes to perform initialization that
210 // needs to be done after the console has opened 197 // needs to be done after the console has opened
@@ -219,6 +206,9 @@ namespace OpenSim.Server.Base
219 206
220 public virtual int Run() 207 public virtual int Run()
221 { 208 {
209 Watchdog.Enabled = true;
210 MemoryWatchdog.Enabled = true;
211
222 while (m_Running) 212 while (m_Running)
223 { 213 {
224 try 214 try
@@ -236,11 +226,12 @@ namespace OpenSim.Server.Base
236 return 0; 226 return 0;
237 } 227 }
238 228
239 protected virtual void HandleQuit(string module, string[] args) 229 protected override void ShutdownSpecific()
240 { 230 {
241 m_Running = false; 231 m_Running = false;
242 m_log.Info("[CONSOLE] Quitting"); 232 m_log.Info("[CONSOLE] Quitting");
243 233
234 base.ShutdownSpecific();
244 } 235 }
245 236
246 protected virtual void ReadConfig() 237 protected virtual void ReadConfig()
@@ -251,4 +242,4 @@ namespace OpenSim.Server.Base
251 { 242 {
252 } 243 }
253 } 244 }
254} 245} \ No newline at end of file
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs
index ff45d94..cc4325a 100644
--- a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs
+++ b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs
@@ -119,16 +119,14 @@ namespace OpenSim.Server.Handlers.Asset
119 119
120 if (asset == null || asset.Data.Length == 0) 120 if (asset == null || asset.Data.Length == 0)
121 { 121 {
122 MainConsole.Instance.Output("Asset not found"); 122 MainConsole.Instance.OutputFormat("Could not find asset with ID {0}", args[2]);
123 return; 123 return;
124 } 124 }
125 125
126 m_AssetService.Delete(args[2]); 126 if (!m_AssetService.Delete(asset.ID))
127 127 MainConsole.Instance.OutputFormat("ERROR: Could not delete asset {0} {1}", asset.ID, asset.Name);
128 //MainConsole.Instance.Output("Asset deleted"); 128 else
129 // TODO: Implement this 129 MainConsole.Instance.OutputFormat("Deleted asset {0} {1}", asset.ID, asset.Name);
130
131 MainConsole.Instance.Output("Asset deletion not supported by database");
132 } 130 }
133 131
134 void HandleDumpAsset(string module, string[] args) 132 void HandleDumpAsset(string module, string[] args)
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs b/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs
index 986394b..941b97d 100644
--- a/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs
+++ b/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Server.Handlers.Asset
70 m_allowedTypes = allowedTypes; 70 m_allowedTypes = allowedTypes;
71 } 71 }
72 72
73 public override byte[] Handle(string path, Stream request, 73 protected override byte[] ProcessRequest(string path, Stream request,
74 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 74 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
75 { 75 {
76 bool result = false; 76 bool result = false;
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs b/OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs
index 8f7412b..8b23a83 100644
--- a/OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs
+++ b/OpenSim/Server/Handlers/Asset/AssetServerGetHandler.cs
@@ -54,7 +54,7 @@ namespace OpenSim.Server.Handlers.Asset
54 m_AssetService = service; 54 m_AssetService = service;
55 } 55 }
56 56
57 public override byte[] Handle(string path, Stream request, 57 protected override byte[] ProcessRequest(string path, Stream request,
58 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 58 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 { 59 {
60 byte[] result = new byte[0]; 60 byte[] result = new byte[0];
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs b/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs
index a006fa8..8eebc61 100644
--- a/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs
@@ -54,7 +54,7 @@ namespace OpenSim.Server.Handlers.Asset
54 m_AssetService = service; 54 m_AssetService = service;
55 } 55 }
56 56
57 public override byte[] Handle(string path, Stream request, 57 protected override byte[] ProcessRequest(string path, Stream request,
58 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 58 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 { 59 {
60 AssetBase asset; 60 AssetBase asset;
diff --git a/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs b/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs
index 6b93cd9..16e011a 100644
--- a/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Server.Handlers.Authentication
70 } 70 }
71 } 71 }
72 72
73 public override byte[] Handle(string path, Stream request, 73 protected override byte[] ProcessRequest(string path, Stream request,
74 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 74 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
75 { 75 {
76 string[] p = SplitParams(path); 76 string[] p = SplitParams(path);
diff --git a/OpenSim/Server/Handlers/Authentication/OpenIdServerHandler.cs b/OpenSim/Server/Handlers/Authentication/OpenIdServerHandler.cs
index 18cef15..66a26fc 100644
--- a/OpenSim/Server/Handlers/Authentication/OpenIdServerHandler.cs
+++ b/OpenSim/Server/Handlers/Authentication/OpenIdServerHandler.cs
@@ -147,7 +147,7 @@ namespace OpenSim.Server.Handlers.Authentication
147 #endregion 147 #endregion
148 } 148 }
149 149
150 public class OpenIdStreamHandler : IStreamHandler 150 public class OpenIdStreamHandler : BaseOutputStreamHandler
151 { 151 {
152 #region HTML 152 #region HTML
153 153
@@ -191,42 +191,34 @@ For more information, see <a href='http://openid.net/'>http://openid.net/</a>.
191 191
192 #endregion HTML 192 #endregion HTML
193 193
194 public string Name { get { return "OpenId"; } }
195 public string Description { get { return null; } }
196 public string ContentType { get { return m_contentType; } }
197 public string HttpMethod { get { return m_httpMethod; } }
198 public string Path { get { return m_path; } }
199
200 string m_contentType;
201 string m_httpMethod;
202 string m_path;
203 IAuthenticationService m_authenticationService; 194 IAuthenticationService m_authenticationService;
204 IUserAccountService m_userAccountService; 195 IUserAccountService m_userAccountService;
205 ProviderMemoryStore m_openidStore = new ProviderMemoryStore(); 196 ProviderMemoryStore m_openidStore = new ProviderMemoryStore();
206 197
198 public override string ContentType { get { return "text/html"; } }
199
207 /// <summary> 200 /// <summary>
208 /// Constructor 201 /// Constructor
209 /// </summary> 202 /// </summary>
210 public OpenIdStreamHandler(string httpMethod, string path, IUserAccountService userService, IAuthenticationService authService) 203 public OpenIdStreamHandler(
204 string httpMethod, string path, IUserAccountService userService, IAuthenticationService authService)
205 : base(httpMethod, path, "OpenId", "OpenID stream handler")
211 { 206 {
212 m_authenticationService = authService; 207 m_authenticationService = authService;
213 m_userAccountService = userService; 208 m_userAccountService = userService;
214 m_httpMethod = httpMethod;
215 m_path = path;
216
217 m_contentType = "text/html";
218 } 209 }
219 210
220 /// <summary> 211 /// <summary>
221 /// Handles all GET and POST requests for OpenID identifier pages and endpoint 212 /// Handles all GET and POST requests for OpenID identifier pages and endpoint
222 /// server communication 213 /// server communication
223 /// </summary> 214 /// </summary>
224 public void Handle(string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 215 protected override void ProcessRequest(
216 string path, Stream request, Stream response, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
225 { 217 {
226 Uri providerEndpoint = new Uri(String.Format("{0}://{1}{2}", httpRequest.Url.Scheme, httpRequest.Url.Authority, httpRequest.Url.AbsolutePath)); 218 Uri providerEndpoint = new Uri(String.Format("{0}://{1}{2}", httpRequest.Url.Scheme, httpRequest.Url.Authority, httpRequest.Url.AbsolutePath));
227 219
228 // Defult to returning HTML content 220 // Defult to returning HTML content
229 m_contentType = "text/html"; 221 httpResponse.ContentType = ContentType;
230 222
231 try 223 try
232 { 224 {
@@ -276,7 +268,7 @@ For more information, see <a href='http://openid.net/'>http://openid.net/</a>.
276 268
277 string[] contentTypeValues = provider.Request.Response.Headers.GetValues("Content-Type"); 269 string[] contentTypeValues = provider.Request.Response.Headers.GetValues("Content-Type");
278 if (contentTypeValues != null && contentTypeValues.Length == 1) 270 if (contentTypeValues != null && contentTypeValues.Length == 1)
279 m_contentType = contentTypeValues[0]; 271 httpResponse.ContentType = contentTypeValues[0];
280 272
281 // Set the response code and document body based on the OpenID result 273 // Set the response code and document body based on the OpenID result
282 httpResponse.StatusCode = (int)provider.Request.Response.Code; 274 httpResponse.StatusCode = (int)provider.Request.Response.Code;
@@ -344,4 +336,4 @@ For more information, see <a href='http://openid.net/'>http://openid.net/</a>.
344 return false; 336 return false;
345 } 337 }
346 } 338 }
347} 339} \ No newline at end of file
diff --git a/OpenSim/Server/Handlers/Authorization/AuthorizationServerPostHandler.cs b/OpenSim/Server/Handlers/Authorization/AuthorizationServerPostHandler.cs
index bcf9d47..c9b4e9b 100644
--- a/OpenSim/Server/Handlers/Authorization/AuthorizationServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Authorization/AuthorizationServerPostHandler.cs
@@ -54,7 +54,7 @@ namespace OpenSim.Server.Handlers.Authorization
54 m_AuthorizationService = service; 54 m_AuthorizationService = service;
55 } 55 }
56 56
57 public override byte[] Handle(string path, Stream request, 57 protected override byte[] ProcessRequest(string path, Stream request,
58 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 58 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
59 { 59 {
60 XmlSerializer xs = new XmlSerializer(typeof (AuthorizationRequest)); 60 XmlSerializer xs = new XmlSerializer(typeof (AuthorizationRequest));
diff --git a/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs b/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs
index 8cd747e..d6bbb8f 100644
--- a/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs
@@ -56,7 +56,7 @@ namespace OpenSim.Server.Handlers.Avatar
56 m_AvatarService = service; 56 m_AvatarService = service;
57 } 57 }
58 58
59 public override byte[] Handle(string path, Stream requestData, 59 protected override byte[] ProcessRequest(string path, Stream requestData,
60 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 60 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
61 { 61 {
62 StreamReader sr = new StreamReader(requestData); 62 StreamReader sr = new StreamReader(requestData);
diff --git a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs
index 47a8558..ca0a24c 100644
--- a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs
@@ -57,7 +57,7 @@ namespace OpenSim.Server.Handlers.Friends
57 m_FriendsService = service; 57 m_FriendsService = service;
58 } 58 }
59 59
60 public override byte[] Handle(string path, Stream requestData, 60 protected override byte[] ProcessRequest(string path, Stream requestData,
61 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 61 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
62 { 62 {
63 StreamReader sr = new StreamReader(requestData); 63 StreamReader sr = new StreamReader(requestData);
diff --git a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs
index ef5f33e..c63b409 100644
--- a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs
@@ -57,7 +57,7 @@ namespace OpenSim.Server.Handlers.Grid
57 m_GridService = service; 57 m_GridService = service;
58 } 58 }
59 59
60 public override byte[] Handle(string path, Stream requestData, 60 protected override byte[] ProcessRequest(string path, Stream requestData,
61 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 61 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
62 { 62 {
63 StreamReader sr = new StreamReader(requestData); 63 StreamReader sr = new StreamReader(requestData);
@@ -106,6 +106,9 @@ namespace OpenSim.Server.Handlers.Grid
106 case "get_default_regions": 106 case "get_default_regions":
107 return GetDefaultRegions(request); 107 return GetDefaultRegions(request);
108 108
109 case "get_default_hypergrid_regions":
110 return GetDefaultHypergridRegions(request);
111
109 case "get_fallback_regions": 112 case "get_fallback_regions":
110 return GetFallbackRegions(request); 113 return GetFallbackRegions(request);
111 114
@@ -444,6 +447,36 @@ namespace OpenSim.Server.Handlers.Grid
444 return Util.UTF8NoBomEncoding.GetBytes(xmlString); 447 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
445 } 448 }
446 449
450 byte[] GetDefaultHypergridRegions(Dictionary<string, object> request)
451 {
452 //m_log.DebugFormat("[GRID HANDLER]: GetDefaultRegions");
453 UUID scopeID = UUID.Zero;
454 if (request.ContainsKey("SCOPEID"))
455 UUID.TryParse(request["SCOPEID"].ToString(), out scopeID);
456 else
457 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get region range");
458
459 List<GridRegion> rinfos = m_GridService.GetDefaultHypergridRegions(scopeID);
460
461 Dictionary<string, object> result = new Dictionary<string, object>();
462 if ((rinfos == null) || ((rinfos != null) && (rinfos.Count == 0)))
463 result["result"] = "null";
464 else
465 {
466 int i = 0;
467 foreach (GridRegion rinfo in rinfos)
468 {
469 Dictionary<string, object> rinfoDict = rinfo.ToKeyValuePairs();
470 result["region" + i] = rinfoDict;
471 i++;
472 }
473 }
474 string xmlString = ServerUtils.BuildXmlResponse(result);
475
476 //m_log.DebugFormat("[GRID HANDLER]: resp string: {0}", xmlString);
477 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
478 }
479
447 byte[] GetFallbackRegions(Dictionary<string, object> request) 480 byte[] GetFallbackRegions(Dictionary<string, object> request)
448 { 481 {
449 //m_log.DebugFormat("[GRID HANDLER]: GetRegionRange"); 482 //m_log.DebugFormat("[GRID HANDLER]: GetRegionRange");
diff --git a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs
index 687cf8d..0b98e9a 100644
--- a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs
@@ -56,7 +56,7 @@ namespace OpenSim.Server.Handlers.GridUser
56 m_GridUserService = service; 56 m_GridUserService = service;
57 } 57 }
58 58
59 public override byte[] Handle(string path, Stream requestData, 59 protected override byte[] ProcessRequest(string path, Stream requestData,
60 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 60 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
61 { 61 {
62 StreamReader sr = new StreamReader(requestData); 62 StreamReader sr = new StreamReader(requestData);
@@ -185,10 +185,12 @@ namespace OpenSim.Server.Handlers.GridUser
185 GridUserInfo guinfo = m_GridUserService.GetGridUserInfo(user); 185 GridUserInfo guinfo = m_GridUserService.GetGridUserInfo(user);
186 186
187 Dictionary<string, object> result = new Dictionary<string, object>(); 187 Dictionary<string, object> result = new Dictionary<string, object>();
188 result["result"] = guinfo.ToKeyValuePairs(); 188 if (guinfo != null)
189 result["result"] = guinfo.ToKeyValuePairs();
190 else
191 result["result"] = "null";
189 192
190 string xmlString = ServerUtils.BuildXmlResponse(result); 193 string xmlString = ServerUtils.BuildXmlResponse(result);
191
192 //m_log.DebugFormat("[GRID USER HANDLER]: resp string: {0}", xmlString); 194 //m_log.DebugFormat("[GRID USER HANDLER]: resp string: {0}", xmlString);
193 return Util.UTF8NoBomEncoding.GetBytes(xmlString); 195 return Util.UTF8NoBomEncoding.GetBytes(xmlString);
194 } 196 }
diff --git a/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs
index cf1af15..adc2fbc 100644
--- a/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/AgentHandlers.cs
@@ -61,7 +61,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
61 m_Proxy = proxy; 61 m_Proxy = proxy;
62 } 62 }
63 63
64 protected override bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) 64 protected override bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
65 { 65 {
66 return m_GatekeeperService.LoginAgent(aCircuit, destination, out reason); 66 return m_GatekeeperService.LoginAgent(aCircuit, destination, out reason);
67 } 67 }
diff --git a/OpenSim/Server/Handlers/Hypergrid/GatekeeperServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/GatekeeperServerConnector.cs
index 0d4990a..ffe2f36 100644
--- a/OpenSim/Server/Handlers/Hypergrid/GatekeeperServerConnector.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/GatekeeperServerConnector.cs
@@ -76,10 +76,14 @@ namespace OpenSim.Server.Handlers.Hypergrid
76 server.AddStreamHandler(new GatekeeperAgentHandler(m_GatekeeperService, m_Proxy)); 76 server.AddStreamHandler(new GatekeeperAgentHandler(m_GatekeeperService, m_Proxy));
77 } 77 }
78 78
79 public GatekeeperServiceInConnector(IConfigSource config, IHttpServer server) 79 public GatekeeperServiceInConnector(IConfigSource config, IHttpServer server, string configName)
80 : this(config, server, null) 80 : this(config, server, (ISimulationService)null)
81 { 81 {
82 } 82 }
83 83
84 public GatekeeperServiceInConnector(IConfigSource config, IHttpServer server)
85 : this(config, server, String.Empty)
86 {
87 }
84 } 88 }
85} 89}
diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs
index 0aa2729..a2bdadb 100644
--- a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
68 m_log.ErrorFormat("[HGFRIENDS HANDLER]: TheService is null!"); 68 m_log.ErrorFormat("[HGFRIENDS HANDLER]: TheService is null!");
69 } 69 }
70 70
71 public override byte[] Handle(string path, Stream requestData, 71 protected override byte[] ProcessRequest(string path, Stream requestData,
72 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 72 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
73 { 73 {
74 StreamReader sr = new StreamReader(requestData); 74 StreamReader sr = new StreamReader(requestData);
diff --git a/OpenSim/Server/Handlers/Hypergrid/HeloServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/HeloServerConnector.cs
index f306b1c..06eaf2e 100644
--- a/OpenSim/Server/Handlers/Hypergrid/HeloServerConnector.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/HeloServerConnector.cs
@@ -91,7 +91,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
91 m_HandlersType = handlersType; 91 m_HandlersType = handlersType;
92 } 92 }
93 93
94 public override byte[] Handle(string path, Stream requestData, 94 protected override byte[] ProcessRequest(string path, Stream requestData,
95 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 95 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
96 { 96 {
97 return OKResponse(httpResponse); 97 return OKResponse(httpResponse);
diff --git a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs
index 968c1e6..04bb9e8 100644
--- a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs
@@ -49,191 +49,88 @@ using log4net;
49 49
50namespace OpenSim.Server.Handlers.Hypergrid 50namespace OpenSim.Server.Handlers.Hypergrid
51{ 51{
52 public class HomeAgentHandler 52 public class HomeAgentHandler : AgentPostHandler
53 { 53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private IUserAgentService m_UserAgentService; 55 private IUserAgentService m_UserAgentService;
56 56
57 private string m_LoginServerIP; 57 private string m_LoginServerIP;
58 private bool m_Proxy = false;
59 58
60 public HomeAgentHandler(IUserAgentService userAgentService, string loginServerIP, bool proxy) 59 public HomeAgentHandler(IUserAgentService userAgentService, string loginServerIP, bool proxy) :
60 base("/homeagent")
61 { 61 {
62 m_UserAgentService = userAgentService; 62 m_UserAgentService = userAgentService;
63 m_LoginServerIP = loginServerIP; 63 m_LoginServerIP = loginServerIP;
64 m_Proxy = proxy; 64 m_Proxy = proxy;
65 } 65 }
66 66
67 public Hashtable Handler(Hashtable request) 67 protected override AgentDestinationData CreateAgentDestinationData()
68 { 68 {
69// m_log.Debug("[CONNECTION DEBUGGING]: HomeAgentHandler Called"); 69 return new ExtendedAgentDestinationData();
70// 70 }
71// m_log.Debug("---------------------------"); 71
72// m_log.Debug(" >> uri=" + request["uri"]); 72 protected override void UnpackData(OSDMap args, AgentDestinationData d, Hashtable request)
73// m_log.Debug(" >> content-type=" + request["content-type"]); 73 {
74// m_log.Debug(" >> http-method=" + request["http-method"]); 74 base.UnpackData(args, d, request);
75// m_log.Debug("---------------------------\n"); 75 ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d;
76 76 try
77 Hashtable responsedata = new Hashtable();
78 responsedata["content_type"] = "text/html";
79 responsedata["keepalive"] = false;
80
81
82 UUID agentID;
83 UUID regionID;
84 string action;
85 if (!Utils.GetParams((string)request["uri"], out agentID, out regionID, out action))
86 { 77 {
87 m_log.InfoFormat("[HOME AGENT HANDLER]: Invalid parameters for agent message {0}", request["uri"]); 78 if (args.ContainsKey("gatekeeper_host") && args["gatekeeper_host"] != null)
88 responsedata["int_response_code"] = 404; 79 data.host = args["gatekeeper_host"].AsString();
89 responsedata["str_response_string"] = "false"; 80 if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null)
81 Int32.TryParse(args["gatekeeper_port"].AsString(), out data.port);
82 if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] != null)
83 data.gatekeeperServerURI = args["gatekeeper_serveruri"];
84 if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] != null)
85 data.destinationServerURI = args["destination_serveruri"];
90 86
91 return responsedata;
92 } 87 }
93 88 catch (InvalidCastException)
94 // Next, let's parse the verb
95 string method = (string)request["http-method"];
96 if (method.Equals("POST"))
97 { 89 {
98 DoAgentPost(request, responsedata, agentID); 90 m_log.ErrorFormat("[HOME AGENT HANDLER]: Bad cast in UnpackData");
99 return responsedata;
100 } 91 }
101 else
102 {
103 m_log.InfoFormat("[HOME AGENT HANDLER]: method {0} not supported in agent message", method);
104 responsedata["int_response_code"] = HttpStatusCode.MethodNotAllowed;
105 responsedata["str_response_string"] = "Method not allowed";
106 92
107 return responsedata; 93 string callerIP = GetCallerIP(request);
108 } 94 // Verify if this call came from the login server
95 if (callerIP == m_LoginServerIP)
96 data.fromLogin = true;
109 97
110 } 98 }
111 99
112 protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id) 100 protected override GridRegion ExtractGatekeeper(AgentDestinationData d)
113 { 101 {
114 OSDMap args = Utils.GetOSDMap((string)request["body"]); 102 if (d is ExtendedAgentDestinationData)
115 if (args == null)
116 { 103 {
117 responsedata["int_response_code"] = HttpStatusCode.BadRequest; 104 ExtendedAgentDestinationData data = (ExtendedAgentDestinationData)d;
118 responsedata["str_response_string"] = "Bad request"; 105 GridRegion gatekeeper = new GridRegion();
119 return; 106 gatekeeper.ServerURI = data.gatekeeperServerURI;
107 gatekeeper.ExternalHostName = data.host;
108 gatekeeper.HttpPort = (uint)data.port;
109 gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
110
111 return gatekeeper;
120 } 112 }
121
122 // retrieve the input arguments
123 int x = 0, y = 0;
124 UUID uuid = UUID.Zero;
125 string regionname = string.Empty;
126 string gatekeeper_host = string.Empty;
127 string gatekeeper_serveruri = string.Empty;
128 string destination_serveruri = string.Empty;
129 int gatekeeper_port = 0;
130 IPEndPoint client_ipaddress = null;
131
132 if (args.ContainsKey("gatekeeper_host") && args["gatekeeper_host"] != null)
133 gatekeeper_host = args["gatekeeper_host"].AsString();
134 if (args.ContainsKey("gatekeeper_port") && args["gatekeeper_port"] != null)
135 Int32.TryParse(args["gatekeeper_port"].AsString(), out gatekeeper_port);
136 if (args.ContainsKey("gatekeeper_serveruri") && args["gatekeeper_serveruri"] !=null)
137 gatekeeper_serveruri = args["gatekeeper_serveruri"];
138 if (args.ContainsKey("destination_serveruri") && args["destination_serveruri"] !=null)
139 destination_serveruri = args["destination_serveruri"];
140
141 GridRegion gatekeeper = new GridRegion();
142 gatekeeper.ServerURI = gatekeeper_serveruri;
143 gatekeeper.ExternalHostName = gatekeeper_host;
144 gatekeeper.HttpPort = (uint)gatekeeper_port;
145 gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
146
147 if (args.ContainsKey("destination_x") && args["destination_x"] != null)
148 Int32.TryParse(args["destination_x"].AsString(), out x);
149 else
150 m_log.WarnFormat(" -- request didn't have destination_x");
151 if (args.ContainsKey("destination_y") && args["destination_y"] != null)
152 Int32.TryParse(args["destination_y"].AsString(), out y);
153 else 113 else
154 m_log.WarnFormat(" -- request didn't have destination_y"); 114 m_log.WarnFormat("[HOME AGENT HANDLER]: Wrong data type");
155 if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
156 UUID.TryParse(args["destination_uuid"].AsString(), out uuid);
157 if (args.ContainsKey("destination_name") && args["destination_name"] != null)
158 regionname = args["destination_name"].ToString();
159
160 if (args.ContainsKey("client_ip") && args["client_ip"] != null)
161 {
162 string ip_str = args["client_ip"].ToString();
163 try
164 {
165 string callerIP = GetCallerIP(request);
166 // Verify if this caller has authority to send the client IP
167 if (callerIP == m_LoginServerIP)
168 client_ipaddress = new IPEndPoint(IPAddress.Parse(ip_str), 0);
169 else // leaving this for now, but this warning should be removed
170 m_log.WarnFormat("[HOME AGENT HANDLER]: Unauthorized machine {0} tried to set client ip to {1}", callerIP, ip_str);
171 }
172 catch
173 {
174 m_log.DebugFormat("[HOME AGENT HANDLER]: Exception parsing client ip address from {0}", ip_str);
175 }
176 }
177 115
178 GridRegion destination = new GridRegion(); 116 return null;
179 destination.RegionID = uuid;
180 destination.RegionLocX = x;
181 destination.RegionLocY = y;
182 destination.RegionName = regionname;
183 destination.ServerURI = destination_serveruri;
184
185 AgentCircuitData aCircuit = new AgentCircuitData();
186 try
187 {
188 aCircuit.UnpackAgentCircuitData(args);
189 }
190 catch (Exception ex)
191 {
192 m_log.InfoFormat("[HOME AGENT HANDLER]: exception on unpacking ChildCreate message {0}", ex.Message);
193 responsedata["int_response_code"] = HttpStatusCode.BadRequest;
194 responsedata["str_response_string"] = "Bad request";
195 return;
196 }
197
198 OSDMap resp = new OSDMap(2);
199 string reason = String.Empty;
200
201 bool result = m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, client_ipaddress, out reason);
202
203 resp["reason"] = OSD.FromString(reason);
204 resp["success"] = OSD.FromBoolean(result);
205
206 // TODO: add reason if not String.Empty?
207 responsedata["int_response_code"] = HttpStatusCode.OK;
208 responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
209 } 117 }
210 118
211 private string GetCallerIP(Hashtable request)
212 {
213 if (!m_Proxy)
214 return Util.GetCallerIP(request);
215
216 // We're behind a proxy
217 Hashtable headers = (Hashtable)request["headers"];
218 string xff = "X-Forwarded-For";
219 if (headers.ContainsKey(xff.ToLower()))
220 xff = xff.ToLower();
221 119
222 if (!headers.ContainsKey(xff) || headers[xff] == null) 120 protected override bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
223 { 121 {
224 m_log.WarnFormat("[AGENT HANDLER]: No XFF header"); 122 return m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, fromLogin, out reason);
225 return Util.GetCallerIP(request); 123 }
226 }
227 124
228 m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]); 125 }
229 126
230 IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]); 127 public class ExtendedAgentDestinationData : AgentDestinationData
231 if (ep != null) 128 {
232 return ep.Address.ToString(); 129 public string host;
130 public int port;
131 public string gatekeeperServerURI;
132 public string destinationServerURI;
233 133
234 // Oops
235 return Util.GetCallerIP(request);
236 }
237 } 134 }
238 135
239} 136}
diff --git a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs
index 80eb5d2..8145a21 100644
--- a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs
@@ -54,10 +54,15 @@ namespace OpenSim.Server.Handlers.Hypergrid
54 private IInstantMessage m_IMService; 54 private IInstantMessage m_IMService;
55 55
56 public InstantMessageServerConnector(IConfigSource config, IHttpServer server) : 56 public InstantMessageServerConnector(IConfigSource config, IHttpServer server) :
57 this(config, server, null) 57 this(config, server, (IInstantMessageSimConnector)null)
58 { 58 {
59 } 59 }
60 60
61 public InstantMessageServerConnector(IConfigSource config, IHttpServer server, string configName) :
62 this(config, server)
63 {
64 }
65
61 public InstantMessageServerConnector(IConfigSource config, IHttpServer server, IInstantMessageSimConnector simConnector) : 66 public InstantMessageServerConnector(IConfigSource config, IHttpServer server, IInstantMessageSimConnector simConnector) :
62 base(config, server, String.Empty) 67 base(config, server, String.Empty)
63 { 68 {
diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
index db62aaa..7137836 100644
--- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
@@ -62,10 +62,15 @@ namespace OpenSim.Server.Handlers.Hypergrid
62 private bool m_VerifyCallers = false; 62 private bool m_VerifyCallers = false;
63 63
64 public UserAgentServerConnector(IConfigSource config, IHttpServer server) : 64 public UserAgentServerConnector(IConfigSource config, IHttpServer server) :
65 this(config, server, null) 65 this(config, server, (IFriendsSimConnector)null)
66 { 66 {
67 } 67 }
68 68
69 public UserAgentServerConnector(IConfigSource config, IHttpServer server, string configName) :
70 this(config, server)
71 {
72 }
73
69 public UserAgentServerConnector(IConfigSource config, IHttpServer server, IFriendsSimConnector friendsConnector) : 74 public UserAgentServerConnector(IConfigSource config, IHttpServer server, IFriendsSimConnector friendsConnector) :
70 base(config, server, String.Empty) 75 base(config, server, String.Empty)
71 { 76 {
@@ -103,7 +108,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
103 server.AddXmlRPCHandler("get_uui", GetUUI, false); 108 server.AddXmlRPCHandler("get_uui", GetUUI, false);
104 server.AddXmlRPCHandler("get_uuid", GetUUID, false); 109 server.AddXmlRPCHandler("get_uuid", GetUUID, false);
105 110
106 server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); 111 server.AddStreamHandler(new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy));
107 } 112 }
108 113
109 public XmlRpcResponse GetHomeRegion(XmlRpcRequest request, IPEndPoint remoteClient) 114 public XmlRpcResponse GetHomeRegion(XmlRpcRequest request, IPEndPoint remoteClient)
@@ -448,7 +453,6 @@ namespace OpenSim.Server.Handlers.Hypergrid
448 XmlRpcResponse response = new XmlRpcResponse(); 453 XmlRpcResponse response = new XmlRpcResponse();
449 response.Value = hash; 454 response.Value = hash;
450 return response; 455 return response;
451
452 } 456 }
453 457
454 /// <summary> 458 /// <summary>
@@ -466,9 +470,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
466 //string portstr = (string)requestData["port"]; 470 //string portstr = (string)requestData["port"];
467 if (requestData.ContainsKey("first") && requestData.ContainsKey("last")) 471 if (requestData.ContainsKey("first") && requestData.ContainsKey("last"))
468 { 472 {
469 UUID userID = UUID.Zero;
470 string first = (string)requestData["first"]; 473 string first = (string)requestData["first"];
471
472 string last = (string)requestData["last"]; 474 string last = (string)requestData["last"];
473 UUID uuid = m_HomeUsersService.GetUUID(first, last); 475 UUID uuid = m_HomeUsersService.GetUUID(first, last);
474 hash["UUID"] = uuid.ToString(); 476 hash["UUID"] = uuid.ToString();
@@ -477,7 +479,6 @@ namespace OpenSim.Server.Handlers.Hypergrid
477 XmlRpcResponse response = new XmlRpcResponse(); 479 XmlRpcResponse response = new XmlRpcResponse();
478 response.Value = hash; 480 response.Value = hash;
479 return response; 481 return response;
480
481 } 482 }
482 } 483 }
483} 484} \ No newline at end of file
diff --git a/OpenSim/Server/Handlers/Inventory/InventoryServerMoveItemsHandler.cs b/OpenSim/Server/Handlers/Inventory/InventoryServerMoveItemsHandler.cs
index 231e32f..e2c50fe 100644
--- a/OpenSim/Server/Handlers/Inventory/InventoryServerMoveItemsHandler.cs
+++ b/OpenSim/Server/Handlers/Inventory/InventoryServerMoveItemsHandler.cs
@@ -56,7 +56,7 @@ namespace OpenSim.Server.Handlers.Inventory
56 m_InventoryService = service; 56 m_InventoryService = service;
57 } 57 }
58 58
59 public override byte[] Handle(string path, Stream request, 59 protected override byte[] ProcessRequest(string path, Stream request,
60 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 60 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
61 { 61 {
62 XmlSerializer xs = new XmlSerializer(typeof (List<InventoryItemBase>)); 62 XmlSerializer xs = new XmlSerializer(typeof (List<InventoryItemBase>));
diff --git a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs
index 64127c2..0d7c136 100644
--- a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs
+++ b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs
@@ -87,7 +87,7 @@ namespace OpenSim.Server.Handlers.Asset
87 m_InventoryService = service; 87 m_InventoryService = service;
88 } 88 }
89 89
90 public override byte[] Handle(string path, Stream requestData, 90 protected override byte[] ProcessRequest(string path, Stream requestData,
91 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 91 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
92 { 92 {
93 StreamReader sr = new StreamReader(requestData); 93 StreamReader sr = new StreamReader(requestData);
@@ -155,7 +155,7 @@ namespace OpenSim.Server.Handlers.Asset
155 } 155 }
156 catch (Exception e) 156 catch (Exception e)
157 { 157 {
158 m_log.DebugFormat("[XINVENTORY HANDLER]: Exception {0}", e.StackTrace); 158 m_log.ErrorFormat("[XINVENTORY HANDLER]: Exception {0}", e.StackTrace);
159 } 159 }
160 160
161 return FailureResult(); 161 return FailureResult();
diff --git a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs
index f83a239..f2a5678 100644
--- a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs
+++ b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs
@@ -53,6 +53,7 @@ namespace OpenSim.Server.Handlers.Login
53 53
54 private ILoginService m_LocalService; 54 private ILoginService m_LocalService;
55 private bool m_Proxy; 55 private bool m_Proxy;
56
56 57
57 public LLLoginHandlers(ILoginService service, bool hasProxy) 58 public LLLoginHandlers(ILoginService service, bool hasProxy)
58 { 59 {
@@ -144,6 +145,17 @@ namespace OpenSim.Server.Handlers.Login
144 return FailedXMLRPCResponse(); 145 return FailedXMLRPCResponse();
145 146
146 } 147 }
148 public XmlRpcResponse HandleXMLRPCLoginBlocked(XmlRpcRequest request, IPEndPoint client)
149 {
150 XmlRpcResponse response = new XmlRpcResponse();
151 Hashtable resp = new Hashtable();
152
153 resp["reason"] = "presence";
154 resp["message"] = "Logins are currently restricted. Please try again later.";
155 resp["login"] = "false";
156 response.Value = resp;
157 return response;
158 }
147 159
148 public XmlRpcResponse HandleXMLRPCSetLoginLevel(XmlRpcRequest request, IPEndPoint remoteClient) 160 public XmlRpcResponse HandleXMLRPCSetLoginLevel(XmlRpcRequest request, IPEndPoint remoteClient)
149 { 161 {
@@ -213,6 +225,61 @@ namespace OpenSim.Server.Handlers.Login
213 return FailedOSDResponse(); 225 return FailedOSDResponse();
214 } 226 }
215 227
228 public void HandleWebSocketLoginEvents(string path, WebSocketHttpServerHandler sock)
229 {
230 sock.MaxPayloadSize = 16384; //16 kb payload
231 sock.InitialMsgTimeout = 5000; //5 second first message to trigger at least one of these events
232 sock.NoDelay_TCP_Nagle = true;
233 sock.OnData += delegate(object sender, WebsocketDataEventArgs data) { sock.Close("fail"); };
234 sock.OnPing += delegate(object sender, PingEventArgs pingdata) { sock.Close("fail"); };
235 sock.OnPong += delegate(object sender, PongEventArgs pongdata) { sock.Close("fail"); };
236 sock.OnText += delegate(object sender, WebsocketTextEventArgs text)
237 {
238 OSD request = null;
239 try
240 {
241 request = OSDParser.DeserializeJson(text.Data);
242 if (!(request is OSDMap))
243 {
244 sock.SendMessage(OSDParser.SerializeJsonString(FailedOSDResponse()));
245 }
246 else
247 {
248 OSDMap req = request as OSDMap;
249 string first = req["firstname"].AsString();
250 string last = req["lastname"].AsString();
251 string passwd = req["passwd"].AsString();
252 string start = req["startlocation"].AsString();
253 string version = req["version"].AsString();
254 string channel = req["channel"].AsString();
255 string mac = req["mac"].AsString();
256 string id0 = req["id0"].AsString();
257 UUID scope = UUID.Zero;
258 IPEndPoint endPoint =
259 (sender as WebSocketHttpServerHandler).GetRemoteIPEndpoint();
260 LoginResponse reply = null;
261 reply = m_LocalService.Login(first, last, passwd, start, scope, version,
262 channel, mac, id0, endPoint);
263 sock.SendMessage(OSDParser.SerializeJsonString(reply.ToOSDMap()));
264
265 }
266
267 }
268 catch (Exception)
269 {
270 sock.SendMessage(OSDParser.SerializeJsonString(FailedOSDResponse()));
271 }
272 finally
273 {
274 sock.Close("success");
275 }
276 };
277
278 sock.HandshakeAndUpgrade();
279
280 }
281
282
216 private XmlRpcResponse FailedXMLRPCResponse() 283 private XmlRpcResponse FailedXMLRPCResponse()
217 { 284 {
218 Hashtable hash = new Hashtable(); 285 Hashtable hash = new Hashtable();
diff --git a/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs b/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs
index 9a7ad34..f60e892 100644
--- a/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs
+++ b/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs
@@ -44,6 +44,7 @@ namespace OpenSim.Server.Handlers.Login
44 44
45 private ILoginService m_LoginService; 45 private ILoginService m_LoginService;
46 private bool m_Proxy; 46 private bool m_Proxy;
47 private BasicDosProtectorOptions m_DosProtectionOptions;
47 48
48 public LLLoginServiceInConnector(IConfigSource config, IHttpServer server, IScene scene) : 49 public LLLoginServiceInConnector(IConfigSource config, IHttpServer server, IScene scene) :
49 base(config, server, String.Empty) 50 base(config, server, String.Empty)
@@ -60,8 +61,8 @@ namespace OpenSim.Server.Handlers.Login
60 InitializeHandlers(server); 61 InitializeHandlers(server);
61 } 62 }
62 63
63 public LLLoginServiceInConnector(IConfigSource config, IHttpServer server) : 64 public LLLoginServiceInConnector(IConfigSource config, IHttpServer server, string configName) :
64 base(config, server, String.Empty) 65 base(config, server, configName)
65 { 66 {
66 string loginService = ReadLocalServiceFromConfig(config); 67 string loginService = ReadLocalServiceFromConfig(config);
67 68
@@ -72,6 +73,11 @@ namespace OpenSim.Server.Handlers.Login
72 InitializeHandlers(server); 73 InitializeHandlers(server);
73 } 74 }
74 75
76 public LLLoginServiceInConnector(IConfigSource config, IHttpServer server) :
77 this(config, server, String.Empty)
78 {
79 }
80
75 private string ReadLocalServiceFromConfig(IConfigSource config) 81 private string ReadLocalServiceFromConfig(IConfigSource config)
76 { 82 {
77 IConfig serverConfig = config.Configs["LoginService"]; 83 IConfig serverConfig = config.Configs["LoginService"];
@@ -83,6 +89,16 @@ namespace OpenSim.Server.Handlers.Login
83 throw new Exception(String.Format("No LocalServiceModule for LoginService in config file")); 89 throw new Exception(String.Format("No LocalServiceModule for LoginService in config file"));
84 90
85 m_Proxy = serverConfig.GetBoolean("HasProxy", false); 91 m_Proxy = serverConfig.GetBoolean("HasProxy", false);
92 m_DosProtectionOptions = new BasicDosProtectorOptions();
93 // Dos Protection Options
94 m_DosProtectionOptions.AllowXForwardedFor = serverConfig.GetBoolean("DOSAllowXForwardedForHeader", false);
95 m_DosProtectionOptions.RequestTimeSpan =
96 TimeSpan.FromMilliseconds(serverConfig.GetInt("DOSRequestTimeFrameMS", 10000));
97 m_DosProtectionOptions.MaxRequestsInTimeframe = serverConfig.GetInt("DOSMaxRequestsInTimeFrame", 5);
98 m_DosProtectionOptions.ForgetTimeSpan =
99 TimeSpan.FromMilliseconds(serverConfig.GetInt("DOSForgiveClientAfterMS", 120000));
100 m_DosProtectionOptions.ReportingName = "LOGINDOSPROTECTION";
101
86 102
87 return loginService; 103 return loginService;
88 } 104 }
@@ -90,9 +106,12 @@ namespace OpenSim.Server.Handlers.Login
90 private void InitializeHandlers(IHttpServer server) 106 private void InitializeHandlers(IHttpServer server)
91 { 107 {
92 LLLoginHandlers loginHandlers = new LLLoginHandlers(m_LoginService, m_Proxy); 108 LLLoginHandlers loginHandlers = new LLLoginHandlers(m_LoginService, m_Proxy);
93 server.AddXmlRPCHandler("login_to_simulator", loginHandlers.HandleXMLRPCLogin, false); 109 server.AddXmlRPCHandler("login_to_simulator",
110 new XmlRpcBasicDOSProtector(loginHandlers.HandleXMLRPCLogin,loginHandlers.HandleXMLRPCLoginBlocked,
111 m_DosProtectionOptions).Process, false);
94 server.AddXmlRPCHandler("set_login_level", loginHandlers.HandleXMLRPCSetLoginLevel, false); 112 server.AddXmlRPCHandler("set_login_level", loginHandlers.HandleXMLRPCSetLoginLevel, false);
95 server.SetDefaultLLSDHandler(loginHandlers.HandleLLSDLogin); 113 server.SetDefaultLLSDHandler(loginHandlers.HandleLLSDLogin);
114 server.AddWebSocketHandler("/WebSocket/GridLogin", loginHandlers.HandleWebSocketLoginEvents);
96 } 115 }
97 } 116 }
98} 117}
diff --git a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs
index 4a61969..d438fc7 100644
--- a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs
+++ b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs
@@ -99,7 +99,7 @@ namespace OpenSim.Server.Handlers.MapImage
99 m_Proxy = proxy; 99 m_Proxy = proxy;
100 } 100 }
101 101
102 public override byte[] Handle(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 102 protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
103 { 103 {
104// m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: Received {0}", path); 104// m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: Received {0}", path);
105 StreamReader sr = new StreamReader(requestData); 105 StreamReader sr = new StreamReader(requestData);
diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs
index 4502b7d..bd1ddbd 100644
--- a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs
+++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs
@@ -83,7 +83,7 @@ namespace OpenSim.Server.Handlers.MapImage
83 m_MapService = service; 83 m_MapService = service;
84 } 84 }
85 85
86 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 86 protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
87 { 87 {
88 ev.WaitOne(); 88 ev.WaitOne();
89 lock (ev) 89 lock (ev)
diff --git a/OpenSim/Server/Handlers/Neighbour/NeighbourHandlers.cs b/OpenSim/Server/Handlers/Neighbour/NeighbourHandlers.cs
index 8a1f824..3525a01 100644
--- a/OpenSim/Server/Handlers/Neighbour/NeighbourHandlers.cs
+++ b/OpenSim/Server/Handlers/Neighbour/NeighbourHandlers.cs
@@ -58,7 +58,7 @@ namespace OpenSim.Server.Handlers.Neighbour
58 // TODO: unused: m_AuthenticationService = authentication; 58 // TODO: unused: m_AuthenticationService = authentication;
59 } 59 }
60 60
61 public override byte[] Handle(string path, Stream request, 61 protected override byte[] ProcessRequest(string path, Stream request,
62 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 62 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
63 { 63 {
64 // Not implemented yet 64 // Not implemented yet
@@ -83,7 +83,7 @@ namespace OpenSim.Server.Handlers.Neighbour
83 // TODO: unused: m_AllowForeignGuests = foreignGuests; 83 // TODO: unused: m_AllowForeignGuests = foreignGuests;
84 } 84 }
85 85
86 public override byte[] Handle(string path, Stream request, 86 protected override byte[] ProcessRequest(string path, Stream request,
87 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 87 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
88 { 88 {
89 byte[] result = new byte[0]; 89 byte[] result = new byte[0];
@@ -176,7 +176,7 @@ namespace OpenSim.Server.Handlers.Neighbour
176 // TODO: unused: m_AuthenticationService = authentication; 176 // TODO: unused: m_AuthenticationService = authentication;
177 } 177 }
178 178
179 public override byte[] Handle(string path, Stream request, 179 protected override byte[] ProcessRequest(string path, Stream request,
180 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 180 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
181 { 181 {
182 // Not implemented yet 182 // Not implemented yet
@@ -197,7 +197,7 @@ namespace OpenSim.Server.Handlers.Neighbour
197 // TODO: unused: m_AuthenticationService = authentication; 197 // TODO: unused: m_AuthenticationService = authentication;
198 } 198 }
199 199
200 public override byte[] Handle(string path, Stream request, 200 protected override byte[] ProcessRequest(string path, Stream request,
201 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 201 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
202 { 202 {
203 // Not implemented yet 203 // Not implemented yet
diff --git a/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs b/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs
index 2d67c6d..abb4b19 100644
--- a/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs
@@ -56,7 +56,7 @@ namespace OpenSim.Server.Handlers.Presence
56 m_PresenceService = service; 56 m_PresenceService = service;
57 } 57 }
58 58
59 public override byte[] Handle(string path, Stream requestData, 59 protected override byte[] ProcessRequest(string path, Stream requestData,
60 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 60 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
61 { 61 {
62 StreamReader sr = new StreamReader(requestData); 62 StreamReader sr = new StreamReader(requestData);
diff --git a/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs b/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs
new file mode 100644
index 0000000..28dbbc2
--- /dev/null
+++ b/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.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.Reflection;
30using Nini.Config;
31using OpenSim.Server.Base;
32using OpenSim.Services.Interfaces;
33using OpenSim.Framework.Servers.HttpServer;
34using OpenSim.Framework;
35using OpenSim.Server.Handlers.Base;
36using log4net;
37
38namespace OpenSim.Server.Handlers.Profiles
39{
40 public class UserProfilesConnector: ServiceConnector
41 {
42// static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 // Our Local Module
45 public IUserProfilesService ServiceModule
46 {
47 get; private set;
48 }
49
50 // The HTTP server.
51 public IHttpServer Server
52 {
53 get; private set;
54 }
55
56 public string ConfigName
57 {
58 get; private set;
59 }
60
61 public bool Enabled
62 {
63 get; private set;
64 }
65
66 public UserProfilesConnector(IConfigSource config, IHttpServer server, string configName) :
67 base(config, server, configName)
68 {
69 ConfigName = "UserProfilesService";
70 if(!string.IsNullOrEmpty(configName))
71 ConfigName = configName;
72
73 IConfig serverConfig = config.Configs[ConfigName];
74 if (serverConfig == null)
75 throw new Exception(String.Format("No section {0} in config file", ConfigName));
76
77 if(!serverConfig.GetBoolean("Enabled",false))
78 {
79 Enabled = false;
80 return;
81 }
82
83 Enabled = true;
84
85 Server = server;
86
87 string service = serverConfig.GetString("LocalServiceModule", String.Empty);
88
89 Object[] args = new Object[] { config, ConfigName };
90 ServiceModule = ServerUtils.LoadPlugin<IUserProfilesService>(service, args);
91
92 JsonRpcProfileHandlers handler = new JsonRpcProfileHandlers(ServiceModule);
93
94 Server.AddJsonRPCHandler("avatarclassifiedsrequest", handler.AvatarClassifiedsRequest);
95 Server.AddJsonRPCHandler("classified_update", handler.ClassifiedUpdate);
96 Server.AddJsonRPCHandler("classifieds_info_query", handler.ClassifiedInfoRequest);
97 Server.AddJsonRPCHandler("classified_delete", handler.ClassifiedDelete);
98 Server.AddJsonRPCHandler("avatarpicksrequest", handler.AvatarPicksRequest);
99 Server.AddJsonRPCHandler("pickinforequest", handler.PickInfoRequest);
100 Server.AddJsonRPCHandler("picks_update", handler.PicksUpdate);
101 Server.AddJsonRPCHandler("picks_delete", handler.PicksDelete);
102 Server.AddJsonRPCHandler("avatarnotesrequest", handler.AvatarNotesRequest);
103 Server.AddJsonRPCHandler("avatar_notes_update", handler.NotesUpdate);
104 Server.AddJsonRPCHandler("avatar_properties_request", handler.AvatarPropertiesRequest);
105 Server.AddJsonRPCHandler("avatar_properties_update", handler.AvatarPropertiesUpdate);
106 Server.AddJsonRPCHandler("avatar_interests_update", handler.AvatarInterestsUpdate);
107 Server.AddJsonRPCHandler("image_assets_request", handler.AvatarImageAssetsRequest);
108 Server.AddJsonRPCHandler("user_data_request", handler.RequestUserAppData);
109 Server.AddJsonRPCHandler("user_data_update", handler.UpdateUserAppData);
110 }
111 }
112} \ No newline at end of file
diff --git a/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs b/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs
new file mode 100644
index 0000000..f5f0794
--- /dev/null
+++ b/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs
@@ -0,0 +1,461 @@
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.Reflection;
30using OpenMetaverse;
31using OpenMetaverse.StructuredData;
32using log4net;
33using OpenSim.Services.Interfaces;
34using OpenSim.Framework.Servers.HttpServer;
35using OpenSim.Framework;
36
37namespace OpenSim.Server.Handlers
38{
39 public class UserProfilesHandlers
40 {
41 public UserProfilesHandlers ()
42 {
43 }
44 }
45
46 public class JsonRpcProfileHandlers
47 {
48 static readonly ILog m_log =
49 LogManager.GetLogger(
50 MethodBase.GetCurrentMethod().DeclaringType);
51
52 public IUserProfilesService Service
53 {
54 get; private set;
55 }
56
57 public JsonRpcProfileHandlers(IUserProfilesService service)
58 {
59 Service = service;
60 }
61
62 #region Classifieds
63 /// <summary>
64 /// Request avatar's classified ads.
65 /// </summary>
66 /// <returns>
67 /// An array containing all the calassified uuid and it's name created by the creator id
68 /// </returns>
69 /// <param name='json'>
70 /// Our parameters are in the OSDMap json["params"]
71 /// </param>
72 /// <param name='response'>
73 /// If set to <c>true</c> response.
74 /// </param>
75 public bool AvatarClassifiedsRequest(OSDMap json, ref JsonRpcResponse response)
76 {
77 if(!json.ContainsKey("params"))
78 {
79 response.Error.Code = ErrorCode.ParseError;
80 m_log.DebugFormat ("Classified Request");
81 return false;
82 }
83
84 OSDMap request = (OSDMap)json["params"];
85 UUID creatorId = new UUID(request["creatorId"].AsString());
86
87
88 OSDArray data = (OSDArray) Service.AvatarClassifiedsRequest(creatorId);
89 response.Result = data;
90
91 return true;
92 }
93
94 public bool ClassifiedUpdate(OSDMap json, ref JsonRpcResponse response)
95 {
96 if(!json.ContainsKey("params"))
97 {
98 response.Error.Code = ErrorCode.ParseError;
99 response.Error.Message = "Error parsing classified update request";
100 m_log.DebugFormat ("Classified Update Request");
101 return false;
102 }
103
104 string result = string.Empty;
105 UserClassifiedAdd ad = new UserClassifiedAdd();
106 object Ad = (object)ad;
107 OSD.DeserializeMembers(ref Ad, (OSDMap)json["params"]);
108 if(Service.ClassifiedUpdate(ad, ref result))
109 {
110 response.Result = OSD.SerializeMembers(ad);
111 return true;
112 }
113
114 response.Error.Code = ErrorCode.InternalError;
115 response.Error.Message = string.Format("{0}", result);
116 return false;
117 }
118
119 public bool ClassifiedDelete(OSDMap json, ref JsonRpcResponse response)
120 {
121 if(!json.ContainsKey("params"))
122 {
123 response.Error.Code = ErrorCode.ParseError;
124 m_log.DebugFormat ("Classified Delete Request");
125 return false;
126 }
127
128 OSDMap request = (OSDMap)json["params"];
129 UUID classifiedId = new UUID(request["classifiedID"].AsString());
130
131 OSDMap res = new OSDMap();
132 res["result"] = OSD.FromString("success");
133 response.Result = res;
134
135 return true;
136
137 }
138
139 public bool ClassifiedInfoRequest(OSDMap json, ref JsonRpcResponse response)
140 {
141 if(!json.ContainsKey("params"))
142 {
143 response.Error.Code = ErrorCode.ParseError;
144 response.Error.Message = "no parameters supplied";
145 m_log.DebugFormat ("Classified Info Request");
146 return false;
147 }
148
149 string result = string.Empty;
150 UserClassifiedAdd ad = new UserClassifiedAdd();
151 object Ad = (object)ad;
152 OSD.DeserializeMembers(ref Ad, (OSDMap)json["params"]);
153 if(Service.ClassifiedInfoRequest(ref ad, ref result))
154 {
155 response.Result = OSD.SerializeMembers(ad);
156 return true;
157 }
158
159 response.Error.Code = ErrorCode.InternalError;
160 response.Error.Message = string.Format("{0}", result);
161 return false;
162 }
163 #endregion Classifieds
164
165 #region Picks
166 public bool AvatarPicksRequest(OSDMap json, ref JsonRpcResponse response)
167 {
168 if(!json.ContainsKey("params"))
169 {
170 response.Error.Code = ErrorCode.ParseError;
171 m_log.DebugFormat ("Avatar Picks Request");
172 return false;
173 }
174
175 OSDMap request = (OSDMap)json["params"];
176 UUID creatorId = new UUID(request["creatorId"].AsString());
177
178
179 OSDArray data = (OSDArray) Service.AvatarPicksRequest(creatorId);
180 response.Result = data;
181
182 return true;
183 }
184
185 public bool PickInfoRequest(OSDMap json, ref JsonRpcResponse response)
186 {
187 if(!json.ContainsKey("params"))
188 {
189 response.Error.Code = ErrorCode.ParseError;
190 response.Error.Message = "no parameters supplied";
191 m_log.DebugFormat ("Avatar Picks Info Request");
192 return false;
193 }
194
195 string result = string.Empty;
196 UserProfilePick pick = new UserProfilePick();
197 object Pick = (object)pick;
198 OSD.DeserializeMembers(ref Pick, (OSDMap)json["params"]);
199 if(Service.PickInfoRequest(ref pick, ref result))
200 {
201 response.Result = OSD.SerializeMembers(pick);
202 return true;
203 }
204
205 response.Error.Code = ErrorCode.InternalError;
206 response.Error.Message = string.Format("{0}", result);
207 return false;
208 }
209
210 public bool PicksUpdate(OSDMap json, ref JsonRpcResponse response)
211 {
212 if(!json.ContainsKey("params"))
213 {
214 response.Error.Code = ErrorCode.ParseError;
215 response.Error.Message = "no parameters supplied";
216 m_log.DebugFormat ("Avatar Picks Update Request");
217 return false;
218 }
219
220 string result = string.Empty;
221 UserProfilePick pick = new UserProfilePick();
222 object Pick = (object)pick;
223 OSD.DeserializeMembers(ref Pick, (OSDMap)json["params"]);
224 if(Service.PicksUpdate(ref pick, ref result))
225 {
226 response.Result = OSD.SerializeMembers(pick);
227 return true;
228 }
229
230 response.Error.Code = ErrorCode.InternalError;
231 response.Error.Message = "unable to update pick";
232
233 return false;
234 }
235
236 public bool PicksDelete(OSDMap json, ref JsonRpcResponse response)
237 {
238 if(!json.ContainsKey("params"))
239 {
240 response.Error.Code = ErrorCode.ParseError;
241 m_log.DebugFormat ("Avatar Picks Delete Request");
242 return false;
243 }
244
245 OSDMap request = (OSDMap)json["params"];
246 UUID pickId = new UUID(request["pickId"].AsString());
247 if(Service.PicksDelete(pickId))
248 return true;
249
250 response.Error.Code = ErrorCode.InternalError;
251 response.Error.Message = "data error removing record";
252 return false;
253 }
254 #endregion Picks
255
256 #region Notes
257 public bool AvatarNotesRequest(OSDMap json, ref JsonRpcResponse response)
258 {
259 if(!json.ContainsKey("params"))
260 {
261 response.Error.Code = ErrorCode.ParseError;
262 response.Error.Message = "Params missing";
263 m_log.DebugFormat ("Avatar Notes Request");
264 return false;
265 }
266
267 string result = string.Empty;
268 UserProfileNotes note = new UserProfileNotes();
269 object Note = (object)note;
270 OSD.DeserializeMembers(ref Note, (OSDMap)json["params"]);
271 if(Service.AvatarNotesRequest(ref note))
272 {
273 response.Result = OSD.SerializeMembers(note);
274 return true;
275 }
276
277 object Notes = (object) note;
278 OSD.DeserializeMembers(ref Notes, (OSDMap)json["params"]);
279 return true;
280 }
281
282 public bool NotesUpdate(OSDMap json, ref JsonRpcResponse response)
283 {
284 if(!json.ContainsKey("params"))
285 {
286 response.Error.Code = ErrorCode.ParseError;
287 response.Error.Message = "No parameters";
288 m_log.DebugFormat ("Avatar Notes Update Request");
289 return false;
290 }
291
292 string result = string.Empty;
293 UserProfileNotes note = new UserProfileNotes();
294 object Notes = (object) note;
295 OSD.DeserializeMembers(ref Notes, (OSDMap)json["params"]);
296 if(Service.NotesUpdate(ref note, ref result))
297 {
298 response.Result = OSD.SerializeMembers(note);
299 return true;
300 }
301 return true;
302 }
303 #endregion Notes
304
305 #region Profile Properties
306 public bool AvatarPropertiesRequest(OSDMap json, ref JsonRpcResponse response)
307 {
308 if(!json.ContainsKey("params"))
309 {
310 response.Error.Code = ErrorCode.ParseError;
311 response.Error.Message = "no parameters supplied";
312 m_log.DebugFormat ("Avatar Properties Request");
313 return false;
314 }
315
316 string result = string.Empty;
317 UserProfileProperties props = new UserProfileProperties();
318 object Props = (object)props;
319 OSD.DeserializeMembers(ref Props, (OSDMap)json["params"]);
320 if(Service.AvatarPropertiesRequest(ref props, ref result))
321 {
322 response.Result = OSD.SerializeMembers(props);
323 return true;
324 }
325
326 response.Error.Code = ErrorCode.InternalError;
327 response.Error.Message = string.Format("{0}", result);
328 return false;
329 }
330
331 public bool AvatarPropertiesUpdate(OSDMap json, ref JsonRpcResponse response)
332 {
333 if(!json.ContainsKey("params"))
334 {
335 response.Error.Code = ErrorCode.ParseError;
336 response.Error.Message = "no parameters supplied";
337 m_log.DebugFormat ("Avatar Properties Update Request");
338 return false;
339 }
340
341 string result = string.Empty;
342 UserProfileProperties props = new UserProfileProperties();
343 object Props = (object)props;
344 OSD.DeserializeMembers(ref Props, (OSDMap)json["params"]);
345 if(Service.AvatarPropertiesUpdate(ref props, ref result))
346 {
347 response.Result = OSD.SerializeMembers(props);
348 return true;
349 }
350
351 response.Error.Code = ErrorCode.InternalError;
352 response.Error.Message = string.Format("{0}", result);
353 return false;
354 }
355 #endregion Profile Properties
356
357 #region Interests
358 public bool AvatarInterestsUpdate(OSDMap json, ref JsonRpcResponse response)
359 {
360 if(!json.ContainsKey("params"))
361 {
362 response.Error.Code = ErrorCode.ParseError;
363 response.Error.Message = "no parameters supplied";
364 m_log.DebugFormat ("Avatar Interests Update Request");
365 return false;
366 }
367
368 string result = string.Empty;
369 UserProfileProperties props = new UserProfileProperties();
370 object Props = (object)props;
371 OSD.DeserializeMembers(ref Props, (OSDMap)json["params"]);
372 if(Service.AvatarInterestsUpdate(props, ref result))
373 {
374 response.Result = OSD.SerializeMembers(props);
375 return true;
376 }
377
378 response.Error.Code = ErrorCode.InternalError;
379 response.Error.Message = string.Format("{0}", result);
380 return false;
381 }
382 #endregion Interests
383
384 #region Utility
385 public bool AvatarImageAssetsRequest(OSDMap json, ref JsonRpcResponse response)
386 {
387 if(!json.ContainsKey("params"))
388 {
389 response.Error.Code = ErrorCode.ParseError;
390 m_log.DebugFormat ("Avatar Image Assets Request");
391 return false;
392 }
393
394 OSDMap request = (OSDMap)json["params"];
395 UUID avatarId = new UUID(request["avatarId"].AsString());
396
397 OSDArray data = (OSDArray) Service.AvatarImageAssetsRequest(avatarId);
398 response.Result = data;
399
400 return true;
401 }
402 #endregion Utiltiy
403
404 #region UserData
405 public bool RequestUserAppData(OSDMap json, ref JsonRpcResponse response)
406 {
407 if(!json.ContainsKey("params"))
408 {
409 response.Error.Code = ErrorCode.ParseError;
410 response.Error.Message = "no parameters supplied";
411 m_log.DebugFormat ("User Application Service URL Request: No Parameters!");
412 return false;
413 }
414
415 string result = string.Empty;
416 UserAppData props = new UserAppData();
417 object Props = (object)props;
418 OSD.DeserializeMembers(ref Props, (OSDMap)json["params"]);
419 if(Service.RequestUserAppData(ref props, ref result))
420 {
421 OSDMap res = new OSDMap();
422 res["result"] = OSD.FromString("success");
423 res["token"] = OSD.FromString (result);
424 response.Result = res;
425
426 return true;
427 }
428
429 response.Error.Code = ErrorCode.InternalError;
430 response.Error.Message = string.Format("{0}", result);
431 return false;
432 }
433
434 public bool UpdateUserAppData(OSDMap json, ref JsonRpcResponse response)
435 {
436 if(!json.ContainsKey("params"))
437 {
438 response.Error.Code = ErrorCode.ParseError;
439 response.Error.Message = "no parameters supplied";
440 m_log.DebugFormat ("User App Data Update Request");
441 return false;
442 }
443
444 string result = string.Empty;
445 UserAppData props = new UserAppData();
446 object Props = (object)props;
447 OSD.DeserializeMembers(ref Props, (OSDMap)json["params"]);
448 if(Service.SetUserAppData(props, ref result))
449 {
450 response.Result = OSD.SerializeMembers(props);
451 return true;
452 }
453
454 response.Error.Code = ErrorCode.InternalError;
455 response.Error.Message = string.Format("{0}", result);
456 return false;
457 }
458 #endregion UserData
459 }
460}
461
diff --git a/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs b/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs
index 3295ffd..04cd798 100644
--- a/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs
+++ b/OpenSim/Server/Handlers/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
index 0bd8269..964ccf8 100644
--- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
+++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs
@@ -27,11 +27,13 @@
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Specialized;
30using System.IO; 31using System.IO;
31using System.IO.Compression; 32using System.IO.Compression;
32using System.Reflection; 33using System.Reflection;
33using System.Net; 34using System.Net;
34using System.Text; 35using System.Text;
36using System.Web;
35 37
36using OpenSim.Server.Base; 38using OpenSim.Server.Base;
37using OpenSim.Server.Handlers.Base; 39using OpenSim.Server.Handlers.Base;
@@ -90,19 +92,13 @@ namespace OpenSim.Server.Handlers.Simulation
90 92
91 // Next, let's parse the verb 93 // Next, let's parse the verb
92 string method = (string)request["http-method"]; 94 string method = (string)request["http-method"];
93 if (method.Equals("GET")) 95 if (method.Equals("DELETE"))
94 { 96 {
95 DoAgentGet(request, responsedata, agentID, regionID); 97 string auth_token = string.Empty;
96 return responsedata; 98 if (request.ContainsKey("auth"))
97 } 99 auth_token = request["auth"].ToString();
98 else if (method.Equals("DELETE")) 100
99 { 101 DoAgentDelete(request, responsedata, agentID, action, regionID, auth_token);
100 DoAgentDelete(request, responsedata, agentID, action, regionID);
101 return responsedata;
102 }
103 else if (method.Equals("DELETECHILD"))
104 {
105 DoChildAgentDelete(request, responsedata, agentID, action, regionID);
106 return responsedata; 102 return responsedata;
107 } 103 }
108 else if (method.Equals("QUERYACCESS")) 104 else if (method.Equals("QUERYACCESS"))
@@ -112,7 +108,7 @@ namespace OpenSim.Server.Handlers.Simulation
112 } 108 }
113 else 109 else
114 { 110 {
115 m_log.InfoFormat("[AGENT HANDLER]: method {0} not supported in agent message", method); 111 m_log.ErrorFormat("[AGENT HANDLER]: method {0} not supported in agent message {1} (caller is {2})", method, (string)request["uri"], Util.GetCallerIP(request));
116 responsedata["int_response_code"] = HttpStatusCode.MethodNotAllowed; 112 responsedata["int_response_code"] = HttpStatusCode.MethodNotAllowed;
117 responsedata["str_response_string"] = "Method not allowed"; 113 responsedata["str_response_string"] = "Method not allowed";
118 114
@@ -161,79 +157,12 @@ namespace OpenSim.Server.Handlers.Simulation
161// Console.WriteLine("str_response_string [{0}]", responsedata["str_response_string"]); 157// Console.WriteLine("str_response_string [{0}]", responsedata["str_response_string"]);
162 } 158 }
163 159
164 protected virtual void DoAgentGet(Hashtable request, Hashtable responsedata, UUID id, UUID regionID) 160 protected void DoAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, UUID regionID, string auth_token)
165 { 161 {
166 if (m_SimulationService == null) 162 if (string.IsNullOrEmpty(action))
167 { 163 m_log.DebugFormat("[AGENT HANDLER]: >>> DELETE <<< RegionID: {0}; from: {1}; auth_code: {2}", regionID, Util.GetCallerIP(request), auth_token);
168 m_log.Debug("[AGENT HANDLER]: Agent GET called. Harmless but useless.");
169 responsedata["content_type"] = "application/json";
170 responsedata["int_response_code"] = HttpStatusCode.NotImplemented;
171 responsedata["str_response_string"] = string.Empty;
172
173 return;
174 }
175
176 GridRegion destination = new GridRegion();
177 destination.RegionID = regionID;
178
179 IAgentData agent = null;
180 bool result = m_SimulationService.RetrieveAgent(destination, id, out agent);
181 OSDMap map = null;
182 if (result)
183 {
184 if (agent != null) // just to make sure
185 {
186 map = agent.Pack();
187 string strBuffer = "";
188 try
189 {
190 strBuffer = OSDParser.SerializeJsonString(map);
191 }
192 catch (Exception e)
193 {
194 m_log.WarnFormat("[AGENT HANDLER]: Exception thrown on serialization of DoAgentGet: {0}", e.Message);
195 responsedata["int_response_code"] = HttpStatusCode.InternalServerError;
196 // ignore. buffer will be empty, caller should check.
197 }
198
199 responsedata["content_type"] = "application/json";
200 responsedata["int_response_code"] = HttpStatusCode.OK;
201 responsedata["str_response_string"] = strBuffer;
202 }
203 else
204 {
205 responsedata["int_response_code"] = HttpStatusCode.InternalServerError;
206 responsedata["str_response_string"] = "Internal error";
207 }
208 }
209 else
210 {
211 responsedata["int_response_code"] = HttpStatusCode.NotFound;
212 responsedata["str_response_string"] = "Not Found";
213 }
214 }
215
216 protected void DoChildAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, UUID regionID)
217 {
218 m_log.Debug(" >>> DoChildAgentDelete action:" + action + "; RegionID:" + regionID);
219
220 GridRegion destination = new GridRegion();
221 destination.RegionID = regionID;
222
223 if (action.Equals("release"))
224 ReleaseAgent(regionID, id);
225 else 164 else
226 m_SimulationService.CloseChildAgent(destination, id); 165 m_log.DebugFormat("[AGENT HANDLER]: Release {0} to RegionID: {1}", id, regionID);
227
228 responsedata["int_response_code"] = HttpStatusCode.OK;
229 responsedata["str_response_string"] = "OpenSim agent " + id.ToString();
230
231 m_log.Debug("[AGENT HANDLER]: Child Agent Released/Deleted.");
232 }
233
234 protected void DoAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, UUID regionID)
235 {
236 m_log.Debug(" >>> DoDelete action:" + action + "; RegionID:" + regionID);
237 166
238 GridRegion destination = new GridRegion(); 167 GridRegion destination = new GridRegion();
239 destination.RegionID = regionID; 168 destination.RegionID = regionID;
@@ -241,12 +170,12 @@ namespace OpenSim.Server.Handlers.Simulation
241 if (action.Equals("release")) 170 if (action.Equals("release"))
242 ReleaseAgent(regionID, id); 171 ReleaseAgent(regionID, id);
243 else 172 else
244 m_SimulationService.CloseAgent(destination, id); 173 Util.FireAndForget(delegate { m_SimulationService.CloseAgent(destination, id, auth_token); });
245 174
246 responsedata["int_response_code"] = HttpStatusCode.OK; 175 responsedata["int_response_code"] = HttpStatusCode.OK;
247 responsedata["str_response_string"] = "OpenSim agent " + id.ToString(); 176 responsedata["str_response_string"] = "OpenSim agent " + id.ToString();
248 177
249 m_log.DebugFormat("[AGENT HANDLER]: Agent {0} Released/Deleted from region {1}", id, regionID); 178 //m_log.DebugFormat("[AGENT HANDLER]: Agent {0} Released/Deleted from region {1}", id, regionID);
250 } 179 }
251 180
252 protected virtual void ReleaseAgent(UUID regionID, UUID id) 181 protected virtual void ReleaseAgent(UUID regionID, UUID id)
@@ -274,7 +203,7 @@ namespace OpenSim.Server.Handlers.Simulation
274 m_SimulationService = null; 203 m_SimulationService = null;
275 } 204 }
276 205
277 public override byte[] Handle(string path, Stream request, 206 protected override byte[] ProcessRequest(string path, Stream request,
278 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 207 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
279 { 208 {
280// m_log.DebugFormat("[SIMULATION]: Stream handler called"); 209// m_log.DebugFormat("[SIMULATION]: Stream handler called");
@@ -351,31 +280,16 @@ namespace OpenSim.Server.Handlers.Simulation
351 return; 280 return;
352 } 281 }
353 282
354 // retrieve the input arguments 283 AgentDestinationData data = CreateAgentDestinationData();
355 int x = 0, y = 0; 284 UnpackData(args, data, request);
356 UUID uuid = UUID.Zero;
357 string regionname = string.Empty;
358 uint teleportFlags = 0;
359 if (args.ContainsKey("destination_x") && args["destination_x"] != null)
360 Int32.TryParse(args["destination_x"].AsString(), out x);
361 else
362 m_log.WarnFormat(" -- request didn't have destination_x");
363 if (args.ContainsKey("destination_y") && args["destination_y"] != null)
364 Int32.TryParse(args["destination_y"].AsString(), out y);
365 else
366 m_log.WarnFormat(" -- request didn't have destination_y");
367 if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
368 UUID.TryParse(args["destination_uuid"].AsString(), out uuid);
369 if (args.ContainsKey("destination_name") && args["destination_name"] != null)
370 regionname = args["destination_name"].ToString();
371 if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null)
372 teleportFlags = args["teleport_flags"].AsUInteger();
373 285
374 GridRegion destination = new GridRegion(); 286 GridRegion destination = new GridRegion();
375 destination.RegionID = uuid; 287 destination.RegionID = data.uuid;
376 destination.RegionLocX = x; 288 destination.RegionLocX = data.x;
377 destination.RegionLocY = y; 289 destination.RegionLocY = data.y;
378 destination.RegionName = regionname; 290 destination.RegionName = data.name;
291
292 GridRegion gatekeeper = ExtractGatekeeper(data);
379 293
380 AgentCircuitData aCircuit = new AgentCircuitData(); 294 AgentCircuitData aCircuit = new AgentCircuitData();
381 try 295 try
@@ -396,7 +310,7 @@ namespace OpenSim.Server.Handlers.Simulation
396 // This is the meaning of POST agent 310 // This is the meaning of POST agent
397 //m_regionClient.AdjustUserInformation(aCircuit); 311 //m_regionClient.AdjustUserInformation(aCircuit);
398 //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); 312 //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason);
399 bool result = CreateAgent(destination, aCircuit, teleportFlags, out reason); 313 bool result = CreateAgent(gatekeeper, destination, aCircuit, data.flags, data.fromLogin, out reason);
400 314
401 resp["reason"] = OSD.FromString(reason); 315 resp["reason"] = OSD.FromString(reason);
402 resp["success"] = OSD.FromBoolean(result); 316 resp["success"] = OSD.FromBoolean(result);
@@ -408,7 +322,36 @@ namespace OpenSim.Server.Handlers.Simulation
408 responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); 322 responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp);
409 } 323 }
410 324
411 private string GetCallerIP(Hashtable request) 325 protected virtual AgentDestinationData CreateAgentDestinationData()
326 {
327 return new AgentDestinationData();
328 }
329
330 protected virtual void UnpackData(OSDMap args, AgentDestinationData data, Hashtable request)
331 {
332 // retrieve the input arguments
333 if (args.ContainsKey("destination_x") && args["destination_x"] != null)
334 Int32.TryParse(args["destination_x"].AsString(), out data.x);
335 else
336 m_log.WarnFormat(" -- request didn't have destination_x");
337 if (args.ContainsKey("destination_y") && args["destination_y"] != null)
338 Int32.TryParse(args["destination_y"].AsString(), out data.y);
339 else
340 m_log.WarnFormat(" -- request didn't have destination_y");
341 if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null)
342 UUID.TryParse(args["destination_uuid"].AsString(), out data.uuid);
343 if (args.ContainsKey("destination_name") && args["destination_name"] != null)
344 data.name = args["destination_name"].ToString();
345 if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null)
346 data.flags = args["teleport_flags"].AsUInteger();
347 }
348
349 protected virtual GridRegion ExtractGatekeeper(AgentDestinationData data)
350 {
351 return null;
352 }
353
354 protected string GetCallerIP(Hashtable request)
412 { 355 {
413 if (!m_Proxy) 356 if (!m_Proxy)
414 return Util.GetCallerIP(request); 357 return Util.GetCallerIP(request);
@@ -441,7 +384,7 @@ namespace OpenSim.Server.Handlers.Simulation
441 } 384 }
442 385
443 // subclasses can override this 386 // subclasses can override this
444 protected virtual bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) 387 protected virtual bool CreateAgent(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, bool fromLogin, out string reason)
445 { 388 {
446 reason = String.Empty; 389 reason = String.Empty;
447 390
@@ -474,7 +417,7 @@ namespace OpenSim.Server.Handlers.Simulation
474 m_SimulationService = null; 417 m_SimulationService = null;
475 } 418 }
476 419
477 public override byte[] Handle(string path, Stream request, 420 protected override byte[] ProcessRequest(string path, Stream request,
478 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 421 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
479 { 422 {
480// m_log.DebugFormat("[SIMULATION]: Stream handler called"); 423// m_log.DebugFormat("[SIMULATION]: Stream handler called");
@@ -593,7 +536,6 @@ namespace OpenSim.Server.Handlers.Simulation
593 //agent.Dump(); 536 //agent.Dump();
594 // This is one of the meanings of PUT agent 537 // This is one of the meanings of PUT agent
595 result = UpdateAgent(destination, agent); 538 result = UpdateAgent(destination, agent);
596
597 } 539 }
598 else if ("AgentPosition".Equals(messageType)) 540 else if ("AgentPosition".Equals(messageType))
599 { 541 {
@@ -624,4 +566,14 @@ namespace OpenSim.Server.Handlers.Simulation
624 return m_SimulationService.UpdateAgent(destination, agent); 566 return m_SimulationService.UpdateAgent(destination, agent);
625 } 567 }
626 } 568 }
569
570 public class AgentDestinationData
571 {
572 public int x;
573 public int y;
574 public string name;
575 public UUID uuid;
576 public uint flags;
577 public bool fromLogin;
578 }
627} 579}
diff --git a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs
index 72551ef..24c9de6 100644
--- a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs
@@ -68,7 +68,7 @@ namespace OpenSim.Server.Handlers.UserAccounts
68 } 68 }
69 } 69 }
70 70
71 public override byte[] Handle(string path, Stream requestData, 71 protected override byte[] ProcessRequest(string path, Stream requestData,
72 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 72 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
73 { 73 {
74 StreamReader sr = new StreamReader(requestData); 74 StreamReader sr = new StreamReader(requestData);
diff --git a/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs b/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs
index 50ee033..72c2ac4 100644
--- a/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AssetService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/AssetService/XAssetService.cs b/OpenSim/Services/AssetService/XAssetService.cs
index 8a2ca7c..6047616 100644
--- a/OpenSim/Services/AssetService/XAssetService.cs
+++ b/OpenSim/Services/AssetService/XAssetService.cs
@@ -205,15 +205,16 @@ namespace OpenSim.Services.AssetService
205 if (!UUID.TryParse(id, out assetID)) 205 if (!UUID.TryParse(id, out assetID))
206 return false; 206 return false;
207 207
208 // Don't bother deleting from a chained asset service. This isn't a big deal since deleting happens 208 if (HasChainedAssetService)
209 // very rarely. 209 m_ChainedAssetService.Delete(id);
210 210
211 return m_Database.Delete(id); 211 return m_Database.Delete(id);
212 } 212 }
213 213
214 private void MigrateFromChainedService(AssetBase asset) 214 private void MigrateFromChainedService(AssetBase asset)
215 { 215 {
216 Util.FireAndForget(o => { Store(asset); m_ChainedAssetService.Delete(asset.ID); }); 216 Store(asset);
217 m_ChainedAssetService.Delete(asset.ID);
217 } 218 }
218 } 219 }
219} \ No newline at end of file 220} \ No newline at end of file
diff --git a/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs
index 435852da..8ffeeca 100644
--- a/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AuthenticationService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs b/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs
index 8db1671..e51d2ca 100644
--- a/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AuthorizationService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs b/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs
index 138d4cd..3800e62 100644
--- a/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/AvatarService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/Base/Properties/AssemblyInfo.cs b/OpenSim/Services/Base/Properties/AssemblyInfo.cs
index 84a40f0..959670c 100644
--- a/OpenSim/Services/Base/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Base/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
index 8b702e0..bf0cc35 100644
--- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
@@ -66,6 +66,12 @@ namespace OpenSim.Services.Connectors
66 66
67 private Thread[] m_fetchThreads; 67 private Thread[] m_fetchThreads;
68 68
69 public int MaxAssetRequestConcurrency
70 {
71 get { return m_maxAssetRequestConcurrency; }
72 set { m_maxAssetRequestConcurrency = value; }
73 }
74
69 public AssetServicesConnector() 75 public AssetServicesConnector()
70 { 76 {
71 } 77 }
diff --git a/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs b/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs
index f982cc1..af91cdb 100644
--- a/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs
@@ -525,6 +525,57 @@ namespace OpenSim.Services.Connectors
525 return rinfos; 525 return rinfos;
526 } 526 }
527 527
528 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
529 {
530 Dictionary<string, object> sendData = new Dictionary<string, object>();
531
532 sendData["SCOPEID"] = scopeID.ToString();
533
534 sendData["METHOD"] = "get_default_hypergrid_regions";
535
536 List<GridRegion> rinfos = new List<GridRegion>();
537 string reply = string.Empty;
538 string uri = m_ServerURI + "/grid";
539 try
540 {
541 reply = SynchronousRestFormsRequester.MakeRequest("POST",
542 uri,
543 ServerUtils.BuildQueryString(sendData));
544
545 //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply);
546 }
547 catch (Exception e)
548 {
549 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
550 return rinfos;
551 }
552
553 if (reply != string.Empty)
554 {
555 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
556
557 if (replyData != null)
558 {
559 Dictionary<string, object>.ValueCollection rinfosList = replyData.Values;
560 foreach (object r in rinfosList)
561 {
562 if (r is Dictionary<string, object>)
563 {
564 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
565 rinfos.Add(rinfo);
566 }
567 }
568 }
569 else
570 m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultHypergridRegions {0} received null response",
571 scopeID);
572 }
573 else
574 m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultHypergridRegions received null reply");
575
576 return rinfos;
577 }
578
528 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 579 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
529 { 580 {
530 Dictionary<string, object> sendData = new Dictionary<string, object>(); 581 Dictionary<string, object> sendData = new Dictionary<string, object>();
diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs
index 94bda82..1a62d2f 100644
--- a/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs
+++ b/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs
@@ -214,7 +214,7 @@ namespace OpenSim.Services.Connectors
214 214
215 } 215 }
216 else 216 else
217 m_log.DebugFormat("[GRID USER CONNECTOR]: Loggedin received empty reply"); 217 m_log.DebugFormat("[GRID USER CONNECTOR]: Get received empty reply");
218 } 218 }
219 catch (Exception e) 219 catch (Exception e)
220 { 220 {
diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
index d840527..803cd1b 100644
--- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
@@ -53,7 +53,8 @@ namespace OpenSim.Services.Connectors.Hypergrid
53 53
54 private IAssetService m_AssetService; 54 private IAssetService m_AssetService;
55 55
56 public GatekeeperServiceConnector() : base() 56 public GatekeeperServiceConnector()
57 : base()
57 { 58 {
58 } 59 }
59 60
@@ -123,11 +124,13 @@ namespace OpenSim.Services.Connectors.Hypergrid
123 realHandle = Convert.ToUInt64((string)hash["handle"]); 124 realHandle = Convert.ToUInt64((string)hash["handle"]);
124 //m_log.Debug(">> HERE, realHandle: " + realHandle); 125 //m_log.Debug(">> HERE, realHandle: " + realHandle);
125 } 126 }
126 if (hash["region_image"] != null) { 127 if (hash["region_image"] != null)
128 {
127 imageURL = (string)hash["region_image"]; 129 imageURL = (string)hash["region_image"];
128 //m_log.Debug(">> HERE, imageURL: " + imageURL); 130 //m_log.Debug(">> HERE, imageURL: " + imageURL);
129 } 131 }
130 if (hash["external_name"] != null) { 132 if (hash["external_name"] != null)
133 {
131 externalName = (string)hash["external_name"]; 134 externalName = (string)hash["external_name"];
132 //m_log.Debug(">> HERE, externalName: " + externalName); 135 //m_log.Debug(">> HERE, externalName: " + externalName);
133 } 136 }
@@ -179,7 +182,7 @@ namespace OpenSim.Services.Connectors.Hypergrid
179 //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width); 182 //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width);
180 imageData = OpenJPEG.EncodeFromImage(bitmap, true); 183 imageData = OpenJPEG.EncodeFromImage(bitmap, true);
181 } 184 }
182 185
183 AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString()); 186 AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString());
184 187
185 // !!! for now 188 // !!! for now
@@ -257,7 +260,8 @@ namespace OpenSim.Services.Connectors.Hypergrid
257 region.RegionName = (string)hash["region_name"]; 260 region.RegionName = (string)hash["region_name"];
258 //m_log.Debug(">> HERE, region_name: " + region.RegionName); 261 //m_log.Debug(">> HERE, region_name: " + region.RegionName);
259 } 262 }
260 if (hash["hostname"] != null) { 263 if (hash["hostname"] != null)
264 {
261 region.ExternalHostName = (string)hash["hostname"]; 265 region.ExternalHostName = (string)hash["hostname"];
262 //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName); 266 //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName);
263 } 267 }
@@ -275,10 +279,10 @@ namespace OpenSim.Services.Connectors.Hypergrid
275 region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p); 279 region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p);
276 //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint); 280 //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint);
277 } 281 }
278 282
279 if (hash["server_uri"] != null) 283 if (hash["server_uri"] != null)
280 { 284 {
281 region.ServerURI = (string) hash["server_uri"]; 285 region.ServerURI = (string)hash["server_uri"];
282 //m_log.Debug(">> HERE, server_uri: " + region.ServerURI); 286 //m_log.Debug(">> HERE, server_uri: " + region.ServerURI);
283 } 287 }
284 288
@@ -295,55 +299,5 @@ namespace OpenSim.Services.Connectors.Hypergrid
295 299
296 return null; 300 return null;
297 } 301 }
298
299 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason)
300 {
301 // m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: CreateAgent start");
302
303 myipaddress = String.Empty;
304 reason = String.Empty;
305
306 if (destination == null)
307 {
308 m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Given destination is null");
309 return false;
310 }
311
312 string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/";
313
314 try
315 {
316 OSDMap args = aCircuit.PackAgentCircuitData();
317
318 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
319 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
320 args["destination_name"] = OSD.FromString(destination.RegionName);
321 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
322 args["teleport_flags"] = OSD.FromString(flags.ToString());
323
324 OSDMap result = WebUtil.PostToService(uri, args, 80000);
325 if (result["Success"].AsBoolean())
326 {
327 OSDMap unpacked = (OSDMap)result["_Result"];
328
329 if (unpacked != null)
330 {
331 reason = unpacked["reason"].AsString();
332 myipaddress = unpacked["your_ip"].AsString();
333 return unpacked["success"].AsBoolean();
334 }
335 }
336
337 reason = result["Message"] != null ? result["Message"].AsString() : "error";
338 return false;
339 }
340 catch (Exception e)
341 {
342 m_log.Warn("[REMOTE SIMULATION CONNECTOR]: CreateAgent failed with exception: " + e.ToString());
343 reason = e.Message;
344 }
345
346 return false;
347 }
348 } 302 }
349} 303}
diff --git a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServicesConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServicesConnector.cs
index e984a54..622d4e1 100644
--- a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServicesConnector.cs
@@ -277,7 +277,7 @@ namespace OpenSim.Services.Connectors.Hypergrid
277 { 277 {
278 reply = SynchronousRestFormsRequester.MakeRequest("POST", 278 reply = SynchronousRestFormsRequester.MakeRequest("POST",
279 uri, 279 uri,
280 ServerUtils.BuildQueryString(sendData)); 280 ServerUtils.BuildQueryString(sendData), 15);
281 } 281 }
282 catch (Exception e) 282 catch (Exception e)
283 { 283 {
diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
index d7e38f1..32ea4ee 100644
--- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
@@ -44,13 +44,14 @@ using Nini.Config;
44 44
45namespace OpenSim.Services.Connectors.Hypergrid 45namespace OpenSim.Services.Connectors.Hypergrid
46{ 46{
47 public class UserAgentServiceConnector : IUserAgentService 47 public class UserAgentServiceConnector : SimulationServiceConnector, IUserAgentService
48 { 48 {
49 private static readonly ILog m_log = 49 private static readonly ILog m_log =
50 LogManager.GetLogger( 50 LogManager.GetLogger(
51 MethodBase.GetCurrentMethod().DeclaringType); 51 MethodBase.GetCurrentMethod().DeclaringType);
52 52
53 string m_ServerURL; 53 private string m_ServerURL;
54 private GridRegion m_Gatekeeper;
54 55
55 public UserAgentServiceConnector(string url) : this(url, true) 56 public UserAgentServiceConnector(string url) : this(url, true)
56 { 57 {
@@ -102,9 +103,15 @@ namespace OpenSim.Services.Connectors.Hypergrid
102 m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL); 103 m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL);
103 } 104 }
104 105
106 protected override string AgentPath()
107 {
108 return "homeagent/";
109 }
105 110
106 // The Login service calls this interface with a non-null [client] ipaddress 111 // The Login service calls this interface with fromLogin=true
107 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress, out string reason) 112 // Sims call it with fromLogin=false
113 // Either way, this is verified by the handler
114 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, bool fromLogin, out string reason)
108 { 115 {
109 reason = String.Empty; 116 reason = String.Empty;
110 117
@@ -115,119 +122,34 @@ namespace OpenSim.Services.Connectors.Hypergrid
115 return false; 122 return false;
116 } 123 }
117 124
118 string uri = m_ServerURL + "homeagent/" + aCircuit.AgentID + "/"; 125 GridRegion home = new GridRegion();
119 126 home.ServerURI = m_ServerURL;
120 Console.WriteLine(" >>> LoginAgentToGrid <<< " + uri); 127 home.RegionID = destination.RegionID;
121 128 home.RegionLocX = destination.RegionLocX;
122 HttpWebRequest AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri); 129 home.RegionLocY = destination.RegionLocY;
123 AgentCreateRequest.Method = "POST";
124 AgentCreateRequest.ContentType = "application/json";
125 AgentCreateRequest.Timeout = 10000;
126 //AgentCreateRequest.KeepAlive = false;
127 //AgentCreateRequest.Headers.Add("Authorization", authKey);
128
129 // Fill it in
130 OSDMap args = PackCreateAgentArguments(aCircuit, gatekeeper, destination, ipaddress);
131
132 string strBuffer = "";
133 byte[] buffer = new byte[1];
134 try
135 {
136 strBuffer = OSDParser.SerializeJsonString(args);
137 Encoding str = Util.UTF8;
138 buffer = str.GetBytes(strBuffer);
139
140 }
141 catch (Exception e)
142 {
143 m_log.WarnFormat("[USER AGENT CONNECTOR]: Exception thrown on serialization of ChildCreate: {0}", e.Message);
144 // ignore. buffer will be empty, caller should check.
145 }
146
147 Stream os = null;
148 try
149 { // send the Post
150 AgentCreateRequest.ContentLength = buffer.Length; //Count bytes to send
151 os = AgentCreateRequest.GetRequestStream();
152 os.Write(buffer, 0, strBuffer.Length); //Send it
153 m_log.InfoFormat("[USER AGENT CONNECTOR]: Posted CreateAgent request to remote sim {0}, region {1}, x={2} y={3}",
154 uri, destination.RegionName, destination.RegionLocX, destination.RegionLocY);
155 }
156 //catch (WebException ex)
157 catch
158 {
159 //m_log.InfoFormat("[USER AGENT CONNECTOR]: Bad send on ChildAgentUpdate {0}", ex.Message);
160 reason = "cannot contact remote region";
161 return false;
162 }
163 finally
164 {
165 if (os != null)
166 os.Close();
167 }
168
169 // Let's wait for the response
170 //m_log.Info("[USER AGENT CONNECTOR]: Waiting for a reply after DoCreateChildAgentCall");
171 130
172 try 131 m_Gatekeeper = gatekeeper;
173 {
174 using (WebResponse webResponse = AgentCreateRequest.GetResponse())
175 {
176 if (webResponse == null)
177 {
178 m_log.Info("[USER AGENT CONNECTOR]: Null reply on DoCreateChildAgentCall post");
179 }
180 else
181 {
182 using (Stream s = webResponse.GetResponseStream())
183 {
184 using (StreamReader sr = new StreamReader(s))
185 {
186 string response = sr.ReadToEnd().Trim();
187 m_log.InfoFormat("[USER AGENT CONNECTOR]: DoCreateChildAgentCall reply was {0} ", response);
188
189 if (!String.IsNullOrEmpty(response))
190 {
191 try
192 {
193 // we assume we got an OSDMap back
194 OSDMap r = Util.GetOSDMap(response);
195 bool success = r["success"].AsBoolean();
196 reason = r["reason"].AsString();
197 return success;
198 }
199 catch (NullReferenceException e)
200 {
201 m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", e.Message);
202
203 // check for old style response
204 if (response.ToLower().StartsWith("true"))
205 return true;
206
207 return false;
208 }
209 }
210 }
211 }
212 }
213 }
214 }
215 catch (WebException ex)
216 {
217 m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", ex.Message);
218 reason = "Destination did not reply";
219 return false;
220 }
221 132
222 return true; 133 Console.WriteLine(" >>> LoginAgentToGrid <<< " + home.ServerURI);
223 134
135 uint flags = fromLogin ? (uint)TeleportFlags.ViaLogin : (uint)TeleportFlags.ViaHome;
136 return CreateAgent(home, aCircuit, flags, out reason);
224 } 137 }
225 138
226 139
227 // The simulators call this interface 140 // The simulators call this interface
228 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason) 141 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason)
229 { 142 {
230 return LoginAgentToGrid(aCircuit, gatekeeper, destination, null, out reason); 143 return LoginAgentToGrid(aCircuit, gatekeeper, destination, false, out reason);
144 }
145
146 protected override void PackData(OSDMap args, AgentCircuitData aCircuit, GridRegion destination, uint flags)
147 {
148 base.PackData(args, aCircuit, destination, flags);
149 args["gatekeeper_serveruri"] = OSD.FromString(m_Gatekeeper.ServerURI);
150 args["gatekeeper_host"] = OSD.FromString(m_Gatekeeper.ExternalHostName);
151 args["gatekeeper_port"] = OSD.FromString(m_Gatekeeper.HttpPort.ToString());
152 args["destination_serveruri"] = OSD.FromString(destination.ServerURI);
231 } 153 }
232 154
233 protected OSDMap PackCreateAgentArguments(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress) 155 protected OSDMap PackCreateAgentArguments(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress)
@@ -633,7 +555,7 @@ namespace OpenSim.Services.Connectors.Hypergrid
633 } 555 }
634 catch 556 catch
635 { 557 {
636 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetServerURLs", m_ServerURL); 558 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetServerURLs for user {1}", m_ServerURL, userID);
637// reason = "Exception: " + e.Message; 559// reason = "Exception: " + e.Message;
638 return serverURLs; 560 return serverURLs;
639 } 561 }
diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs
index dbce9f6..e19c23d 100644
--- a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs
+++ b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs
@@ -123,6 +123,7 @@ namespace OpenSim.Services.Connectors.InstantMessage
123 gim["position_z"] = msg.Position.Z.ToString(); 123 gim["position_z"] = msg.Position.Z.ToString();
124 gim["region_id"] = msg.RegionID.ToString(); 124 gim["region_id"] = msg.RegionID.ToString();
125 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket, Base64FormattingOptions.None); 125 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket, Base64FormattingOptions.None);
126 gim["region_id"] = new UUID(msg.RegionID).ToString();
126 127
127 return gim; 128 return gim;
128 } 129 }
diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
index 44f5e01..36d4ae2 100644
--- a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
@@ -84,6 +84,30 @@ namespace OpenSim.Services.Connectors
84 m_ServerURI = serviceURI; 84 m_ServerURI = serviceURI;
85 } 85 }
86 86
87 private bool CheckReturn(Dictionary<string, object> ret)
88 {
89 if (ret == null)
90 return false;
91
92 if (ret.Count == 0)
93 return false;
94
95 if (ret.ContainsKey("RESULT"))
96 {
97 if (ret["RESULT"] is string)
98 {
99 bool result;
100
101 if (bool.TryParse((string)ret["RESULT"], out result))
102 return result;
103
104 return false;
105 }
106 }
107
108 return true;
109 }
110
87 public bool CreateUserInventory(UUID principalID) 111 public bool CreateUserInventory(UUID principalID)
88 { 112 {
89 Dictionary<string,object> ret = MakeRequest("CREATEUSERINVENTORY", 113 Dictionary<string,object> ret = MakeRequest("CREATEUSERINVENTORY",
@@ -91,12 +115,7 @@ namespace OpenSim.Services.Connectors
91 { "PRINCIPAL", principalID.ToString() } 115 { "PRINCIPAL", principalID.ToString() }
92 }); 116 });
93 117
94 if (ret == null) 118 return CheckReturn(ret);
95 return false;
96 if (ret.Count == 0)
97 return false;
98
99 return bool.Parse(ret["RESULT"].ToString());
100 } 119 }
101 120
102 public List<InventoryFolderBase> GetInventorySkeleton(UUID principalID) 121 public List<InventoryFolderBase> GetInventorySkeleton(UUID principalID)
@@ -106,9 +125,7 @@ namespace OpenSim.Services.Connectors
106 { "PRINCIPAL", principalID.ToString() } 125 { "PRINCIPAL", principalID.ToString() }
107 }); 126 });
108 127
109 if (ret == null) 128 if (!CheckReturn(ret))
110 return null;
111 if (ret.Count == 0)
112 return null; 129 return null;
113 130
114 Dictionary<string, object> folders = (Dictionary<string, object>)ret["FOLDERS"]; 131 Dictionary<string, object> folders = (Dictionary<string, object>)ret["FOLDERS"];
@@ -135,9 +152,7 @@ namespace OpenSim.Services.Connectors
135 { "PRINCIPAL", principalID.ToString() } 152 { "PRINCIPAL", principalID.ToString() }
136 }); 153 });
137 154
138 if (ret == null) 155 if (!CheckReturn(ret))
139 return null;
140 if (ret.Count == 0)
141 return null; 156 return null;
142 157
143 return BuildFolder((Dictionary<string, object>)ret["folder"]); 158 return BuildFolder((Dictionary<string, object>)ret["folder"]);
@@ -151,9 +166,7 @@ namespace OpenSim.Services.Connectors
151 { "TYPE", ((int)type).ToString() } 166 { "TYPE", ((int)type).ToString() }
152 }); 167 });
153 168
154 if (ret == null) 169 if (!CheckReturn(ret))
155 return null;
156 if (ret.Count == 0)
157 return null; 170 return null;
158 171
159 return BuildFolder((Dictionary<string, object>)ret["folder"]); 172 return BuildFolder((Dictionary<string, object>)ret["folder"]);
@@ -174,9 +187,7 @@ namespace OpenSim.Services.Connectors
174 { "FOLDER", folderID.ToString() } 187 { "FOLDER", folderID.ToString() }
175 }); 188 });
176 189
177 if (ret == null) 190 if (!CheckReturn(ret))
178 return null;
179 if (ret.Count == 0)
180 return null; 191 return null;
181 192
182 Dictionary<string,object> folders = 193 Dictionary<string,object> folders =
@@ -205,9 +216,7 @@ namespace OpenSim.Services.Connectors
205 { "FOLDER", folderID.ToString() } 216 { "FOLDER", folderID.ToString() }
206 }); 217 });
207 218
208 if (ret == null) 219 if (!CheckReturn(ret))
209 return null;
210 if (ret.Count == 0)
211 return null; 220 return null;
212 221
213 Dictionary<string, object> items = (Dictionary<string, object>)ret["ITEMS"]; 222 Dictionary<string, object> items = (Dictionary<string, object>)ret["ITEMS"];
@@ -230,10 +239,7 @@ namespace OpenSim.Services.Connectors
230 { "ID", folder.ID.ToString() } 239 { "ID", folder.ID.ToString() }
231 }); 240 });
232 241
233 if (ret == null) 242 return CheckReturn(ret);
234 return false;
235
236 return bool.Parse(ret["RESULT"].ToString());
237 } 243 }
238 244
239 public bool UpdateFolder(InventoryFolderBase folder) 245 public bool UpdateFolder(InventoryFolderBase folder)
@@ -248,10 +254,7 @@ namespace OpenSim.Services.Connectors
248 { "ID", folder.ID.ToString() } 254 { "ID", folder.ID.ToString() }
249 }); 255 });
250 256
251 if (ret == null) 257 return CheckReturn(ret);
252 return false;
253
254 return bool.Parse(ret["RESULT"].ToString());
255 } 258 }
256 259
257 public bool MoveFolder(InventoryFolderBase folder) 260 public bool MoveFolder(InventoryFolderBase folder)
@@ -263,10 +266,7 @@ namespace OpenSim.Services.Connectors
263 { "PRINCIPAL", folder.Owner.ToString() } 266 { "PRINCIPAL", folder.Owner.ToString() }
264 }); 267 });
265 268
266 if (ret == null) 269 return CheckReturn(ret);
267 return false;
268
269 return bool.Parse(ret["RESULT"].ToString());
270 } 270 }
271 271
272 public bool DeleteFolders(UUID principalID, List<UUID> folderIDs) 272 public bool DeleteFolders(UUID principalID, List<UUID> folderIDs)
@@ -282,10 +282,7 @@ namespace OpenSim.Services.Connectors
282 { "FOLDERS", slist } 282 { "FOLDERS", slist }
283 }); 283 });
284 284
285 if (ret == null) 285 return CheckReturn(ret);
286 return false;
287
288 return bool.Parse(ret["RESULT"].ToString());
289 } 286 }
290 287
291 public bool PurgeFolder(InventoryFolderBase folder) 288 public bool PurgeFolder(InventoryFolderBase folder)
@@ -295,10 +292,7 @@ namespace OpenSim.Services.Connectors
295 { "ID", folder.ID.ToString() } 292 { "ID", folder.ID.ToString() }
296 }); 293 });
297 294
298 if (ret == null) 295 return CheckReturn(ret);
299 return false;
300
301 return bool.Parse(ret["RESULT"].ToString());
302 } 296 }
303 297
304 public bool AddItem(InventoryItemBase item) 298 public bool AddItem(InventoryItemBase item)
@@ -330,10 +324,7 @@ namespace OpenSim.Services.Connectors
330 { "CreationDate", item.CreationDate.ToString() } 324 { "CreationDate", item.CreationDate.ToString() }
331 }); 325 });
332 326
333 if (ret == null) 327 return CheckReturn(ret);
334 return false;
335
336 return bool.Parse(ret["RESULT"].ToString());
337 } 328 }
338 329
339 public bool UpdateItem(InventoryItemBase item) 330 public bool UpdateItem(InventoryItemBase item)
@@ -365,10 +356,7 @@ namespace OpenSim.Services.Connectors
365 { "CreationDate", item.CreationDate.ToString() } 356 { "CreationDate", item.CreationDate.ToString() }
366 }); 357 });
367 358
368 if (ret == null) 359 return CheckReturn(ret);
369 return false;
370
371 return bool.Parse(ret["RESULT"].ToString());
372 } 360 }
373 361
374 public bool MoveItems(UUID principalID, List<InventoryItemBase> items) 362 public bool MoveItems(UUID principalID, List<InventoryItemBase> items)
@@ -389,10 +377,7 @@ namespace OpenSim.Services.Connectors
389 { "DESTLIST", destlist } 377 { "DESTLIST", destlist }
390 }); 378 });
391 379
392 if (ret == null) 380 return CheckReturn(ret);
393 return false;
394
395 return bool.Parse(ret["RESULT"].ToString());
396 } 381 }
397 382
398 public bool DeleteItems(UUID principalID, List<UUID> itemIDs) 383 public bool DeleteItems(UUID principalID, List<UUID> itemIDs)
@@ -408,10 +393,7 @@ namespace OpenSim.Services.Connectors
408 { "ITEMS", slist } 393 { "ITEMS", slist }
409 }); 394 });
410 395
411 if (ret == null) 396 return CheckReturn(ret);
412 return false;
413
414 return bool.Parse(ret["RESULT"].ToString());
415 } 397 }
416 398
417 public InventoryItemBase GetItem(InventoryItemBase item) 399 public InventoryItemBase GetItem(InventoryItemBase item)
@@ -423,9 +405,7 @@ namespace OpenSim.Services.Connectors
423 { "ID", item.ID.ToString() } 405 { "ID", item.ID.ToString() }
424 }); 406 });
425 407
426 if (ret == null) 408 if (!CheckReturn(ret))
427 return null;
428 if (ret.Count == 0)
429 return null; 409 return null;
430 410
431 return BuildItem((Dictionary<string, object>)ret["item"]); 411 return BuildItem((Dictionary<string, object>)ret["item"]);
@@ -447,9 +427,7 @@ namespace OpenSim.Services.Connectors
447 { "ID", folder.ID.ToString() } 427 { "ID", folder.ID.ToString() }
448 }); 428 });
449 429
450 if (ret == null) 430 if (!CheckReturn(ret))
451 return null;
452 if (ret.Count == 0)
453 return null; 431 return null;
454 432
455 return BuildFolder((Dictionary<string, object>)ret["folder"]); 433 return BuildFolder((Dictionary<string, object>)ret["folder"]);
@@ -469,7 +447,7 @@ namespace OpenSim.Services.Connectors
469 { "PRINCIPAL", principalID.ToString() } 447 { "PRINCIPAL", principalID.ToString() }
470 }); 448 });
471 449
472 if (ret == null) 450 if (!CheckReturn(ret))
473 return null; 451 return null;
474 452
475 List<InventoryItemBase> items = new List<InventoryItemBase>(); 453 List<InventoryItemBase> items = new List<InventoryItemBase>();
@@ -488,10 +466,22 @@ namespace OpenSim.Services.Connectors
488 { "ASSET", assetID.ToString() } 466 { "ASSET", assetID.ToString() }
489 }); 467 });
490 468
469 // We cannot use CheckReturn() here because valid values for RESULT are "false" (in the case of request failure) or an int
491 if (ret == null) 470 if (ret == null)
492 return 0; 471 return 0;
493 472
494 return int.Parse(ret["RESULT"].ToString()); 473 if (ret.ContainsKey("RESULT"))
474 {
475 if (ret["RESULT"] is string)
476 {
477 int intResult;
478
479 if (int.TryParse ((string)ret["RESULT"], out intResult))
480 return intResult;
481 }
482 }
483
484 return 0;
495 } 485 }
496 486
497 public InventoryCollection GetUserInventory(UUID principalID) 487 public InventoryCollection GetUserInventory(UUID principalID)
@@ -508,9 +498,7 @@ namespace OpenSim.Services.Connectors
508 { "PRINCIPAL", principalID.ToString() } 498 { "PRINCIPAL", principalID.ToString() }
509 }); 499 });
510 500
511 if (ret == null) 501 if (!CheckReturn(ret))
512 return null;
513 if (ret.Count == 0)
514 return null; 502 return null;
515 503
516 Dictionary<string, object> folders = 504 Dictionary<string, object> folders =
diff --git a/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs b/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs
index 267dd71..725204d 100644
--- a/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs
+++ b/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs
@@ -174,29 +174,32 @@ namespace OpenSim.Services.Connectors
174 } 174 }
175 else if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "failure")) 175 else if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "failure"))
176 { 176 {
177 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Registration failed: {0}", replyData["Message"].ToString()); 177 reason = string.Format("Map post to {0} failed: {1}", uri, replyData["Message"].ToString());
178 reason = replyData["Message"].ToString(); 178 m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason);
179
179 return false; 180 return false;
180 } 181 }
181 else if (!replyData.ContainsKey("Result")) 182 else if (!replyData.ContainsKey("Result"))
182 { 183 {
183 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: reply data does not contain result field"); 184 reason = string.Format("Reply data from {0} does not contain result field", uri);
185 m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason);
184 } 186 }
185 else 187 else
186 { 188 {
187 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: unexpected result {0}", replyData["Result"].ToString()); 189 reason = string.Format("Unexpected result {0} from {1}" + replyData["Result"].ToString(), uri);
188 reason = "Unexpected result " + replyData["Result"].ToString(); 190 m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason);
189 } 191 }
190
191 } 192 }
192 else 193 else
193 { 194 {
194 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Map post received null reply"); 195 reason = string.Format("Map post received null reply from {0}", uri);
196 m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason);
195 } 197 }
196 } 198 }
197 catch (Exception e) 199 catch (Exception e)
198 { 200 {
199 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Exception when contacting map server at {0}: {1}", uri, e.Message); 201 reason = string.Format("Exception when posting to map server at {0}: {1}", uri, e.Message);
202 m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason);
200 } 203 }
201 finally 204 finally
202 { 205 {
diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs
index b36fa23..245703c 100644
--- a/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs
@@ -98,7 +98,7 @@ namespace OpenSim.Services.Connectors
98 catch (Exception e) 98 catch (Exception e)
99 { 99 {
100 m_log.WarnFormat( 100 m_log.WarnFormat(
101 "[NEIGHBOUR SERVICE CONNCTOR]: Unable to parse uri {0} to send HelloNeighbour from {1} to {2}. Exception {3}{4}", 101 "[NEIGHBOUR SERVICES CONNECTOR]: Unable to parse uri {0} to send HelloNeighbour from {1} to {2}. Exception {3}{4}",
102 uri, thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace); 102 uri, thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
103 103
104 return false; 104 return false;
@@ -117,7 +117,7 @@ namespace OpenSim.Services.Connectors
117 catch (Exception e) 117 catch (Exception e)
118 { 118 {
119 m_log.WarnFormat( 119 m_log.WarnFormat(
120 "[NEIGHBOUR SERVICE CONNCTOR]: PackRegionInfoData failed for HelloNeighbour from {0} to {1}. Exception {2}{3}", 120 "[NEIGHBOUR SERVICES CONNECTOR]: PackRegionInfoData failed for HelloNeighbour from {0} to {1}. Exception {2}{3}",
121 thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace); 121 thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
122 122
123 return false; 123 return false;
@@ -137,7 +137,7 @@ namespace OpenSim.Services.Connectors
137 catch (Exception e) 137 catch (Exception e)
138 { 138 {
139 m_log.WarnFormat( 139 m_log.WarnFormat(
140 "[NEIGHBOUR SERVICE CONNCTOR]: Exception thrown on serialization of HelloNeighbour from {0} to {1}. Exception {2}{3}", 140 "[NEIGHBOUR SERVICES CONNECTOR]: Exception thrown on serialization of HelloNeighbour from {0} to {1}. Exception {2}{3}",
141 thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace); 141 thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
142 142
143 return false; 143 return false;
@@ -175,7 +175,7 @@ namespace OpenSim.Services.Connectors
175 if (webResponse == null) 175 if (webResponse == null)
176 { 176 {
177 m_log.DebugFormat( 177 m_log.DebugFormat(
178 "[REST COMMS]: Null reply on DoHelloNeighbourCall post from {0} to {1}", 178 "[NEIGHBOUR SERVICES CONNECTOR]: Null reply on DoHelloNeighbourCall post from {0} to {1}",
179 thisRegion.RegionName, region.RegionName); 179 thisRegion.RegionName, region.RegionName);
180 } 180 }
181 181
@@ -193,7 +193,7 @@ namespace OpenSim.Services.Connectors
193 catch (Exception e) 193 catch (Exception e)
194 { 194 {
195 m_log.WarnFormat( 195 m_log.WarnFormat(
196 "[NEIGHBOUR SERVICE CONNCTOR]: Exception on reply of DoHelloNeighbourCall from {0} back to {1}. Exception {2}{3}", 196 "[NEIGHBOUR SERVICES CONNECTOR]: Exception on reply of DoHelloNeighbourCall from {0} back to {1}. Exception {2}{3}",
197 region.RegionName, thisRegion.RegionName, e.Message, e.StackTrace); 197 region.RegionName, thisRegion.RegionName, e.Message, e.StackTrace);
198 198
199 return false; 199 return false;
diff --git a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
index 8b18afb..bc89f5d 100644
--- a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
index 74b980c..6f8d9ed 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Collections.Specialized;
30using System.IO; 31using System.IO;
31using System.Net; 32using System.Net;
32using System.Reflection; 33using System.Reflection;
@@ -122,7 +123,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
122 m_Enabled = true; 123 m_Enabled = true;
123 } 124 }
124 125
125 #region IAssetService 126#region IAssetService
126 127
127 public AssetBase Get(string id) 128 public AssetBase Get(string id)
128 { 129 {
@@ -140,8 +141,9 @@ namespace OpenSim.Services.Connectors.SimianGrid
140 return asset; 141 return asset;
141 } 142 }
142 143
143 return GetRemote(id); 144 return SimianGetOperation(id);
144 } 145 }
146
145 147
146 public AssetBase GetCached(string id) 148 public AssetBase GetCached(string id)
147 { 149 {
@@ -164,8 +166,6 @@ namespace OpenSim.Services.Connectors.SimianGrid
164 throw new InvalidOperationException(); 166 throw new InvalidOperationException();
165 } 167 }
166 168
167 AssetMetadata metadata = null;
168
169 // Cache fetch 169 // Cache fetch
170 if (m_cache != null) 170 if (m_cache != null)
171 { 171 {
@@ -174,50 +174,18 @@ namespace OpenSim.Services.Connectors.SimianGrid
174 return asset.Metadata; 174 return asset.Metadata;
175 } 175 }
176 176
177 Uri url; 177 // return GetRemoteMetadata(id);
178 178 return SimianGetMetadataOperation(id);
179 // Determine if id is an absolute URL or a grid-relative UUID
180 if (!Uri.TryCreate(id, UriKind.Absolute, out url))
181 url = new Uri(m_serverUrl + id);
182
183 try
184 {
185 HttpWebRequest request = UntrustedHttpWebRequest.Create(url);
186 request.Method = "HEAD";
187
188 using (WebResponse response = request.GetResponse())
189 {
190 using (Stream responseStream = response.GetResponseStream())
191 {
192 // Create the metadata object
193 metadata = new AssetMetadata();
194 metadata.ContentType = response.ContentType;
195 metadata.ID = id;
196
197 UUID uuid;
198 if (UUID.TryParse(id, out uuid))
199 metadata.FullID = uuid;
200
201 string lastModifiedStr = response.Headers.Get("Last-Modified");
202 if (!String.IsNullOrEmpty(lastModifiedStr))
203 {
204 DateTime lastModified;
205 if (DateTime.TryParse(lastModifiedStr, out lastModified))
206 metadata.CreationDate = lastModified;
207 }
208 }
209 }
210 }
211 catch (Exception ex)
212 {
213 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset HEAD from " + url + " failed: " + ex.Message);
214 }
215
216 return metadata;
217 } 179 }
218 180
219 public byte[] GetData(string id) 181 public byte[] GetData(string id)
220 { 182 {
183 if (String.IsNullOrEmpty(m_serverUrl))
184 {
185 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
186 throw new InvalidOperationException();
187 }
188
221 AssetBase asset = Get(id); 189 AssetBase asset = Get(id);
222 190
223 if (asset != null) 191 if (asset != null)
@@ -255,7 +223,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
255 Util.FireAndForget( 223 Util.FireAndForget(
256 delegate(object o) 224 delegate(object o)
257 { 225 {
258 AssetBase asset = GetRemote(id); 226 AssetBase asset = SimianGetOperation(id);
259 handler(id, sender, asset); 227 handler(id, sender, asset);
260 } 228 }
261 ); 229 );
@@ -278,7 +246,6 @@ namespace OpenSim.Services.Connectors.SimianGrid
278 } 246 }
279 247
280 bool storedInCache = false; 248 bool storedInCache = false;
281 string errorMessage = null;
282 249
283 // AssetID handling 250 // AssetID handling
284 if (String.IsNullOrEmpty(asset.ID) || asset.ID == ZeroID) 251 if (String.IsNullOrEmpty(asset.ID) || asset.ID == ZeroID)
@@ -307,83 +274,9 @@ namespace OpenSim.Services.Connectors.SimianGrid
307 return asset.ID; 274 return asset.ID;
308 } 275 }
309 276
310 // Distinguish public and private assets 277 return SimianStoreOperation(asset);
311 bool isPublic = true;
312 switch ((AssetType)asset.Type)
313 {
314 case AssetType.CallingCard:
315 case AssetType.Gesture:
316 case AssetType.LSLBytecode:
317 case AssetType.LSLText:
318 isPublic = false;
319 break;
320 }
321
322 // Make sure ContentType is set
323 if (String.IsNullOrEmpty(asset.Metadata.ContentType))
324 asset.Metadata.ContentType = SLUtil.SLAssetTypeToContentType(asset.Type);
325
326 // Build the remote storage request
327 List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>()
328 {
329 new MultipartForm.Parameter("AssetID", asset.FullID.ToString()),
330 new MultipartForm.Parameter("CreatorID", asset.Metadata.CreatorID),
331 new MultipartForm.Parameter("Temporary", asset.Temporary ? "1" : "0"),
332 new MultipartForm.Parameter("Public", isPublic ? "1" : "0"),
333 new MultipartForm.File("Asset", asset.Name, asset.Metadata.ContentType, asset.Data)
334 };
335
336 // Make the remote storage request
337 try
338 {
339 // Simian does not require the asset ID to be in the URL because it's in the post data.
340 // By appending it to the URL also, we allow caching proxies (squid) to invalidate asset URLs
341 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl + asset.FullID.ToString());
342
343 using (HttpWebResponse response = MultipartForm.Post(request, postParameters))
344 {
345 using (Stream responseStream = response.GetResponseStream())
346 {
347 string responseStr = null;
348
349 try
350 {
351 responseStr = responseStream.GetStreamString();
352 OSD responseOSD = OSDParser.Deserialize(responseStr);
353 if (responseOSD.Type == OSDType.Map)
354 {
355 OSDMap responseMap = (OSDMap)responseOSD;
356 if (responseMap["Success"].AsBoolean())
357 return asset.ID;
358 else
359 errorMessage = "Upload failed: " + responseMap["Message"].AsString();
360 }
361 else
362 {
363 errorMessage = "Response format was invalid:\n" + responseStr;
364 }
365 }
366 catch (Exception ex)
367 {
368 if (!String.IsNullOrEmpty(responseStr))
369 errorMessage = "Failed to parse the response:\n" + responseStr;
370 else
371 errorMessage = "Failed to retrieve the response: " + ex.Message;
372 }
373 }
374 }
375 }
376 catch (WebException ex)
377 {
378 errorMessage = ex.Message;
379 }
380
381 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to store asset \"{0}\" ({1}, {2}): {3}",
382 asset.Name, asset.ID, asset.Metadata.ContentType, errorMessage);
383
384 return null;
385 } 278 }
386 279
387 /// <summary> 280 /// <summary>
388 /// Update an asset's content 281 /// Update an asset's content
389 /// </summary> 282 /// </summary>
@@ -393,11 +286,17 @@ namespace OpenSim.Services.Connectors.SimianGrid
393 /// <returns></returns> 286 /// <returns></returns>
394 public bool UpdateContent(string id, byte[] data) 287 public bool UpdateContent(string id, byte[] data)
395 { 288 {
289 if (String.IsNullOrEmpty(m_serverUrl))
290 {
291 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
292 throw new InvalidOperationException();
293 }
294
396 AssetBase asset = Get(id); 295 AssetBase asset = Get(id);
397 296
398 if (asset == null) 297 if (asset == null)
399 { 298 {
400 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Failed to fetch asset " + id + " for updating"); 299 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to fetch asset {0} for updating", id);
401 return false; 300 return false;
402 } 301 }
403 302
@@ -420,83 +319,347 @@ namespace OpenSim.Services.Connectors.SimianGrid
420 throw new InvalidOperationException(); 319 throw new InvalidOperationException();
421 } 320 }
422 321
423 //string errorMessage = String.Empty;
424 string url = m_serverUrl + id;
425
426 if (m_cache != null) 322 if (m_cache != null)
427 m_cache.Expire(id); 323 m_cache.Expire(id);
428 324
325 return SimianDeleteOperation(id);
326 }
327
328#endregion IAssetService
329
330#region SimianOperations
331 /// <summary>
332 /// Invokes the xRemoveAsset operation on the simian server to delete an asset
333 /// </summary>
334 /// <param name="id"></param>
335 /// <returns></returns>
336 private bool SimianDeleteOperation(string id)
337 {
429 try 338 try
430 { 339 {
431 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); 340 NameValueCollection requestArgs = new NameValueCollection
432 request.Method = "DELETE"; 341 {
342 { "RequestMethod", "xRemoveAsset" },
343 { "AssetID", id }
344 };
433 345
434 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 346 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
347 if (! response["Success"].AsBoolean())
435 { 348 {
436 if (response.StatusCode != HttpStatusCode.NoContent) 349 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: failed to delete asset; {0}",response["Message"].AsString());
437 { 350 return false;
438 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Unexpected response when deleting asset " + url + ": " +
439 response.StatusCode + " (" + response.StatusDescription + ")");
440 }
441 } 351 }
442 352
443 return true; 353 return true;
354
444 } 355 }
445 catch (Exception ex) 356 catch (Exception ex)
446 { 357 {
447 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Failed to delete asset " + id + " from the asset service: " + ex.Message); 358 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: failed to delete asset {0}; {1}", id, ex.Message);
448 return false;
449 } 359 }
450 }
451 360
452 #endregion IAssetService 361 return false;
362 }
453 363
454 private AssetBase GetRemote(string id) 364 /// <summary>
365 /// Invokes the xAddAsset operation on the simian server to create or update an asset
366 /// </summary>
367 /// <param name="id"></param>
368 /// <returns></returns>
369 private string SimianStoreOperation(AssetBase asset)
455 { 370 {
456 AssetBase asset = null; 371 try
457 Uri url; 372 {
373 NameValueCollection requestArgs = new NameValueCollection
374 {
375 { "RequestMethod", "xAddAsset" },
376 { "ContentType", asset.Metadata.ContentType },
377 { "EncodedData", Convert.ToBase64String(asset.Data) },
378 { "AssetID", asset.FullID.ToString() },
379 { "CreatorID", asset.Metadata.CreatorID },
380 { "Temporary", asset.Temporary ? "1" : "0" },
381 { "Name", asset.Name }
382 };
383
384 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
385 if (! response["Success"].AsBoolean())
386 {
387 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR] failed to store asset; {0}",response["Message"].AsString());
388 return null;
389 }
458 390
459 // Determine if id is an absolute URL or a grid-relative UUID 391 // asset.ID is always set before calling this function
460 if (!Uri.TryCreate(id, UriKind.Absolute, out url)) 392 return asset.ID;
461 url = new Uri(m_serverUrl + id); 393
394 }
395 catch (Exception ex)
396 {
397 m_log.ErrorFormat("[SIMIAN ASSET CONNECTOR] failed to store asset; {0}",ex.Message);
398 }
399
400 return null;
401 }
462 402
463 try 403 /// <summary>
404 /// Invokes the xGetAsset operation on the simian server to get data associated with an asset
405 /// </summary>
406 /// <param name="id"></param>
407 /// <returns></returns>
408 private AssetBase SimianGetOperation(string id)
409 {
410 try
464 { 411 {
465 HttpWebRequest request = UntrustedHttpWebRequest.Create(url); 412 NameValueCollection requestArgs = new NameValueCollection
413 {
414 { "RequestMethod", "xGetAsset" },
415 { "ID", id }
416 };
466 417
467 using (WebResponse response = request.GetResponse()) 418 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
419 if (! response["Success"].AsBoolean())
468 { 420 {
469 using (Stream responseStream = response.GetResponseStream()) 421 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR] Failed to get asset; {0}",response["Message"].AsString());
470 { 422 return null;
471 string creatorID = response.Headers.GetOne("X-Asset-Creator-Id") ?? String.Empty;
472
473 // Create the asset object
474 asset = new AssetBase(id, String.Empty, SLUtil.ContentTypeToSLAssetType(response.ContentType), creatorID);
475
476 UUID assetID;
477 if (UUID.TryParse(id, out assetID))
478 asset.FullID = assetID;
479
480 // Grab the asset data from the response stream
481 using (MemoryStream stream = new MemoryStream())
482 {
483 responseStream.CopyStream(stream, Int32.MaxValue);
484 asset.Data = stream.ToArray();
485 }
486 }
487 } 423 }
424
425 AssetBase asset = new AssetBase();
488 426
489 // Cache store 427 asset.ID = id;
490 if (m_cache != null && asset != null) 428 asset.Name = String.Empty;
491 m_cache.Cache(asset); 429 asset.Metadata.ContentType = response["ContentType"].AsString(); // this will also set the asset Type property
430 asset.CreatorID = response["CreatorID"].AsString();
431 asset.Data = System.Convert.FromBase64String(response["EncodedData"].AsString());
432 asset.Local = false;
433 asset.Temporary = response["Temporary"];
492 434
493 return asset; 435 return asset;
494 } 436 }
495 catch (Exception ex) 437 catch (Exception ex)
496 { 438 {
497 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message); 439 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: failed to retrieve asset {0}; {1}", id, ex.Message);
498 return null;
499 } 440 }
441
442 return null;
443 }
444
445 /// <summary>
446 /// Invokes the xGetAssetMetadata operation on the simian server to retrieve metadata for an asset
447 /// This operation is generally used to determine if an asset exists in the database
448 /// </summary>
449 /// <param name="id"></param>
450 /// <returns></returns>
451 private AssetMetadata SimianGetMetadataOperation(string id)
452 {
453 try
454 {
455 NameValueCollection requestArgs = new NameValueCollection
456 {
457 { "RequestMethod", "xGetAssetMetadata" },
458 { "ID", id }
459 };
460
461 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
462 if (! response["Success"].AsBoolean())
463 {
464 // this is not really an error, this call is used to test existence
465 // m_log.DebugFormat("[SIMIAN ASSET CONNECTOR] Failed to get asset metadata; {0}",response["Message"].AsString());
466 return null;
467 }
468
469 AssetMetadata metadata = new AssetMetadata();
470 metadata.ID = id;
471 metadata.ContentType = response["ContentType"].AsString();
472 metadata.CreatorID = response["CreatorID"].AsString();
473 metadata.Local = false;
474 metadata.Temporary = response["Temporary"];
475
476 string lastModifiedStr = response["Last-Modified"].AsString();
477 if (! String.IsNullOrEmpty(lastModifiedStr))
478 {
479 DateTime lastModified;
480 if (DateTime.TryParse(lastModifiedStr, out lastModified))
481 metadata.CreationDate = lastModified;
482 }
483
484 return metadata;
485 }
486 catch (Exception ex)
487 {
488 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to get asset metadata; {0}", ex.Message);
489 }
490
491 return null;
500 } 492 }
493#endregion
494
495 // private AssetMetadata GetRemoteMetadata(string id)
496 // {
497 // Uri url;
498 // AssetMetadata metadata = null;
499
500 // // Determine if id is an absolute URL or a grid-relative UUID
501 // if (!Uri.TryCreate(id, UriKind.Absolute, out url))
502 // url = new Uri(m_serverUrl + id);
503
504 // try
505 // {
506 // HttpWebRequest request = UntrustedHttpWebRequest.Create(url);
507 // request.Method = "HEAD";
508
509 // using (WebResponse response = request.GetResponse())
510 // {
511 // using (Stream responseStream = response.GetResponseStream())
512 // {
513 // // Create the metadata object
514 // metadata = new AssetMetadata();
515 // metadata.ContentType = response.ContentType;
516 // metadata.ID = id;
517
518 // UUID uuid;
519 // if (UUID.TryParse(id, out uuid))
520 // metadata.FullID = uuid;
521
522 // string lastModifiedStr = response.Headers.Get("Last-Modified");
523 // if (!String.IsNullOrEmpty(lastModifiedStr))
524 // {
525 // DateTime lastModified;
526 // if (DateTime.TryParse(lastModifiedStr, out lastModified))
527 // metadata.CreationDate = lastModified;
528 // }
529 // }
530 // }
531 // }
532 // catch (Exception ex)
533 // {
534 // m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset HEAD from " + url + " failed: " + ex.Message);
535 // }
536
537 // return metadata;
538 // }
539
540 // private AssetBase GetRemote(string id)
541 // {
542 // AssetBase asset = null;
543 // Uri url;
544
545 // // Determine if id is an absolute URL or a grid-relative UUID
546 // if (!Uri.TryCreate(id, UriKind.Absolute, out url))
547 // url = new Uri(m_serverUrl + id);
548
549 // try
550 // {
551 // HttpWebRequest request = UntrustedHttpWebRequest.Create(url);
552
553 // using (WebResponse response = request.GetResponse())
554 // {
555 // using (Stream responseStream = response.GetResponseStream())
556 // {
557 // string creatorID = response.Headers.GetOne("X-Asset-Creator-Id") ?? String.Empty;
558
559 // // Create the asset object
560 // asset = new AssetBase(id, String.Empty, SLUtil.ContentTypeToSLAssetType(response.ContentType), creatorID);
561
562 // UUID assetID;
563 // if (UUID.TryParse(id, out assetID))
564 // asset.FullID = assetID;
565
566 // // Grab the asset data from the response stream
567 // using (MemoryStream stream = new MemoryStream())
568 // {
569 // responseStream.CopyStream(stream, Int32.MaxValue);
570 // asset.Data = stream.ToArray();
571 // }
572 // }
573 // }
574
575 // // Cache store
576 // if (m_cache != null && asset != null)
577 // m_cache.Cache(asset);
578
579 // return asset;
580 // }
581 // catch (Exception ex)
582 // {
583 // m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message);
584 // return null;
585 // }
586 // }
587
588 // private string StoreRemote(AssetBase asset)
589 // {
590 // // Distinguish public and private assets
591 // bool isPublic = true;
592 // switch ((AssetType)asset.Type)
593 // {
594 // case AssetType.CallingCard:
595 // case AssetType.Gesture:
596 // case AssetType.LSLBytecode:
597 // case AssetType.LSLText:
598 // isPublic = false;
599 // break;
600 // }
601
602 // string errorMessage = null;
603
604 // // Build the remote storage request
605 // List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>()
606 // {
607 // new MultipartForm.Parameter("AssetID", asset.FullID.ToString()),
608 // new MultipartForm.Parameter("CreatorID", asset.Metadata.CreatorID),
609 // new MultipartForm.Parameter("Temporary", asset.Temporary ? "1" : "0"),
610 // new MultipartForm.Parameter("Public", isPublic ? "1" : "0"),
611 // new MultipartForm.File("Asset", asset.Name, asset.Metadata.ContentType, asset.Data)
612 // };
613
614 // // Make the remote storage request
615 // try
616 // {
617 // // Simian does not require the asset ID to be in the URL because it's in the post data.
618 // // By appending it to the URL also, we allow caching proxies (squid) to invalidate asset URLs
619 // HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl + asset.FullID.ToString());
620
621 // using (HttpWebResponse response = MultipartForm.Post(request, postParameters))
622 // {
623 // using (Stream responseStream = response.GetResponseStream())
624 // {
625 // string responseStr = null;
626
627 // try
628 // {
629 // responseStr = responseStream.GetStreamString();
630 // OSD responseOSD = OSDParser.Deserialize(responseStr);
631 // if (responseOSD.Type == OSDType.Map)
632 // {
633 // OSDMap responseMap = (OSDMap)responseOSD;
634 // if (responseMap["Success"].AsBoolean())
635 // return asset.ID;
636 // else
637 // errorMessage = "Upload failed: " + responseMap["Message"].AsString();
638 // }
639 // else
640 // {
641 // errorMessage = "Response format was invalid:\n" + responseStr;
642 // }
643 // }
644 // catch (Exception ex)
645 // {
646 // if (!String.IsNullOrEmpty(responseStr))
647 // errorMessage = "Failed to parse the response:\n" + responseStr;
648 // else
649 // errorMessage = "Failed to retrieve the response: " + ex.Message;
650 // }
651 // }
652 // }
653 // }
654 // catch (WebException ex)
655 // {
656 // errorMessage = ex.Message;
657 // }
658
659 // m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to store asset \"{0}\" ({1}, {2}): {3}",
660 // asset.Name, asset.ID, asset.Metadata.ContentType, errorMessage);
661
662 // return null;
663 // }
501 } 664 }
502} 665}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
index 03b19ae..c402907 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
@@ -116,7 +116,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
116 { "UserID", principalID.ToString() } 116 { "UserID", principalID.ToString() }
117 }; 117 };
118 118
119 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 119 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
120 if (response["Success"].AsBoolean() && response["Identities"] is OSDArray) 120 if (response["Success"].AsBoolean() && response["Identities"] is OSDArray)
121 { 121 {
122 bool md5hashFound = false; 122 bool md5hashFound = false;
@@ -159,7 +159,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
159 { "SessionID", token } 159 { "SessionID", token }
160 }; 160 };
161 161
162 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 162 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
163 if (response["Success"].AsBoolean()) 163 if (response["Success"].AsBoolean())
164 { 164 {
165 return true; 165 return true;
@@ -181,7 +181,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
181 { "UserID", principalID.ToString() } 181 { "UserID", principalID.ToString() }
182 }; 182 };
183 183
184 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 184 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
185 if (response["Success"].AsBoolean()) 185 if (response["Success"].AsBoolean())
186 { 186 {
187 return true; 187 return true;
@@ -204,7 +204,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
204 { "UserID", principalID.ToString() } 204 { "UserID", principalID.ToString() }
205 }; 205 };
206 206
207 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 207 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
208 if (response["Success"].AsBoolean() && response["User"] is OSDMap) 208 if (response["Success"].AsBoolean() && response["User"] is OSDMap)
209 { 209 {
210 OSDMap userMap = (OSDMap)response["User"]; 210 OSDMap userMap = (OSDMap)response["User"];
@@ -224,7 +224,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
224 { "UserID", principalID.ToString() } 224 { "UserID", principalID.ToString() }
225 }; 225 };
226 226
227 response = WebUtil.PostToService(m_serverUrl, requestArgs); 227 response = SimianGrid.PostToService(m_serverUrl, requestArgs);
228 bool success = response["Success"].AsBoolean(); 228 bool success = response["Success"].AsBoolean();
229 229
230 if (!success) 230 if (!success)
@@ -303,7 +303,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
303 { "UserID", userID.ToString() } 303 { "UserID", userID.ToString() }
304 }; 304 };
305 305
306 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 306 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
307 if (response["Success"].AsBoolean()) 307 if (response["Success"].AsBoolean())
308 return response["SessionID"].AsUUID().ToString(); 308 return response["SessionID"].AsUUID().ToString();
309 else 309 else
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
index 841bfa0..a397740 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
@@ -122,7 +122,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
122 { "UserID", userID.ToString() } 122 { "UserID", userID.ToString() }
123 }; 123 };
124 124
125 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 125 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
126 if (response["Success"].AsBoolean()) 126 if (response["Success"].AsBoolean())
127 { 127 {
128 OSDMap map = null; 128 OSDMap map = null;
@@ -168,7 +168,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
168 { "LLPackedAppearance", OSDParser.SerializeJsonString(map) } 168 { "LLPackedAppearance", OSDParser.SerializeJsonString(map) }
169 }; 169 };
170 170
171 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 171 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
172 bool success = response["Success"].AsBoolean(); 172 bool success = response["Success"].AsBoolean();
173 173
174 if (! success) 174 if (! success)
@@ -189,7 +189,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
189 { "UserID", userID.ToString() } 189 { "UserID", userID.ToString() }
190 }; 190 };
191 191
192 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 192 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
193 if (response["Success"].AsBoolean()) 193 if (response["Success"].AsBoolean())
194 { 194 {
195 OSDMap map = null; 195 OSDMap map = null;
@@ -306,7 +306,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
306 { "LLAttachments", OSDParser.SerializeJsonString(items) } 306 { "LLAttachments", OSDParser.SerializeJsonString(items) }
307 }; 307 };
308 308
309 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 309 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
310 bool success = response["Success"].AsBoolean(); 310 bool success = response["Success"].AsBoolean();
311 311
312 if (!success) 312 if (!success)
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs b/OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs
new file mode 100644
index 0000000..764e71f
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs
@@ -0,0 +1,180 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Reflection;
32using System.IO;
33using System.Web;
34
35using log4net;
36using Nini.Config;
37using Mono.Addins;
38
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41
42using OpenSim.Framework;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45using OpenSim.Services.Interfaces;
46using Caps = OpenSim.Framework.Capabilities.Caps;
47
48namespace OpenSim.Services.Connectors.SimianGrid
49{
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianExternalCapsModule")]
51 public class SimianExternalCapsModule : INonSharedRegionModule, IExternalCapsModule
52 {
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
55 private bool m_enabled = true;
56 private Scene m_scene;
57 private String m_simianURL;
58
59#region IRegionModule Members
60
61 public string Name
62 {
63 get { return this.GetType().Name; }
64 }
65
66 public void Initialise(IConfigSource config)
67 {
68 try
69 {
70 IConfig m_config;
71
72 if ((m_config = config.Configs["SimianExternalCaps"]) != null)
73 {
74 m_enabled = m_config.GetBoolean("Enabled", m_enabled);
75 if ((m_config = config.Configs["SimianGrid"]) != null)
76 {
77 m_simianURL = m_config.GetString("SimianServiceURL");
78 if (String.IsNullOrEmpty(m_simianURL))
79 {
80 //m_log.DebugFormat("[SimianGrid] service URL is not defined");
81 m_enabled = false;
82 return;
83 }
84 }
85 }
86 else
87 m_enabled = false;
88 }
89 catch (Exception e)
90 {
91 m_log.ErrorFormat("[SimianExternalCaps] initialization error: {0}",e.Message);
92 return;
93 }
94 }
95
96 public void PostInitialise() { }
97 public void Close() { }
98
99 public void AddRegion(Scene scene)
100 {
101 if (! m_enabled)
102 return;
103
104 m_scene = scene;
105 m_scene.RegisterModuleInterface<IExternalCapsModule>(this);
106 }
107
108 public void RemoveRegion(Scene scene)
109 {
110 if (! m_enabled)
111 return;
112
113 m_scene.EventManager.OnRegisterCaps -= RegisterCapsEventHandler;
114 m_scene.EventManager.OnDeregisterCaps -= DeregisterCapsEventHandler;
115 }
116
117 public void RegionLoaded(Scene scene)
118 {
119 if (! m_enabled)
120 return;
121
122 m_scene.EventManager.OnRegisterCaps += RegisterCapsEventHandler;
123 m_scene.EventManager.OnDeregisterCaps += DeregisterCapsEventHandler;
124 }
125
126 public Type ReplaceableInterface
127 {
128 get { return null; }
129 }
130
131#endregion
132
133#region IExternalCapsModule
134 // Eg http://grid.sciencesim.com/GridPublic/%CAP%/%OP%/"
135 public bool RegisterExternalUserCapsHandler(UUID agentID, Caps caps, String capName, String urlSkel)
136 {
137 UUID cap = UUID.Random();
138
139 // Call to simian to register the cap we generated
140 // NameValueCollection requestArgs = new NameValueCollection
141 // {
142 // { "RequestMethod", "AddCapability" },
143 // { "Resource", "user" },
144 // { "Expiration", 0 },
145 // { "OwnerID", agentID.ToString() },
146 // { "CapabilityID", cap.ToString() }
147 // };
148
149 // OSDMap response = SimianGrid.PostToService(m_simianURL, requestArgs);
150
151 Dictionary<String,String> subs = new Dictionary<String,String>();
152 subs["%OP%"] = capName;
153 subs["%USR%"] = agentID.ToString();
154 subs["%CAP%"] = cap.ToString();
155 subs["%SIM%"] = m_scene.RegionInfo.RegionID.ToString();
156
157 caps.RegisterHandler(capName,ExpandSkeletonURL(urlSkel,subs));
158 return true;
159 }
160
161#endregion
162
163#region EventHandlers
164 public void RegisterCapsEventHandler(UUID agentID, Caps caps) { }
165 public void DeregisterCapsEventHandler(UUID agentID, Caps caps) { }
166#endregion
167
168 private String ExpandSkeletonURL(String urlSkel, Dictionary<String,String> subs)
169 {
170 String result = urlSkel;
171
172 foreach (KeyValuePair<String,String> kvp in subs)
173 {
174 result = result.Replace(kvp.Key,kvp.Value);
175 }
176
177 return result;
178 }
179 }
180} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs
index 7422d94..9a8164c 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs
@@ -153,7 +153,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
153 { "Value", flags.ToString() } 153 { "Value", flags.ToString() }
154 }; 154 };
155 155
156 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 156 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
157 bool success = response["Success"].AsBoolean(); 157 bool success = response["Success"].AsBoolean();
158 158
159 if (!success) 159 if (!success)
@@ -180,7 +180,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
180 { "Key", friend } 180 { "Key", friend }
181 }; 181 };
182 182
183 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 183 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
184 bool success = response["Success"].AsBoolean(); 184 bool success = response["Success"].AsBoolean();
185 185
186 if (!success) 186 if (!success)
@@ -200,7 +200,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
200 { "Type", "Friend" } 200 { "Type", "Friend" }
201 }; 201 };
202 202
203 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 203 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
204 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) 204 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
205 { 205 {
206 return (OSDArray)response["Entries"]; 206 return (OSDArray)response["Entries"];
@@ -221,7 +221,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
221 { "Type", "Friend" } 221 { "Type", "Friend" }
222 }; 222 };
223 223
224 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 224 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
225 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) 225 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
226 { 226 {
227 return (OSDArray)response["Entries"]; 227 return (OSDArray)response["Entries"];
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs
index 847319c..9898da9 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs
@@ -26,8 +26,122 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
30using System.Collections.Specialized;
31using System.Reflection;
32using log4net;
29using Mono.Addins; 33using Mono.Addins;
30using Nini.Config; 34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
31 41
32[assembly: Addin("SimianGrid", "1.0")] 42[assembly: Addin("SimianGrid", "1.0")]
33[assembly: AddinDependency("OpenSim", "0.5")] 43[assembly: AddinDependency("OpenSim", "0.5")]
44
45namespace OpenSim.Services.Connectors.SimianGrid
46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianExternalCapsModule")]
48 public class SimianGrid : ISharedRegionModule
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 private IConfig m_config = null;
53
54 private String m_simianURL;
55
56#region IRegionModule Members
57
58 public string Name
59 {
60 get { return this.GetType().Name; }
61 }
62
63 public void Initialise(IConfigSource config)
64 {
65 try
66 {
67 m_config = config.Configs["SimianGrid"];
68
69 if (m_config != null)
70 {
71 m_simianURL = m_config.GetString("SimianServiceURL");
72 if (String.IsNullOrEmpty(m_simianURL))
73 {
74 // m_log.DebugFormat("[SimianGrid] service URL is not defined");
75 return;
76 }
77
78 InitialiseSimCap();
79 SimulatorCapability = SimulatorCapability.Trim();
80 m_log.InfoFormat("[SimianExternalCaps] using {0} as simulator capability",SimulatorCapability);
81 }
82 }
83 catch (Exception e)
84 {
85 m_log.ErrorFormat("[SimianExternalCaps] initialization error: {0}",e.Message);
86 return;
87 }
88 }
89
90 public void PostInitialise() { }
91 public void Close() { }
92 public void AddRegion(Scene scene) { }
93 public void RemoveRegion(Scene scene) { }
94 public void RegionLoaded(Scene scene) { }
95
96 public Type ReplaceableInterface
97 {
98 get { return null; }
99 }
100
101 ///<summary>
102 /// Try a variety of methods for finding the simian simulator capability; first check the
103 /// configuration itself, then look for a file that contains the cap, then finally look
104 /// for an environment variable that contains it.
105 ///</summary>
106 private void InitialiseSimCap()
107 {
108 if (m_config.Contains("SimulatorCapability"))
109 {
110 SimulatorCapability = m_config.GetString("SimulatorCapability");
111 return;
112 }
113
114 if (m_config.Contains("SimulatorCapabilityFile"))
115 {
116 String filename = m_config.GetString("SimulatorCapabilityFile");
117 if (System.IO.File.Exists(filename))
118 {
119 SimulatorCapability = System.IO.File.ReadAllText(filename);
120 return;
121 }
122 }
123
124 if (m_config.Contains("SimulatorCapabilityVariable"))
125 {
126 String envname = m_config.GetString("SimulatorCapabilityVariable");
127 String envvalue = System.Environment.GetEnvironmentVariable(envname);
128 if (envvalue != null)
129 {
130 SimulatorCapability = envvalue;
131 return;
132 }
133 }
134
135 m_log.WarnFormat("[SimianExternalCaps] no method specified for simulator capability");
136 }
137
138#endregion
139
140 public static String SimulatorCapability = UUID.Zero.ToString();
141 public static OSDMap PostToService(string url, NameValueCollection data)
142 {
143 data["cap"] = SimulatorCapability;
144 return WebUtil.PostToService(url, data);
145 }
146 }
147} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs
index 93fdae3..b999509 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Collections.Specialized;
30using System.Reflection; 31using System.Reflection;
31using System.Net; 32using System.Net;
32using System.IO; 33using System.IO;
@@ -43,7 +44,8 @@ using OpenSim.Region.Framework.Scenes;
43using OpenMetaverse; 44using OpenMetaverse;
44using OpenMetaverse.StructuredData; 45using OpenMetaverse.StructuredData;
45 46
46namespace OpenSim.Region.OptionalModules.Simian 47//namespace OpenSim.Region.OptionalModules.Simian
48namespace OpenSim.Services.Connectors.SimianGrid
47{ 49{
48 /// <summary> 50 /// <summary>
49 /// </summary> 51 /// </summary>
@@ -196,67 +198,84 @@ namespace OpenSim.Region.OptionalModules.Simian
196 } 198 }
197 } 199 }
198 200
199 List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>() 201 NameValueCollection requestArgs = new NameValueCollection
202 {
203 { "RequestMethod", "xAddMapTile" },
204 { "X", scene.RegionInfo.RegionLocX.ToString() },
205 { "Y", scene.RegionInfo.RegionLocY.ToString() },
206 { "ContentType", "image/png" },
207 { "EncodedData", System.Convert.ToBase64String(pngData) }
208 };
209
210 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
211 if (! response["Success"].AsBoolean())
200 { 212 {
201 new MultipartForm.Parameter("X", scene.RegionInfo.RegionLocX.ToString()), 213 m_log.WarnFormat("[SIMIAN MAPTILE] failed to store map tile; {0}",response["Message"].AsString());
202 new MultipartForm.Parameter("Y", scene.RegionInfo.RegionLocY.ToString()), 214 return;
203 new MultipartForm.File("Tile", "tile.png", "image/png", pngData) 215 }
204 };
205 216
206 string errorMessage = null; 217 // List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>()
207 int tickstart = Util.EnvironmentTickCount(); 218 // {
219 // new MultipartForm.Parameter("X", scene.RegionInfo.RegionLocX.ToString()),
220 // new MultipartForm.Parameter("Y", scene.RegionInfo.RegionLocY.ToString()),
221 // new MultipartForm.File("Tile", "tile.png", "image/png", pngData)
222 // };
208 223
209 // Make the remote storage request 224 // string errorMessage = null;
210 try 225 // int tickstart = Util.EnvironmentTickCount();
211 {
212 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl);
213 request.Timeout = 20000;
214 request.ReadWriteTimeout = 5000;
215 226
216 using (HttpWebResponse response = MultipartForm.Post(request, postParameters)) 227 // // Make the remote storage request
217 { 228 // try
218 using (Stream responseStream = response.GetResponseStream()) 229 // {
219 { 230 // HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl);
220 string responseStr = responseStream.GetStreamString(); 231 // request.Timeout = 20000;
221 OSD responseOSD = OSDParser.Deserialize(responseStr); 232 // request.ReadWriteTimeout = 5000;
222 if (responseOSD.Type == OSDType.Map)
223 {
224 OSDMap responseMap = (OSDMap)responseOSD;
225 if (responseMap["Success"].AsBoolean())
226 return;
227 233
228 errorMessage = "Upload failed: " + responseMap["Message"].AsString(); 234 // using (HttpWebResponse response = MultipartForm.Post(request, postParameters))
229 } 235 // {
230 else 236 // using (Stream responseStream = response.GetResponseStream())
231 { 237 // {
232 errorMessage = "Response format was invalid:\n" + responseStr; 238 // string responseStr = responseStream.GetStreamString();
233 } 239 // OSD responseOSD = OSDParser.Deserialize(responseStr);
234 } 240 // if (responseOSD.Type == OSDType.Map)
235 } 241 // {
236 } 242 // OSDMap responseMap = (OSDMap)responseOSD;
237 catch (WebException we) 243 // if (responseMap["Success"].AsBoolean())
238 { 244 // return;
239 errorMessage = we.Message; 245
240 if (we.Status == WebExceptionStatus.ProtocolError) 246 // errorMessage = "Upload failed: " + responseMap["Message"].AsString();
241 { 247 // }
242 HttpWebResponse webResponse = (HttpWebResponse)we.Response; 248 // else
243 errorMessage = String.Format("[{0}] {1}", 249 // {
244 webResponse.StatusCode,webResponse.StatusDescription); 250 // errorMessage = "Response format was invalid:\n" + responseStr;
245 } 251 // }
246 } 252 // }
247 catch (Exception ex) 253 // }
248 { 254 // }
249 errorMessage = ex.Message; 255 // catch (WebException we)
250 } 256 // {
251 finally 257 // errorMessage = we.Message;
252 { 258 // if (we.Status == WebExceptionStatus.ProtocolError)
253 // This just dumps a warning for any operation that takes more than 100 ms 259 // {
254 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 260 // HttpWebResponse webResponse = (HttpWebResponse)we.Response;
255 m_log.DebugFormat("[SIMIAN MAPTILE]: map tile uploaded in {0}ms",tickdiff); 261 // errorMessage = String.Format("[{0}] {1}",
256 } 262 // webResponse.StatusCode,webResponse.StatusDescription);
263 // }
264 // }
265 // catch (Exception ex)
266 // {
267 // errorMessage = ex.Message;
268 // }
269 // finally
270 // {
271 // // This just dumps a warning for any operation that takes more than 100 ms
272 // int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
273 // m_log.DebugFormat("[SIMIAN MAPTILE]: map tile uploaded in {0}ms",tickdiff);
274 // }
275
276 // m_log.WarnFormat("[SIMIAN MAPTILE]: Failed to store {0} byte tile for {1}: {2}",
277 // pngData.Length, scene.RegionInfo.RegionName, errorMessage);
257 278
258 m_log.WarnFormat("[SIMIAN MAPTILE]: Failed to store {0} byte tile for {1}: {2}",
259 pngData.Length, scene.RegionInfo.RegionName, errorMessage);
260 } 279 }
261 } 280 }
262} \ No newline at end of file 281} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
index 20eaa3a..3cf3416 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
@@ -140,7 +140,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
140 { "ExtraData", OSDParser.SerializeJsonString(extraData) } 140 { "ExtraData", OSDParser.SerializeJsonString(extraData) }
141 }; 141 };
142 142
143 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); 143 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
144 if (response["Success"].AsBoolean()) 144 if (response["Success"].AsBoolean())
145 return String.Empty; 145 return String.Empty;
146 else 146 else
@@ -156,7 +156,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
156 { "Enabled", "0" } 156 { "Enabled", "0" }
157 }; 157 };
158 158
159 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); 159 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
160 bool success = response["Success"].AsBoolean(); 160 bool success = response["Success"].AsBoolean();
161 161
162 if (!success) 162 if (!success)
@@ -203,7 +203,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
203 203
204 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request region with uuid {0}",regionID.ToString()); 204 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request region with uuid {0}",regionID.ToString());
205 205
206 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); 206 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
207 if (response["Success"].AsBoolean()) 207 if (response["Success"].AsBoolean())
208 { 208 {
209 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] uuid request successful {0}",response["Name"].AsString()); 209 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] uuid request successful {0}",response["Name"].AsString());
@@ -231,7 +231,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
231 231
232 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request grid at {0}",position.ToString()); 232 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request grid at {0}",position.ToString());
233 233
234 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); 234 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
235 if (response["Success"].AsBoolean()) 235 if (response["Success"].AsBoolean())
236 { 236 {
237 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] position request successful {0}",response["Name"].AsString()); 237 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] position request successful {0}",response["Name"].AsString());
@@ -272,7 +272,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
272 272
273 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request regions with name {0}",name); 273 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request regions with name {0}",name);
274 274
275 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); 275 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
276 if (response["Success"].AsBoolean()) 276 if (response["Success"].AsBoolean())
277 { 277 {
278 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] found regions with name {0}",name); 278 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] found regions with name {0}",name);
@@ -310,7 +310,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
310 //m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request regions by range {0} to {1}",minPosition.ToString(),maxPosition.ToString()); 310 //m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request regions by range {0} to {1}",minPosition.ToString(),maxPosition.ToString());
311 311
312 312
313 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); 313 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
314 if (response["Success"].AsBoolean()) 314 if (response["Success"].AsBoolean())
315 { 315 {
316 OSDArray array = response["Scenes"] as OSDArray; 316 OSDArray array = response["Scenes"] as OSDArray;
@@ -341,6 +341,12 @@ namespace OpenSim.Services.Connectors.SimianGrid
341 return new List<GridRegion>(0); 341 return new List<GridRegion>(0);
342 } 342 }
343 343
344 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
345 {
346 // TODO: Allow specifying the default grid location
347 return GetDefaultRegions(scopeID);
348 }
349
344 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 350 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
345 { 351 {
346 GridRegion defRegion = GetNearestRegion(new Vector3d(x, y, 0.0), true); 352 GridRegion defRegion = GetNearestRegion(new Vector3d(x, y, 0.0), true);
@@ -361,7 +367,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
361 { "Enabled", "1" } 367 { "Enabled", "1" }
362 }; 368 };
363 369
364 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); 370 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
365 if (response["Success"].AsBoolean()) 371 if (response["Success"].AsBoolean())
366 { 372 {
367 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] found regions with name {0}",name); 373 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] found regions with name {0}",name);
@@ -391,7 +397,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
391 397
392 m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request region flags for {0}",regionID.ToString()); 398 m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request region flags for {0}",regionID.ToString());
393 399
394 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); 400 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
395 if (response["Success"].AsBoolean()) 401 if (response["Success"].AsBoolean())
396 { 402 {
397 OSDMap extraData = response["ExtraData"] as OSDMap; 403 OSDMap extraData = response["ExtraData"] as OSDMap;
@@ -498,7 +504,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
498 if (onlyEnabled) 504 if (onlyEnabled)
499 requestArgs["Enabled"] = "1"; 505 requestArgs["Enabled"] = "1";
500 506
501 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs); 507 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
502 if (response["Success"].AsBoolean()) 508 if (response["Success"].AsBoolean())
503 { 509 {
504 return ResponseToGridRegion(response); 510 return ResponseToGridRegion(response);
@@ -525,9 +531,13 @@ namespace OpenSim.Services.Connectors.SimianGrid
525 region.RegionName = response["Name"].AsString(); 531 region.RegionName = response["Name"].AsString();
526 532
527 Vector3d minPosition = response["MinPosition"].AsVector3d(); 533 Vector3d minPosition = response["MinPosition"].AsVector3d();
534 Vector3d maxPosition = response["MaxPosition"].AsVector3d();
528 region.RegionLocX = (int)minPosition.X; 535 region.RegionLocX = (int)minPosition.X;
529 region.RegionLocY = (int)minPosition.Y; 536 region.RegionLocY = (int)minPosition.Y;
530 537
538 region.RegionSizeX = (int)maxPosition.X - (int)minPosition.X;
539 region.RegionSizeY = (int)maxPosition.Y - (int)minPosition.Y;
540
531 if ( ! extraData["HyperGrid"] ) { 541 if ( ! extraData["HyperGrid"] ) {
532 Uri httpAddress = response["Address"].AsUri(); 542 Uri httpAddress = response["Address"].AsUri();
533 region.ExternalHostName = httpAddress.Host; 543 region.ExternalHostName = httpAddress.Host;
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
index 36325ce..97eaabe 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
@@ -156,7 +156,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
156 { "OwnerID", userID.ToString() } 156 { "OwnerID", userID.ToString() }
157 }; 157 };
158 158
159 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 159 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
160 bool success = response["Success"].AsBoolean(); 160 bool success = response["Success"].AsBoolean();
161 161
162 if (!success) 162 if (!success)
@@ -182,7 +182,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
182 { "ChildrenOnly", "0" } 182 { "ChildrenOnly", "0" }
183 }; 183 };
184 184
185 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 185 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
186 if (response["Success"].AsBoolean() && response["Items"] is OSDArray) 186 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
187 { 187 {
188 OSDArray items = (OSDArray)response["Items"]; 188 OSDArray items = (OSDArray)response["Items"];
@@ -244,7 +244,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
244 { "ChildrenOnly", "1" } 244 { "ChildrenOnly", "1" }
245 }; 245 };
246 246
247 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 247 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
248 if (response["Success"].AsBoolean() && response["Items"] is OSDArray) 248 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
249 { 249 {
250 OSDArray items = (OSDArray)response["Items"]; 250 OSDArray items = (OSDArray)response["Items"];
@@ -274,7 +274,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
274 { "OwnerID", userID.ToString() } 274 { "OwnerID", userID.ToString() }
275 }; 275 };
276 276
277 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 277 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
278 if (response["Success"].AsBoolean() && response["Folder"] is OSDMap) 278 if (response["Success"].AsBoolean() && response["Folder"] is OSDMap)
279 { 279 {
280 OSDMap folder = (OSDMap)response["Folder"]; 280 OSDMap folder = (OSDMap)response["Folder"];
@@ -312,7 +312,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
312 { "ChildrenOnly", "1" } 312 { "ChildrenOnly", "1" }
313 }; 313 };
314 314
315 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 315 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
316 if (response["Success"].AsBoolean() && response["Items"] is OSDArray) 316 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
317 { 317 {
318 List<InventoryItemBase> items = GetItemsFromResponse((OSDArray)response["Items"]); 318 List<InventoryItemBase> items = GetItemsFromResponse((OSDArray)response["Items"]);
@@ -349,7 +349,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
349 { "ChildrenOnly", "1" } 349 { "ChildrenOnly", "1" }
350 }; 350 };
351 351
352 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 352 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
353 if (response["Success"].AsBoolean() && response["Items"] is OSDArray) 353 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
354 { 354 {
355 OSDArray items = (OSDArray)response["Items"]; 355 OSDArray items = (OSDArray)response["Items"];
@@ -383,7 +383,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
383 { "ChildrenOnly", "1" } 383 { "ChildrenOnly", "1" }
384 }; 384 };
385 385
386 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 386 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
387 if (response["Success"].AsBoolean() && response["Items"] is OSDArray) 387 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
388 { 388 {
389 OSDArray items = (OSDArray)response["Items"]; 389 OSDArray items = (OSDArray)response["Items"];
@@ -423,7 +423,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
423 { "ChildrenOnly", "1" } 423 { "ChildrenOnly", "1" }
424 }; 424 };
425 425
426 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 426 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
427 if (response["Success"].AsBoolean() && response["Items"] is OSDArray) 427 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
428 { 428 {
429 OSDArray items = (OSDArray)response["Items"]; 429 OSDArray items = (OSDArray)response["Items"];
@@ -454,7 +454,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
454 { "ContentType", SLUtil.SLAssetTypeToContentType(folder.Type) } 454 { "ContentType", SLUtil.SLAssetTypeToContentType(folder.Type) }
455 }; 455 };
456 456
457 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 457 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
458 bool success = response["Success"].AsBoolean(); 458 bool success = response["Success"].AsBoolean();
459 459
460 if (!success) 460 if (!success)
@@ -518,7 +518,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
518 { "ItemID", itemID.ToString() } 518 { "ItemID", itemID.ToString() }
519 }; 519 };
520 520
521 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 521 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
522 bool success = response["Success"].AsBoolean(); 522 bool success = response["Success"].AsBoolean();
523 523
524 if (!success) 524 if (!success)
@@ -546,7 +546,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
546 { "FolderID", folder.ID.ToString() } 546 { "FolderID", folder.ID.ToString() }
547 }; 547 };
548 548
549 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 549 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
550 bool success = response["Success"].AsBoolean(); 550 bool success = response["Success"].AsBoolean();
551 551
552 if (!success) 552 if (!success)
@@ -623,7 +623,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
623 { "ExtraData", OSDParser.SerializeJsonString(extraData) } 623 { "ExtraData", OSDParser.SerializeJsonString(extraData) }
624 }; 624 };
625 625
626 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 626 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
627 bool success = response["Success"].AsBoolean(); 627 bool success = response["Success"].AsBoolean();
628 628
629 if (!success) 629 if (!success)
@@ -847,7 +847,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
847 { "Items", String.Join(",", itemIDs) } 847 { "Items", String.Join(",", itemIDs) }
848 }; 848 };
849 849
850 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 850 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
851 bool success = response["Success"].AsBoolean(); 851 bool success = response["Success"].AsBoolean();
852 852
853 if (!success) 853 if (!success)
@@ -885,7 +885,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
885 { "UserID", userID.ToString() } 885 { "UserID", userID.ToString() }
886 }; 886 };
887 887
888 OSDMap response = WebUtil.PostToService(m_userServerUrl, requestArgs); 888 OSDMap response = SimianGrid.PostToService(m_userServerUrl, requestArgs);
889 if (response["Success"].AsBoolean()) 889 if (response["Success"].AsBoolean())
890 { 890 {
891 OSDMap user = response["User"] as OSDMap; 891 OSDMap user = response["User"] as OSDMap;
@@ -916,7 +916,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
916 { "Gestures", OSDParser.SerializeJsonString(gestures) } 916 { "Gestures", OSDParser.SerializeJsonString(gestures) }
917 }; 917 };
918 918
919 OSDMap response = WebUtil.PostToService(m_userServerUrl, requestArgs); 919 OSDMap response = SimianGrid.PostToService(m_userServerUrl, requestArgs);
920 if (!response["Success"].AsBoolean()) 920 if (!response["Success"].AsBoolean())
921 { 921 {
922 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to save active gestures for " + userID + ": " + 922 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to save active gestures for " + userID + ": " +
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
index 854bea4..211b775 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
@@ -65,7 +65,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
65 public void PostInitialise() { } 65 public void PostInitialise() { }
66 public void Close() { } 66 public void Close() { }
67 67
68 public SimianPresenceServiceConnector() { m_activityDetector = new SimianActivityDetector(this); } 68 public SimianPresenceServiceConnector() { }
69 public string Name { get { return "SimianPresenceServiceConnector"; } } 69 public string Name { get { return "SimianPresenceServiceConnector"; } }
70 public void AddRegion(Scene scene) 70 public void AddRegion(Scene scene)
71 { 71 {
@@ -121,6 +121,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
121 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) 121 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
122 serviceUrl = serviceUrl + '/'; 122 serviceUrl = serviceUrl + '/';
123 m_serverUrl = serviceUrl; 123 m_serverUrl = serviceUrl;
124 m_activityDetector = new SimianActivityDetector(this);
124 m_Enabled = true; 125 m_Enabled = true;
125 } 126 }
126 } 127 }
@@ -137,17 +138,18 @@ namespace OpenSim.Services.Connectors.SimianGrid
137 userID, sessionID, secureSessionID); 138 userID, sessionID, secureSessionID);
138 139
139 NameValueCollection requestArgs = new NameValueCollection 140 NameValueCollection requestArgs = new NameValueCollection
140 { 141 {
141 { "RequestMethod", "AddSession" }, 142 { "RequestMethod", "AddSession" },
142 { "UserID", userID.ToString() } 143 { "UserID", userID.ToString() }
143 }; 144 };
145
144 if (sessionID != UUID.Zero) 146 if (sessionID != UUID.Zero)
145 { 147 {
146 requestArgs["SessionID"] = sessionID.ToString(); 148 requestArgs["SessionID"] = sessionID.ToString();
147 requestArgs["SecureSessionID"] = secureSessionID.ToString(); 149 requestArgs["SecureSessionID"] = secureSessionID.ToString();
148 } 150 }
149 151
150 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 152 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
151 bool success = response["Success"].AsBoolean(); 153 bool success = response["Success"].AsBoolean();
152 154
153 if (!success) 155 if (!success)
@@ -158,15 +160,15 @@ namespace OpenSim.Services.Connectors.SimianGrid
158 160
159 public bool LogoutAgent(UUID sessionID) 161 public bool LogoutAgent(UUID sessionID)
160 { 162 {
161// m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for agent with sessionID " + sessionID); 163 // m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for agent with sessionID " + sessionID);
162 164
163 NameValueCollection requestArgs = new NameValueCollection 165 NameValueCollection requestArgs = new NameValueCollection
164 { 166 {
165 { "RequestMethod", "RemoveSession" }, 167 { "RequestMethod", "RemoveSession" },
166 { "SessionID", sessionID.ToString() } 168 { "SessionID", sessionID.ToString() }
167 }; 169 };
168 170
169 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 171 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
170 bool success = response["Success"].AsBoolean(); 172 bool success = response["Success"].AsBoolean();
171 173
172 if (!success) 174 if (!success)
@@ -177,15 +179,15 @@ namespace OpenSim.Services.Connectors.SimianGrid
177 179
178 public bool LogoutRegionAgents(UUID regionID) 180 public bool LogoutRegionAgents(UUID regionID)
179 { 181 {
180// m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for all agents in region " + regionID); 182 // m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for all agents in region " + regionID);
181 183
182 NameValueCollection requestArgs = new NameValueCollection 184 NameValueCollection requestArgs = new NameValueCollection
183 { 185 {
184 { "RequestMethod", "RemoveSessions" }, 186 { "RequestMethod", "RemoveSessions" },
185 { "SceneID", regionID.ToString() } 187 { "SceneID", regionID.ToString() }
186 }; 188 };
187 189
188 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 190 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
189 bool success = response["Success"].AsBoolean(); 191 bool success = response["Success"].AsBoolean();
190 192
191 if (!success) 193 if (!success)
@@ -202,49 +204,46 @@ namespace OpenSim.Services.Connectors.SimianGrid
202 204
203 public PresenceInfo GetAgent(UUID sessionID) 205 public PresenceInfo GetAgent(UUID sessionID)
204 { 206 {
205// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent with sessionID " + sessionID); 207 OSDMap sessionResponse = GetSessionDataFromSessionID(sessionID);
206 208 if (sessionResponse == null)
207 NameValueCollection requestArgs = new NameValueCollection
208 {
209 { "RequestMethod", "GetSession" },
210 { "SessionID", sessionID.ToString() }
211 };
212
213 OSDMap sessionResponse = WebUtil.PostToService(m_serverUrl, requestArgs);
214 if (sessionResponse["Success"].AsBoolean())
215 { 209 {
216 UUID userID = sessionResponse["UserID"].AsUUID(); 210 m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session {0}: {1}",sessionID.ToString(),sessionResponse["Message"].AsString());
217 m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID); 211 return null;
218
219 requestArgs = new NameValueCollection
220 {
221 { "RequestMethod", "GetUser" },
222 { "UserID", userID.ToString() }
223 };
224
225 OSDMap userResponse = WebUtil.PostToService(m_serverUrl, requestArgs);
226 if (userResponse["Success"].AsBoolean())
227 return ResponseToPresenceInfo(sessionResponse, userResponse);
228 else
229 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + userResponse["Message"].AsString());
230 } 212 }
231 else 213
214 UUID userID = sessionResponse["UserID"].AsUUID();
215 OSDMap userResponse = GetUserData(userID);
216 if (userResponse == null)
232 { 217 {
233 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session " + sessionID + ": " + sessionResponse["Message"].AsString()); 218 m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}: {1}",userID.ToString(),userResponse["Message"].AsString());
219 return null;
234 } 220 }
235 221
236 return null; 222 return ResponseToPresenceInfo(sessionResponse);
237 } 223 }
238 224
239 public PresenceInfo[] GetAgents(string[] userIDs) 225 public PresenceInfo[] GetAgents(string[] userIDs)
240 { 226 {
241 List<PresenceInfo> presences = new List<PresenceInfo>(userIDs.Length); 227 List<PresenceInfo> presences = new List<PresenceInfo>();
228
229 NameValueCollection requestArgs = new NameValueCollection
230 {
231 { "RequestMethod", "GetSessions" },
232 { "UserIDList", String.Join(",",userIDs) }
233 };
242 234
243 for (int i = 0; i < userIDs.Length; i++) 235 OSDMap sessionListResponse = SimianGrid.PostToService(m_serverUrl, requestArgs);
236 if (! sessionListResponse["Success"].AsBoolean())
244 { 237 {
245 UUID userID; 238 m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve sessions: {0}",sessionListResponse["Message"].AsString());
246 if (UUID.TryParse(userIDs[i], out userID) && userID != UUID.Zero) 239 return null;
247 presences.AddRange(GetSessions(userID)); 240 }
241
242 OSDArray sessionList = sessionListResponse["Sessions"] as OSDArray;
243 for (int i = 0; i < sessionList.Count; i++)
244 {
245 OSDMap sessionInfo = sessionList[i] as OSDMap;
246 presences.Add(ResponseToPresenceInfo(sessionInfo));
248 } 247 }
249 248
250 return presences.ToArray(); 249 return presences.ToArray();
@@ -262,7 +261,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
262 261
263 public bool LoggedOut(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) 262 public bool LoggedOut(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
264 { 263 {
265// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Logging out user " + userID); 264 // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Logging out user " + userID);
266 265
267 // Remove the session to mark this user offline 266 // Remove the session to mark this user offline
268 if (!LogoutAgent(sessionID)) 267 if (!LogoutAgent(sessionID))
@@ -270,13 +269,13 @@ namespace OpenSim.Services.Connectors.SimianGrid
270 269
271 // Save our last position as user data 270 // Save our last position as user data
272 NameValueCollection requestArgs = new NameValueCollection 271 NameValueCollection requestArgs = new NameValueCollection
273 { 272 {
274 { "RequestMethod", "AddUserData" }, 273 { "RequestMethod", "AddUserData" },
275 { "UserID", userID.ToString() }, 274 { "UserID", userID.ToString() },
276 { "LastLocation", SerializeLocation(regionID, lastPosition, lastLookAt) } 275 { "LastLocation", SerializeLocation(regionID, lastPosition, lastLookAt) }
277 }; 276 };
278 277
279 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 278 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
280 bool success = response["Success"].AsBoolean(); 279 bool success = response["Success"].AsBoolean();
281 280
282 if (!success) 281 if (!success)
@@ -287,16 +286,16 @@ namespace OpenSim.Services.Connectors.SimianGrid
287 286
288 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) 287 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
289 { 288 {
290// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Setting home location for user " + userID); 289 // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Setting home location for user " + userID);
291 290
292 NameValueCollection requestArgs = new NameValueCollection 291 NameValueCollection requestArgs = new NameValueCollection
293 { 292 {
294 { "RequestMethod", "AddUserData" }, 293 { "RequestMethod", "AddUserData" },
295 { "UserID", userID.ToString() }, 294 { "UserID", userID.ToString() },
296 { "HomeLocation", SerializeLocation(regionID, position, lookAt) } 295 { "HomeLocation", SerializeLocation(regionID, position, lookAt) }
297 }; 296 };
298 297
299 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 298 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
300 bool success = response["Success"].AsBoolean(); 299 bool success = response["Success"].AsBoolean();
301 300
302 if (!success) 301 if (!success)
@@ -312,24 +311,19 @@ namespace OpenSim.Services.Connectors.SimianGrid
312 311
313 public GridUserInfo GetGridUserInfo(string user) 312 public GridUserInfo GetGridUserInfo(string user)
314 { 313 {
315// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent " + user); 314 // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent " + user);
316 315
317 UUID userID = new UUID(user); 316 UUID userID = new UUID(user);
318// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID); 317 OSDMap userResponse = GetUserData(userID);
319 318
320 NameValueCollection requestArgs = new NameValueCollection 319 if (userResponse == null)
321 { 320 {
322 { "RequestMethod", "GetUser" }, 321 m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}", userID);
323 { "UserID", userID.ToString() } 322 }
324 };
325 323
326 OSDMap userResponse = WebUtil.PostToService(m_serverUrl, requestArgs); 324 // Note that ResponseToGridUserInfo properly checks for and returns a null if passed a null.
327 if (userResponse["Success"].AsBoolean()) 325 return ResponseToGridUserInfo(userResponse);
328 return ResponseToGridUserInfo(userResponse);
329 else
330 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + userResponse["Message"].AsString());
331 326
332 return null;
333 } 327 }
334 328
335 #endregion 329 #endregion
@@ -338,67 +332,51 @@ namespace OpenSim.Services.Connectors.SimianGrid
338 332
339 private OSDMap GetUserData(UUID userID) 333 private OSDMap GetUserData(UUID userID)
340 { 334 {
341// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID); 335 // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID);
342 336
343 NameValueCollection requestArgs = new NameValueCollection 337 NameValueCollection requestArgs = new NameValueCollection
344 { 338 {
345 { "RequestMethod", "GetUser" }, 339 { "RequestMethod", "GetUser" },
346 { "UserID", userID.ToString() } 340 { "UserID", userID.ToString() }
347 }; 341 };
348 342
349 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 343 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
350 if (response["Success"].AsBoolean() && response["User"] is OSDMap) 344 if (response["Success"].AsBoolean() && response["User"] is OSDMap)
351 return response; 345 return response;
352 else
353 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + response["Message"].AsString());
354 346
347 m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}; {1}",userID.ToString(),response["Message"].AsString());
355 return null; 348 return null;
356 } 349 }
357 350
358 private List<PresenceInfo> GetSessions(UUID userID) 351 private OSDMap GetSessionDataFromSessionID(UUID sessionID)
359 { 352 {
360 List<PresenceInfo> presences = new List<PresenceInfo>(1); 353 NameValueCollection requestArgs = new NameValueCollection
361
362 OSDMap userResponse = GetUserData(userID);
363 if (userResponse != null)
364 {
365// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting sessions for " + userID);
366
367 NameValueCollection requestArgs = new NameValueCollection
368 { 354 {
369 { "RequestMethod", "GetSession" }, 355 { "RequestMethod", "GetSession" },
370 { "UserID", userID.ToString() } 356 { "SessionID", sessionID.ToString() }
371 }; 357 };
372 358
373 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 359 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
374 if (response["Success"].AsBoolean()) 360 if (response["Success"].AsBoolean())
375 { 361 return response;
376 PresenceInfo presence = ResponseToPresenceInfo(response, userResponse);
377 if (presence != null)
378 presences.Add(presence);
379 }
380// else
381// {
382// m_log.Debug("[SIMIAN PRESENCE CONNECTOR]: No session returned for " + userID + ": " + response["Message"].AsString());
383// }
384 }
385 362
386 return presences; 363 m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session data for {0}; {1}",sessionID.ToString(),response["Message"].AsString());
364 return null;
387 } 365 }
388 366
389 private bool UpdateSession(UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) 367 private bool UpdateSession(UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
390 { 368 {
391 // Save our current location as session data 369 // Save our current location as session data
392 NameValueCollection requestArgs = new NameValueCollection 370 NameValueCollection requestArgs = new NameValueCollection
393 { 371 {
394 { "RequestMethod", "UpdateSession" }, 372 { "RequestMethod", "UpdateSession" },
395 { "SessionID", sessionID.ToString() }, 373 { "SessionID", sessionID.ToString() },
396 { "SceneID", regionID.ToString() }, 374 { "SceneID", regionID.ToString() },
397 { "ScenePosition", lastPosition.ToString() }, 375 { "ScenePosition", lastPosition.ToString() },
398 { "SceneLookAt", lastLookAt.ToString() } 376 { "SceneLookAt", lastLookAt.ToString() }
399 }; 377 };
400 378
401 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 379 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
402 bool success = response["Success"].AsBoolean(); 380 bool success = response["Success"].AsBoolean();
403 381
404 if (!success) 382 if (!success)
@@ -407,7 +385,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
407 return success; 385 return success;
408 } 386 }
409 387
410 private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse, OSDMap userResponse) 388 private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse)
411 { 389 {
412 if (sessionResponse == null) 390 if (sessionResponse == null)
413 return null; 391 return null;
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs
index bd8069f..684a0db 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs
@@ -392,7 +392,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
392 { "UserID", client.AgentId.ToString() } 392 { "UserID", client.AgentId.ToString() }
393 }; 393 };
394 394
395 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 395 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
396 string email = response["Email"].AsString(); 396 string email = response["Email"].AsString();
397 397
398 if (!response["Success"].AsBoolean()) 398 if (!response["Success"].AsBoolean())
@@ -443,7 +443,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
443 { key, OSDParser.SerializeJsonString(value) } 443 { key, OSDParser.SerializeJsonString(value) }
444 }; 444 };
445 445
446 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 446 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
447 bool success = response["Success"].AsBoolean(); 447 bool success = response["Success"].AsBoolean();
448 448
449 if (!success) 449 if (!success)
@@ -462,7 +462,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
462 { "UserID", userID.ToString() } 462 { "UserID", userID.ToString() }
463 }; 463 };
464 464
465 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 465 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
466 if (response["Success"].AsBoolean() && response["User"] is OSDMap) 466 if (response["Success"].AsBoolean() && response["User"] is OSDMap)
467 { 467 {
468 return (OSDMap)response["User"]; 468 return (OSDMap)response["User"];
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
index fcb5115..fdc8697 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
@@ -165,7 +165,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
165 { "NameQuery", query } 165 { "NameQuery", query }
166 }; 166 };
167 167
168 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 168 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
169 if (response["Success"].AsBoolean()) 169 if (response["Success"].AsBoolean())
170 { 170 {
171 OSDArray array = response["Users"] as OSDArray; 171 OSDArray array = response["Users"] as OSDArray;
@@ -209,7 +209,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
209 { "AccessLevel", data.UserLevel.ToString() } 209 { "AccessLevel", data.UserLevel.ToString() }
210 }; 210 };
211 211
212 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 212 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
213 213
214 if (response["Success"].AsBoolean()) 214 if (response["Success"].AsBoolean())
215 { 215 {
@@ -224,7 +224,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
224 { "UserTitle", data.UserTitle } 224 { "UserTitle", data.UserTitle }
225 }; 225 };
226 226
227 response = WebUtil.PostToService(m_serverUrl, requestArgs); 227 response = SimianGrid.PostToService(m_serverUrl, requestArgs);
228 bool success = response["Success"].AsBoolean(); 228 bool success = response["Success"].AsBoolean();
229 229
230 if (success) 230 if (success)
@@ -257,7 +257,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
257 string lookupValue = (requestArgs.Count > 1) ? requestArgs[1] : "(Unknown)"; 257 string lookupValue = (requestArgs.Count > 1) ? requestArgs[1] : "(Unknown)";
258// m_log.DebugFormat("[SIMIAN ACCOUNT CONNECTOR]: Looking up user account with query: " + lookupValue); 258// m_log.DebugFormat("[SIMIAN ACCOUNT CONNECTOR]: Looking up user account with query: " + lookupValue);
259 259
260 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); 260 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
261 if (response["Success"].AsBoolean()) 261 if (response["Success"].AsBoolean())
262 { 262 {
263 OSDMap user = response["User"] as OSDMap; 263 OSDMap user = response["User"] as OSDMap;
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
index ef2494a..0e74073 100644
--- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -79,11 +79,27 @@ namespace OpenSim.Services.Connectors.Simulation
79 return "agent/"; 79 return "agent/";
80 } 80 }
81 81
82 protected virtual void PackData(OSDMap args, AgentCircuitData aCircuit, GridRegion destination, uint flags)
83 {
84 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
85 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
86 args["destination_name"] = OSD.FromString(destination.RegionName);
87 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
88 args["teleport_flags"] = OSD.FromString(flags.ToString());
89 }
90
82 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason) 91 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason)
83 { 92 {
84 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CreateAgent start"); 93 string tmp = String.Empty;
85 94 return CreateAgent(destination, aCircuit, flags, out tmp, out reason);
95 }
96
97 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason)
98 {
99 m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: Creating agent at {0}", destination.ServerURI);
86 reason = String.Empty; 100 reason = String.Empty;
101 myipaddress = String.Empty;
102
87 if (destination == null) 103 if (destination == null)
88 { 104 {
89 reason = "Destination not found"; 105 reason = "Destination not found";
@@ -96,12 +112,7 @@ namespace OpenSim.Services.Connectors.Simulation
96 try 112 try
97 { 113 {
98 OSDMap args = aCircuit.PackAgentCircuitData(); 114 OSDMap args = aCircuit.PackAgentCircuitData();
99 115 PackData(args, aCircuit, destination, flags);
100 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
101 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
102 args["destination_name"] = OSD.FromString(destination.RegionName);
103 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
104 args["teleport_flags"] = OSD.FromString(flags.ToString());
105 116
106 OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000); 117 OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000);
107 bool success = result["success"].AsBoolean(); 118 bool success = result["success"].AsBoolean();
@@ -111,6 +122,7 @@ namespace OpenSim.Services.Connectors.Simulation
111 122
112 reason = data["reason"].AsString(); 123 reason = data["reason"].AsString();
113 success = data["success"].AsBoolean(); 124 success = data["success"].AsBoolean();
125 myipaddress = data["your_ip"].AsString();
114 return success; 126 return success;
115 } 127 }
116 128
@@ -125,6 +137,7 @@ namespace OpenSim.Services.Connectors.Simulation
125 137
126 reason = data["reason"].AsString(); 138 reason = data["reason"].AsString();
127 success = data["success"].AsBoolean(); 139 success = data["success"].AsBoolean();
140 myipaddress = data["your_ip"].AsString();
128 m_log.WarnFormat( 141 m_log.WarnFormat(
129 "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName); 142 "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName);
130 return success; 143 return success;
@@ -229,7 +242,7 @@ namespace OpenSim.Services.Connectors.Simulation
229 /// </summary> 242 /// </summary>
230 private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout) 243 private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout)
231 { 244 {
232 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent start"); 245 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent in {0}", destination.ServerURI);
233 246
234 // Eventually, we want to use a caps url instead of the agentID 247 // Eventually, we want to use a caps url instead of the agentID
235 string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/"; 248 string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/";
@@ -259,41 +272,6 @@ namespace OpenSim.Services.Connectors.Simulation
259 return false; 272 return false;
260 } 273 }
261 274
262 /// <summary>
263 /// Not sure what sequence causes this function to be invoked. The only calling
264 /// path is through the GET method
265 /// </summary>
266 public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent)
267 {
268 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: RetrieveAgent start");
269
270 agent = null;
271
272 // Eventually, we want to use a caps url instead of the agentID
273 string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/";
274
275 try
276 {
277 OSDMap result = WebUtil.GetFromService(uri, 10000);
278 if (result["Success"].AsBoolean())
279 {
280 // OSDMap args = Util.GetOSDMap(result["_RawResult"].AsString());
281 OSDMap args = (OSDMap)result["_Result"];
282 if (args != null)
283 {
284 agent = new CompleteAgentData();
285 agent.Unpack(args, null);
286 return true;
287 }
288 }
289 }
290 catch (Exception e)
291 {
292 m_log.Warn("[REMOTE SIMULATION CONNECTOR]: UpdateAgent failed with exception: " + e.ToString());
293 }
294
295 return false;
296 }
297 275
298 /// <summary> 276 /// <summary>
299 /// </summary> 277 /// </summary>
@@ -392,35 +370,25 @@ namespace OpenSim.Services.Connectors.Simulation
392 return true; 370 return true;
393 } 371 }
394 372
395 private bool CloseAgent(GridRegion destination, UUID id, bool ChildOnly) 373 /// <summary>
374 /// </summary>
375 public bool CloseAgent(GridRegion destination, UUID id, string auth_code)
396 { 376 {
397// m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CloseAgent start"); 377 string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/?auth=" + auth_code;
398 Util.FireAndForget(x => { 378 m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CloseAgent {0}", uri);
399 string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/";
400 379
401 try 380 try
402 { 381 {
403 WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000, false); 382 WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000, false);
404 } 383 }
405 catch (Exception e) 384 catch (Exception e)
406 { 385 {
407 m_log.WarnFormat("[REMOTE SIMULATION CONNECTOR] CloseAgent failed with exception; {0}",e.ToString()); 386 m_log.WarnFormat("[REMOTE SIMULATION CONNECTOR] CloseAgent failed with exception; {0}",e.ToString());
408 } 387 }
409 });
410 388
411 return true; 389 return true;
412 } 390 }
413 391
414 public bool CloseChildAgent(GridRegion destination, UUID id)
415 {
416 return CloseAgent(destination, id, true);
417 }
418
419 public bool CloseAgent(GridRegion destination, UUID id)
420 {
421 return CloseAgent(destination, id, false);
422 }
423
424 #endregion Agents 392 #endregion Agents
425 393
426 #region Objects 394 #region Objects
diff --git a/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs b/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs
index b488b36..6bc543a 100644
--- a/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/FreeswitchService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/Friends/Properties/AssemblyInfo.cs b/OpenSim/Services/Friends/Properties/AssemblyInfo.cs
index b11d07d..f9473e2 100644
--- a/OpenSim/Services/Friends/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Friends/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs
index 7f71835..76415ce 100644
--- a/OpenSim/Services/GridService/GridService.cs
+++ b/OpenSim/Services/GridService/GridService.cs
@@ -86,7 +86,7 @@ namespace OpenSim.Services.GridService
86 { 86 {
87 MainConsole.Instance.Commands.AddCommand("Regions", true, 87 MainConsole.Instance.Commands.AddCommand("Regions", true,
88 "deregister region id", 88 "deregister region id",
89 "deregister region id <Region UUID>", 89 "deregister region id <region-id>+",
90 "Deregister a region manually.", 90 "Deregister a region manually.",
91 String.Empty, 91 String.Empty,
92 HandleDeregisterRegion); 92 HandleDeregisterRegion);
@@ -265,8 +265,9 @@ namespace OpenSim.Services.GridService
265 m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e); 265 m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e);
266 } 266 }
267 267
268 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) registered successfully at {2}-{3}", 268 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) registered successfully at {2}-{3} with flags {4}",
269 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionCoordX, regionInfos.RegionCoordY); 269 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionCoordX, regionInfos.RegionCoordY,
270 (OpenSim.Framework.RegionFlags)flags);
270 271
271 return String.Empty; 272 return String.Empty;
272 } 273 }
@@ -311,8 +312,9 @@ namespace OpenSim.Services.GridService
311 if (region != null) 312 if (region != null)
312 { 313 {
313 // Not really? Maybe? 314 // Not really? Maybe?
314 List<RegionData> rdatas = m_Database.Get(region.posX - (int)Constants.RegionSize - 1, region.posY - (int)Constants.RegionSize - 1, 315 List<RegionData> rdatas = m_Database.Get(
315 region.posX + (int)Constants.RegionSize + 1, region.posY + (int)Constants.RegionSize + 1, scopeID); 316 region.posX - region.sizeX - 1, region.posY - region.sizeY - 1,
317 region.posX + region.sizeX + 1, region.posY + region.sizeY + 1, scopeID);
316 318
317 foreach (RegionData rdata in rdatas) 319 foreach (RegionData rdata in rdatas)
318 { 320 {
@@ -345,6 +347,11 @@ namespace OpenSim.Services.GridService
345 return null; 347 return null;
346 } 348 }
347 349
350 // Get a region given its base coordinates.
351 // NOTE: this is NOT 'get a region by some point in the region'. The coordinate MUST
352 // be the base coordinate of the region.
353 // The snapping is technically unnecessary but is harmless because regions are always
354 // multiples of the legacy region size (256).
348 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y) 355 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
349 { 356 {
350 int snapX = (int)(x / Constants.RegionSize) * (int)Constants.RegionSize; 357 int snapX = (int)(x / Constants.RegionSize) * (int)Constants.RegionSize;
@@ -439,6 +446,8 @@ namespace OpenSim.Services.GridService
439 RegionData rdata = new RegionData(); 446 RegionData rdata = new RegionData();
440 rdata.posX = (int)rinfo.RegionLocX; 447 rdata.posX = (int)rinfo.RegionLocX;
441 rdata.posY = (int)rinfo.RegionLocY; 448 rdata.posY = (int)rinfo.RegionLocY;
449 rdata.sizeX = rinfo.RegionSizeX;
450 rdata.sizeY = rinfo.RegionSizeY;
442 rdata.RegionID = rinfo.RegionID; 451 rdata.RegionID = rinfo.RegionID;
443 rdata.RegionName = rinfo.RegionName; 452 rdata.RegionName = rinfo.RegionName;
444 rdata.Data = rinfo.ToKeyValuePairs(); 453 rdata.Data = rinfo.ToKeyValuePairs();
@@ -452,6 +461,8 @@ namespace OpenSim.Services.GridService
452 GridRegion rinfo = new GridRegion(rdata.Data); 461 GridRegion rinfo = new GridRegion(rdata.Data);
453 rinfo.RegionLocX = rdata.posX; 462 rinfo.RegionLocX = rdata.posX;
454 rinfo.RegionLocY = rdata.posY; 463 rinfo.RegionLocY = rdata.posY;
464 rinfo.RegionSizeX = rdata.sizeX;
465 rinfo.RegionSizeY = rdata.sizeY;
455 rinfo.RegionID = rdata.RegionID; 466 rinfo.RegionID = rdata.RegionID;
456 rinfo.RegionName = rdata.RegionName; 467 rinfo.RegionName = rdata.RegionName;
457 rinfo.ScopeID = rdata.ScopeID; 468 rinfo.ScopeID = rdata.ScopeID;
@@ -477,6 +488,33 @@ namespace OpenSim.Services.GridService
477 return ret; 488 return ret;
478 } 489 }
479 490
491 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
492 {
493 List<GridRegion> ret = new List<GridRegion>();
494
495 List<RegionData> regions = m_Database.GetDefaultHypergridRegions(scopeID);
496
497 foreach (RegionData r in regions)
498 {
499 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
500 ret.Add(RegionData2RegionInfo(r));
501 }
502
503 int hgDefaultRegionsFoundOnline = regions.Count;
504
505 // For now, hypergrid default regions will always be given precedence but we will also return simple default
506 // regions in case no specific hypergrid regions are specified.
507 ret.AddRange(GetDefaultRegions(scopeID));
508
509 int normalDefaultRegionsFoundOnline = ret.Count - hgDefaultRegionsFoundOnline;
510
511 m_log.DebugFormat(
512 "[GRID SERVICE]: GetDefaultHypergridRegions returning {0} hypergrid default and {1} normal default regions",
513 hgDefaultRegionsFoundOnline, normalDefaultRegionsFoundOnline);
514
515 return ret;
516 }
517
480 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y) 518 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
481 { 519 {
482 List<GridRegion> ret = new List<GridRegion>(); 520 List<GridRegion> ret = new List<GridRegion>();
@@ -525,40 +563,41 @@ namespace OpenSim.Services.GridService
525 563
526 private void HandleDeregisterRegion(string module, string[] cmd) 564 private void HandleDeregisterRegion(string module, string[] cmd)
527 { 565 {
528 if (cmd.Length != 4) 566 if (cmd.Length < 4)
529 { 567 {
530 MainConsole.Instance.Output("Syntax: degregister region id <Region UUID>"); 568 MainConsole.Instance.Output("Usage: degregister region id <region-id>+");
531 return; 569 return;
532 } 570 }
533 571
534 string rawRegionUuid = cmd[3]; 572 for (int i = 3; i < cmd.Length; i++)
535 UUID regionUuid;
536
537 if (!UUID.TryParse(rawRegionUuid, out regionUuid))
538 { 573 {
539 MainConsole.Instance.OutputFormat("{0} is not a valid region uuid", rawRegionUuid); 574 string rawRegionUuid = cmd[i];
540 return; 575 UUID regionUuid;
541 }
542 576
543 GridRegion region = GetRegionByUUID(UUID.Zero, regionUuid); 577 if (!UUID.TryParse(rawRegionUuid, out regionUuid))
578 {
579 MainConsole.Instance.OutputFormat("{0} is not a valid region uuid", rawRegionUuid);
580 return;
581 }
544 582
545 if (region == null) 583 GridRegion region = GetRegionByUUID(UUID.Zero, regionUuid);
546 {
547 MainConsole.Instance.OutputFormat("No region with UUID {0}", regionUuid);
548 return;
549 }
550 584
551 if (DeregisterRegion(regionUuid)) 585 if (region == null)
552 { 586 {
553 MainConsole.Instance.OutputFormat("Deregistered {0} {1}", region.RegionName, regionUuid); 587 MainConsole.Instance.OutputFormat("No region with UUID {0}", regionUuid);
554 } 588 return;
555 else 589 }
556 {
557 // I don't think this can ever occur if we know that the region exists.
558 MainConsole.Instance.OutputFormat("Error deregistering {0} {1}", region.RegionName, regionUuid);
559 }
560 590
561 return; 591 if (DeregisterRegion(regionUuid))
592 {
593 MainConsole.Instance.OutputFormat("Deregistered {0} {1}", region.RegionName, regionUuid);
594 }
595 else
596 {
597 // I don't think this can ever occur if we know that the region exists.
598 MainConsole.Instance.OutputFormat("Error deregistering {0} {1}", region.RegionName, regionUuid);
599 }
600 }
562 } 601 }
563 602
564 private void HandleShowRegions(string module, string[] cmd) 603 private void HandleShowRegions(string module, string[] cmd)
diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs
index 8335724..4024295 100644
--- a/OpenSim/Services/GridService/HypergridLinker.cs
+++ b/OpenSim/Services/GridService/HypergridLinker.cs
@@ -79,7 +79,7 @@ namespace OpenSim.Services.GridService
79 { 79 {
80 if (m_DefaultRegion == null) 80 if (m_DefaultRegion == null)
81 { 81 {
82 List<GridRegion> defs = m_GridService.GetDefaultRegions(m_ScopeID); 82 List<GridRegion> defs = m_GridService.GetDefaultHypergridRegions(m_ScopeID);
83 if (defs != null && defs.Count > 0) 83 if (defs != null && defs.Count > 0)
84 m_DefaultRegion = defs[0]; 84 m_DefaultRegion = defs[0];
85 else 85 else
diff --git a/OpenSim/Services/GridService/Properties/AssemblyInfo.cs b/OpenSim/Services/GridService/Properties/AssemblyInfo.cs
index b1e5e12..bd84123 100644
--- a/OpenSim/Services/GridService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/GridService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs
index 97a0afc..f6136b5 100644
--- a/OpenSim/Services/HypergridService/GatekeeperService.cs
+++ b/OpenSim/Services/HypergridService/GatekeeperService.cs
@@ -58,6 +58,7 @@ namespace OpenSim.Services.HypergridService
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 private static IGridUserService m_GridUserService;
61 private static IBansService m_BansService;
61 62
62 private static string m_AllowedClients = string.Empty; 63 private static string m_AllowedClients = string.Empty;
63 private static string m_DeniedClients = string.Empty; 64 private static string m_DeniedClients = string.Empty;
@@ -87,6 +88,7 @@ namespace OpenSim.Services.HypergridService
87 string presenceService = serverConfig.GetString("PresenceService", String.Empty); 88 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
88 string simulationService = serverConfig.GetString("SimulationService", String.Empty); 89 string simulationService = serverConfig.GetString("SimulationService", String.Empty);
89 string gridUserService = serverConfig.GetString("GridUserService", String.Empty); 90 string gridUserService = serverConfig.GetString("GridUserService", String.Empty);
91 string bansService = serverConfig.GetString("BansService", String.Empty);
90 92
91 // These are mandatory, the others aren't 93 // These are mandatory, the others aren't
92 if (gridService == string.Empty || presenceService == string.Empty) 94 if (gridService == string.Empty || presenceService == string.Empty)
@@ -121,6 +123,8 @@ namespace OpenSim.Services.HypergridService
121 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(homeUsersService, args); 123 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(homeUsersService, args);
122 if (gridUserService != string.Empty) 124 if (gridUserService != string.Empty)
123 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args); 125 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args);
126 if (bansService != string.Empty)
127 m_BansService = ServerUtils.LoadPlugin<IBansService>(bansService, args);
124 128
125 if (simService != null) 129 if (simService != null)
126 m_SimulationService = simService; 130 m_SimulationService = simService;
@@ -167,7 +171,7 @@ namespace OpenSim.Services.HypergridService
167 m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to link to {0}", (regionName == string.Empty)? "default region" : regionName); 171 m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to link to {0}", (regionName == string.Empty)? "default region" : regionName);
168 if (!m_AllowTeleportsToAnyRegion || regionName == string.Empty) 172 if (!m_AllowTeleportsToAnyRegion || regionName == string.Empty)
169 { 173 {
170 List<GridRegion> defs = m_GridService.GetDefaultRegions(m_ScopeID); 174 List<GridRegion> defs = m_GridService.GetDefaultHypergridRegions(m_ScopeID);
171 if (defs != null && defs.Count > 0) 175 if (defs != null && defs.Count > 0)
172 { 176 {
173 region = defs[0]; 177 region = defs[0];
@@ -223,7 +227,7 @@ namespace OpenSim.Services.HypergridService
223 m_log.InfoFormat("[GATEKEEPER SERVICE]: Login request for {0} {1} @ {2} ({3}) at {4} using viewer {5}, channel {6}, IP {7}, Mac {8}, Id0 {9} Teleport Flags {10}", 227 m_log.InfoFormat("[GATEKEEPER SERVICE]: Login request for {0} {1} @ {2} ({3}) at {4} using viewer {5}, channel {6}, IP {7}, Mac {8}, Id0 {9} Teleport Flags {10}",
224 aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName, 228 aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName,
225 aCircuit.Viewer, aCircuit.Channel, aCircuit.IPAddress, aCircuit.Mac, aCircuit.Id0, aCircuit.teleportFlags.ToString()); 229 aCircuit.Viewer, aCircuit.Channel, aCircuit.IPAddress, aCircuit.Mac, aCircuit.Id0, aCircuit.teleportFlags.ToString());
226 230
227 // 231 //
228 // Check client 232 // Check client
229 // 233 //
@@ -287,17 +291,16 @@ namespace OpenSim.Services.HypergridService
287 } 291 }
288 } 292 }
289 } 293 }
290 m_log.DebugFormat("[GATEKEEPER SERVICE]: User is ok");
291 294
292 // 295 //
293 // Foreign agents allowed? Exceptions? 296 // Foreign agents allowed? Exceptions?
294 // 297 //
295 if (account == null) 298 if (account == null)
296 { 299 {
297 bool allowed = m_ForeignAgentsAllowed; 300 bool allowed = m_ForeignAgentsAllowed;
298 301
299 if (m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsAllowedExceptions)) 302 if (m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsAllowedExceptions))
300 allowed = false; 303 allowed = false;
301 304
302 if (!m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsDisallowedExceptions)) 305 if (!m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsDisallowedExceptions))
303 allowed = true; 306 allowed = true;
@@ -311,6 +314,20 @@ namespace OpenSim.Services.HypergridService
311 } 314 }
312 } 315 }
313 316
317 //
318 // Is the user banned?
319 // This uses a Ban service that's more powerful than the configs
320 //
321 string uui = (account != null ? aCircuit.AgentID.ToString() : Util.ProduceUserUniversalIdentifier(aCircuit));
322 if (m_BansService != null && m_BansService.IsBanned(uui, aCircuit.IPAddress, aCircuit.Id0, authURL))
323 {
324 reason = "You are banned from this world";
325 m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: user {0} is banned", uui);
326 return false;
327 }
328
329 m_log.DebugFormat("[GATEKEEPER SERVICE]: User {0} is ok", aCircuit.Name);
330
314 bool isFirstLogin = false; 331 bool isFirstLogin = false;
315 // 332 //
316 // Login the presence, if it's not there yet (by the login service) 333 // Login the presence, if it's not there yet (by the login service)
@@ -328,7 +345,8 @@ namespace OpenSim.Services.HypergridService
328 aCircuit.firstname, aCircuit.lastname); 345 aCircuit.firstname, aCircuit.lastname);
329 return false; 346 return false;
330 } 347 }
331 m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence ok"); 348
349 m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence {0} is ok", aCircuit.Name);
332 350
333 // Also login foreigners with GridUser service 351 // Also login foreigners with GridUser service
334 if (m_GridUserService != null && account == null) 352 if (m_GridUserService != null && account == null)
@@ -359,7 +377,9 @@ namespace OpenSim.Services.HypergridService
359 reason = "Destination region not found"; 377 reason = "Destination region not found";
360 return false; 378 return false;
361 } 379 }
362 m_log.DebugFormat("[GATEKEEPER SERVICE]: destination ok: {0}", destination.RegionName); 380
381 m_log.DebugFormat(
382 "[GATEKEEPER SERVICE]: Destination {0} is ok for {1}", destination.RegionName, aCircuit.Name);
363 383
364 // 384 //
365 // Adjust the visible name 385 // Adjust the visible name
@@ -393,7 +413,8 @@ namespace OpenSim.Services.HypergridService
393 // Preserve our TeleportFlags we have gathered so-far 413 // Preserve our TeleportFlags we have gathered so-far
394 loginFlag |= (Constants.TeleportFlags) aCircuit.teleportFlags; 414 loginFlag |= (Constants.TeleportFlags) aCircuit.teleportFlags;
395 415
396 m_log.DebugFormat("[GATEKEEPER SERVICE]: launching agent {0}", loginFlag); 416 m_log.DebugFormat("[GATEKEEPER SERVICE]: Launching {0} {1}", aCircuit.Name, loginFlag);
417
397 return m_SimulationService.CreateAgent(destination, aCircuit, (uint)loginFlag, out reason); 418 return m_SimulationService.CreateAgent(destination, aCircuit, (uint)loginFlag, out reason);
398 } 419 }
399 420
@@ -402,6 +423,12 @@ namespace OpenSim.Services.HypergridService
402 if (!CheckAddress(aCircuit.ServiceSessionID)) 423 if (!CheckAddress(aCircuit.ServiceSessionID))
403 return false; 424 return false;
404 425
426 if (string.IsNullOrEmpty(aCircuit.IPAddress))
427 {
428 m_log.DebugFormat("[GATEKEEPER SERVICE]: Agent did not provide a client IP address.");
429 return false;
430 }
431
405 string userURL = string.Empty; 432 string userURL = string.Empty;
406 if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) 433 if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
407 userURL = aCircuit.ServiceURLs["HomeURI"].ToString(); 434 userURL = aCircuit.ServiceURLs["HomeURI"].ToString();
diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs
index 326e68d..3233caf 100644
--- a/OpenSim/Services/HypergridService/HGInventoryService.cs
+++ b/OpenSim/Services/HypergridService/HGInventoryService.cs
@@ -298,7 +298,7 @@ namespace OpenSim.Services.HypergridService
298 UserAccount user = m_Cache.GetUser(it.CreatorId); 298 UserAccount user = m_Cache.GetUser(it.CreatorId);
299 299
300 // Adjust the creator data 300 // Adjust the creator data
301 if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty)) 301 if (user != null && it != null && string.IsNullOrEmpty(it.CreatorData))
302 it.CreatorData = m_HomeURL + ";" + user.FirstName + " " + user.LastName; 302 it.CreatorData = m_HomeURL + ";" + user.FirstName + " " + user.LastName;
303 } 303 }
304 return it; 304 return it;
diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
index eecf757..835cde3 100644
--- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
+++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
@@ -54,7 +54,7 @@ namespace OpenSim.Services.HypergridService
54 LogManager.GetLogger( 54 LogManager.GetLogger(
55 MethodBase.GetCurrentMethod().DeclaringType); 55 MethodBase.GetCurrentMethod().DeclaringType);
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 private IAvatarService m_AvatarService;
60 60
@@ -96,8 +96,8 @@ namespace OpenSim.Services.HypergridService
96 if (m_AvatarService == null) 96 if (m_AvatarService == null)
97 throw new Exception(String.Format("Unable to create m_AvatarService from {0}", avatarDll)); 97 throw new Exception(String.Format("Unable to create m_AvatarService from {0}", avatarDll));
98 98
99 m_HomeURL = Util.GetConfigVarFromSections<string>(config, "HomeURI", 99// m_HomeURL = Util.GetConfigVarFromSections<string>(config, "HomeURI",
100 new string[] { "Startup", "Hypergrid", m_ConfigName }, String.Empty); 100// new string[] { "Startup", "Hypergrid", m_ConfigName }, String.Empty);
101 101
102// m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); 102// m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService);
103 } 103 }
@@ -115,6 +115,12 @@ namespace OpenSim.Services.HypergridService
115 { 115 {
116 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); 116 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
117 117
118 if (suitcase == null)
119 {
120 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no suitcase folder for user {0} when looking for inventory skeleton", principalID);
121 return null;
122 }
123
118 List<XInventoryFolder> tree = GetFolderTree(principalID, suitcase.folderID); 124 List<XInventoryFolder> tree = GetFolderTree(principalID, suitcase.folderID);
119 if (tree == null || (tree != null && tree.Count == 0)) 125 if (tree == null || (tree != null && tree.Count == 0))
120 return null; 126 return null;
@@ -134,6 +140,7 @@ namespace OpenSim.Services.HypergridService
134 public override InventoryCollection GetUserInventory(UUID userID) 140 public override InventoryCollection GetUserInventory(UUID userID)
135 { 141 {
136 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Get Suitcase inventory for user {0}", userID); 142 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Get Suitcase inventory for user {0}", userID);
143
137 InventoryCollection userInventory = new InventoryCollection(); 144 InventoryCollection userInventory = new InventoryCollection();
138 userInventory.UserID = userID; 145 userInventory.UserID = userID;
139 userInventory.Folders = new List<InventoryFolderBase>(); 146 userInventory.Folders = new List<InventoryFolderBase>();
@@ -141,6 +148,12 @@ namespace OpenSim.Services.HypergridService
141 148
142 XInventoryFolder suitcase = GetSuitcaseXFolder(userID); 149 XInventoryFolder suitcase = GetSuitcaseXFolder(userID);
143 150
151 if (suitcase == null)
152 {
153 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no suitcase folder for user {0} when looking for user inventory", userID);
154 return null;
155 }
156
144 List<XInventoryFolder> tree = GetFolderTree(userID, suitcase.folderID); 157 List<XInventoryFolder> tree = GetFolderTree(userID, suitcase.folderID);
145 if (tree == null || (tree != null && tree.Count == 0)) 158 if (tree == null || (tree != null && tree.Count == 0))
146 { 159 {
@@ -182,7 +195,8 @@ namespace OpenSim.Services.HypergridService
182 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetRootFolder for {0}", principalID); 195 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetRootFolder for {0}", principalID);
183 196
184 // Let's find out the local root folder 197 // Let's find out the local root folder
185 XInventoryFolder root = GetRootXFolder(principalID); ; 198 XInventoryFolder root = GetRootXFolder(principalID);
199
186 if (root == null) 200 if (root == null)
187 { 201 {
188 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve local root folder for user {0}", principalID); 202 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve local root folder for user {0}", principalID);
@@ -199,16 +213,23 @@ namespace OpenSim.Services.HypergridService
199 // In the DB we tag it as type 100, but we use -1 (Unknown) outside 213 // In the DB we tag it as type 100, but we use -1 (Unknown) outside
200 suitcase = CreateFolder(principalID, root.folderID, 100, "My Suitcase"); 214 suitcase = CreateFolder(principalID, root.folderID, 100, "My Suitcase");
201 if (suitcase == null) 215 if (suitcase == null)
216 {
202 m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to create suitcase folder"); 217 m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to create suitcase folder");
203 m_Database.StoreFolder(suitcase); 218 }
219 else
220 {
221 m_Database.StoreFolder(suitcase);
204 222
205 // Create System folders 223 // Create System folders
206 CreateSystemFolders(principalID, suitcase.folderID); 224 CreateSystemFolders(principalID, suitcase.folderID);
207 }
208 225
209 SetAsNormalFolder(suitcase); 226 SetAsNormalFolder(suitcase);
210 227
211 return ConvertToOpenSim(suitcase); 228 return ConvertToOpenSim(suitcase);
229 }
230 }
231
232 return null;
212 } 233 }
213 234
214 protected void CreateSystemFolders(UUID principalID, UUID rootID) 235 protected void CreateSystemFolders(UUID principalID, UUID rootID)
@@ -255,6 +276,13 @@ namespace OpenSim.Services.HypergridService
255 { 276 {
256 //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type); 277 //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type);
257 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); 278 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
279
280 if (suitcase == null)
281 {
282 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no suitcase folder for user {0} when looking for child type folder {1}", principalID, type);
283 return null;
284 }
285
258 XInventoryFolder[] folders = m_Database.GetFolders( 286 XInventoryFolder[] folders = m_Database.GetFolders(
259 new string[] { "agentID", "type", "parentFolderID" }, 287 new string[] { "agentID", "type", "parentFolderID" },
260 new string[] { principalID.ToString(), ((int)type).ToString(), suitcase.folderID.ToString() }); 288 new string[] { principalID.ToString(), ((int)type).ToString(), suitcase.folderID.ToString() });
@@ -472,6 +500,22 @@ namespace OpenSim.Services.HypergridService
472 return null; 500 return null;
473 } 501 }
474 502
503 private XInventoryFolder GetCurrentOutfitXFolder(UUID userID)
504 {
505 XInventoryFolder root = GetRootXFolder(userID);
506 if (root == null)
507 return null;
508
509 XInventoryFolder[] folders = m_Database.GetFolders(
510 new string[] { "agentID", "type", "parentFolderID" },
511 new string[] { userID.ToString(), ((int)AssetType.CurrentOutfitFolder).ToString(), root.folderID.ToString() });
512
513 if (folders.Length == 0)
514 return null;
515
516 return folders[0];
517 }
518
475 private XInventoryFolder GetSuitcaseXFolder(UUID principalID) 519 private XInventoryFolder GetSuitcaseXFolder(UUID principalID)
476 { 520 {
477 // Warp! Root folder for travelers 521 // Warp! Root folder for travelers
@@ -510,6 +554,7 @@ namespace OpenSim.Services.HypergridService
510 if (m_SuitcaseTrees.TryGetValue(principalID, out t)) 554 if (m_SuitcaseTrees.TryGetValue(principalID, out t))
511 return t; 555 return t;
512 556
557 // Get the tree of the suitcase folder
513 t = GetFolderTreeRecursive(folder); 558 t = GetFolderTreeRecursive(folder);
514 m_SuitcaseTrees.AddOrUpdate(principalID, t, 5*60); // 5minutes 559 m_SuitcaseTrees.AddOrUpdate(principalID, t, 5*60); // 5minutes
515 return t; 560 return t;
@@ -546,6 +591,7 @@ namespace OpenSim.Services.HypergridService
546 private bool IsWithinSuitcaseTree(UUID principalID, UUID folderID) 591 private bool IsWithinSuitcaseTree(UUID principalID, UUID folderID)
547 { 592 {
548 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); 593 XInventoryFolder suitcase = GetSuitcaseXFolder(principalID);
594
549 if (suitcase == null) 595 if (suitcase == null)
550 { 596 {
551 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder", principalID); 597 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder", principalID);
@@ -555,6 +601,9 @@ namespace OpenSim.Services.HypergridService
555 List<XInventoryFolder> tree = new List<XInventoryFolder>(); 601 List<XInventoryFolder> tree = new List<XInventoryFolder>();
556 tree.Add(suitcase); // Warp! the tree is the real root folder plus the children of the suitcase folder 602 tree.Add(suitcase); // Warp! the tree is the real root folder plus the children of the suitcase folder
557 tree.AddRange(GetFolderTree(principalID, suitcase.folderID)); 603 tree.AddRange(GetFolderTree(principalID, suitcase.folderID));
604 // Also add the Current Outfit folder to the list of available folders
605 tree.Add(GetCurrentOutfitXFolder(principalID));
606
558 XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl) 607 XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl)
559 { 608 {
560 if (fl.folderID == folderID) return true; 609 if (fl.folderID == folderID) return true;
diff --git a/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs b/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs
index 8d66f1b..0fb60f6 100644
--- a/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/HypergridService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
index ec76508..b414aca 100644
--- a/OpenSim/Services/HypergridService/UserAgentService.cs
+++ b/OpenSim/Services/HypergridService/UserAgentService.cs
@@ -30,6 +30,7 @@ using System.Collections.Generic;
30using System.Net; 30using System.Net;
31using System.Reflection; 31using System.Reflection;
32 32
33using OpenSim.Data;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Services.Connectors.Friends; 35using OpenSim.Services.Connectors.Friends;
35using OpenSim.Services.Connectors.Hypergrid; 36using OpenSim.Services.Connectors.Hypergrid;
@@ -50,14 +51,14 @@ namespace OpenSim.Services.HypergridService
50 /// needs to do it for them. 51 /// needs to do it for them.
51 /// Once we have better clients, this shouldn't be needed. 52 /// Once we have better clients, this shouldn't be needed.
52 /// </summary> 53 /// </summary>
53 public class UserAgentService : IUserAgentService 54 public class UserAgentService : UserAgentServiceBase, IUserAgentService
54 { 55 {
55 private static readonly ILog m_log = 56 private static readonly ILog m_log =
56 LogManager.GetLogger( 57 LogManager.GetLogger(
57 MethodBase.GetCurrentMethod().DeclaringType); 58 MethodBase.GetCurrentMethod().DeclaringType);
58 59
59 // This will need to go into a DB table 60 // This will need to go into a DB table
60 static Dictionary<UUID, TravelingAgentInfo> m_TravelingAgents = new Dictionary<UUID, TravelingAgentInfo>(); 61 //static Dictionary<UUID, TravelingAgentInfo> m_Database = new Dictionary<UUID, TravelingAgentInfo>();
61 62
62 static bool m_Initialized = false; 63 static bool m_Initialized = false;
63 64
@@ -86,6 +87,7 @@ namespace OpenSim.Services.HypergridService
86 } 87 }
87 88
88 public UserAgentService(IConfigSource config, IFriendsSimConnector friendsConnector) 89 public UserAgentService(IConfigSource config, IFriendsSimConnector friendsConnector)
90 : base(config)
89 { 91 {
90 // Let's set this always, because we don't know the sequence 92 // Let's set this always, because we don't know the sequence
91 // of instantiations 93 // of instantiations
@@ -146,6 +148,9 @@ namespace OpenSim.Services.HypergridService
146 if (!m_GridName.EndsWith("/")) 148 if (!m_GridName.EndsWith("/"))
147 m_GridName = m_GridName + "/"; 149 m_GridName = m_GridName + "/";
148 150
151 // Finally some cleanup
152 m_Database.DeleteOld();
153
149 } 154 }
150 } 155 }
151 156
@@ -210,10 +215,10 @@ namespace OpenSim.Services.HypergridService
210 return home; 215 return home;
211 } 216 }
212 217
213 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason) 218 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason)
214 { 219 {
215 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", 220 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}",
216 agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI); 221 agentCircuit.firstname, agentCircuit.lastname, (fromLogin ? agentCircuit.IPAddress : "stored IP"), gatekeeper.ServerURI);
217 222
218 string gridName = gatekeeper.ServerURI; 223 string gridName = gatekeeper.ServerURI;
219 224
@@ -260,12 +265,13 @@ namespace OpenSim.Services.HypergridService
260 265
261 // Generate a new service session 266 // Generate a new service session
262 agentCircuit.ServiceSessionID = region.ServerURI + ";" + UUID.Random(); 267 agentCircuit.ServiceSessionID = region.ServerURI + ";" + UUID.Random();
263 TravelingAgentInfo old = UpdateTravelInfo(agentCircuit, region); 268 TravelingAgentInfo old = null;
269 TravelingAgentInfo travel = CreateTravelInfo(agentCircuit, region, fromLogin, out old);
264 270
265 bool success = false; 271 bool success = false;
266 string myExternalIP = string.Empty; 272 string myExternalIP = string.Empty;
267 273
268 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); 274 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}, desired region: {2}", m_GridName, gridName, region.RegionID);
269 275
270 if (m_GridName == gridName) 276 if (m_GridName == gridName)
271 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); 277 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason);
@@ -282,23 +288,21 @@ namespace OpenSim.Services.HypergridService
282 m_log.DebugFormat("[USER AGENT SERVICE]: Unable to login user {0} {1} to grid {2}, reason: {3}", 288 m_log.DebugFormat("[USER AGENT SERVICE]: Unable to login user {0} {1} to grid {2}, reason: {3}",
283 agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason); 289 agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason);
284 290
285 // restore the old travel info 291 if (old != null)
286 lock (m_TravelingAgents) 292 StoreTravelInfo(old);
287 { 293 else
288 if (old == null) 294 m_Database.Delete(agentCircuit.SessionID);
289 m_TravelingAgents.Remove(agentCircuit.SessionID);
290 else
291 m_TravelingAgents[agentCircuit.SessionID] = old;
292 }
293 295
294 return false; 296 return false;
295 } 297 }
296 298
299 // Everything is ok
300
301 // Update the perceived IP Address of our grid
297 m_log.DebugFormat("[USER AGENT SERVICE]: Gatekeeper sees me as {0}", myExternalIP); 302 m_log.DebugFormat("[USER AGENT SERVICE]: Gatekeeper sees me as {0}", myExternalIP);
298 // else set the IP addresses associated with this client 303 travel.MyIpAddress = myExternalIP;
299 if (clientIP != null) 304
300 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString(); 305 StoreTravelInfo(travel);
301 m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP;
302 306
303 return true; 307 return true;
304 } 308 }
@@ -306,60 +310,42 @@ namespace OpenSim.Services.HypergridService
306 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason) 310 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason)
307 { 311 {
308 reason = string.Empty; 312 reason = string.Empty;
309 return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, null, out reason); 313 return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, false, out reason);
310 } 314 }
311 315
312 private void SetClientIP(UUID sessionID, string ip) 316 TravelingAgentInfo CreateTravelInfo(AgentCircuitData agentCircuit, GridRegion region, bool fromLogin, out TravelingAgentInfo existing)
313 { 317 {
314 if (m_TravelingAgents.ContainsKey(sessionID)) 318 HGTravelingData hgt = m_Database.Get(agentCircuit.SessionID);
315 { 319 existing = null;
316 m_log.DebugFormat("[USER AGENT SERVICE]: Setting IP {0} for session {1}", ip, sessionID);
317 m_TravelingAgents[sessionID].ClientIPAddress = ip;
318 }
319 }
320 320
321 TravelingAgentInfo UpdateTravelInfo(AgentCircuitData agentCircuit, GridRegion region) 321 if (hgt != null)
322 {
323 TravelingAgentInfo travel = new TravelingAgentInfo();
324 TravelingAgentInfo old = null;
325 lock (m_TravelingAgents)
326 { 322 {
327 if (m_TravelingAgents.ContainsKey(agentCircuit.SessionID)) 323 // Very important! Override whatever this agent comes with.
328 { 324 // UserAgentService always sets the IP for every new agent
329 // Very important! Override whatever this agent comes with. 325 // with the original IP address.
330 // UserAgentService always sets the IP for every new agent 326 existing = new TravelingAgentInfo(hgt);
331 // with the original IP address. 327 agentCircuit.IPAddress = existing.ClientIPAddress;
332 agentCircuit.IPAddress = m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress;
333
334 old = m_TravelingAgents[agentCircuit.SessionID];
335 }
336
337 m_TravelingAgents[agentCircuit.SessionID] = travel;
338 } 328 }
329
330 TravelingAgentInfo travel = new TravelingAgentInfo(existing);
331 travel.SessionID = agentCircuit.SessionID;
339 travel.UserID = agentCircuit.AgentID; 332 travel.UserID = agentCircuit.AgentID;
340 travel.GridExternalName = region.ServerURI; 333 travel.GridExternalName = region.ServerURI;
341 travel.ServiceToken = agentCircuit.ServiceSessionID; 334 travel.ServiceToken = agentCircuit.ServiceSessionID;
342 if (old != null)
343 travel.ClientIPAddress = old.ClientIPAddress;
344 335
345 return old; 336 if (fromLogin)
337 travel.ClientIPAddress = agentCircuit.IPAddress;
338
339 StoreTravelInfo(travel);
340
341 return travel;
346 } 342 }
347 343
348 public void LogoutAgent(UUID userID, UUID sessionID) 344 public void LogoutAgent(UUID userID, UUID sessionID)
349 { 345 {
350 m_log.DebugFormat("[USER AGENT SERVICE]: User {0} logged out", userID); 346 m_log.DebugFormat("[USER AGENT SERVICE]: User {0} logged out", userID);
351 347
352 lock (m_TravelingAgents) 348 m_Database.Delete(sessionID);
353 {
354 List<UUID> travels = new List<UUID>();
355 foreach (KeyValuePair<UUID, TravelingAgentInfo> kvp in m_TravelingAgents)
356 if (kvp.Value == null) // do some clean up
357 travels.Add(kvp.Key);
358 else if (kvp.Value.UserID == userID)
359 travels.Add(kvp.Key);
360 foreach (UUID session in travels)
361 m_TravelingAgents.Remove(session);
362 }
363 349
364 GridUserInfo guinfo = m_GridUserService.GetGridUserInfo(userID.ToString()); 350 GridUserInfo guinfo = m_GridUserService.GetGridUserInfo(userID.ToString());
365 if (guinfo != null) 351 if (guinfo != null)
@@ -369,10 +355,11 @@ namespace OpenSim.Services.HypergridService
369 // We need to prevent foreign users with the same UUID as a local user 355 // We need to prevent foreign users with the same UUID as a local user
370 public bool IsAgentComingHome(UUID sessionID, string thisGridExternalName) 356 public bool IsAgentComingHome(UUID sessionID, string thisGridExternalName)
371 { 357 {
372 if (!m_TravelingAgents.ContainsKey(sessionID)) 358 HGTravelingData hgt = m_Database.Get(sessionID);
359 if (hgt == null)
373 return false; 360 return false;
374 361
375 TravelingAgentInfo travel = m_TravelingAgents[sessionID]; 362 TravelingAgentInfo travel = new TravelingAgentInfo(hgt);
376 363
377 return travel.GridExternalName.ToLower() == thisGridExternalName.ToLower(); 364 return travel.GridExternalName.ToLower() == thisGridExternalName.ToLower();
378 } 365 }
@@ -385,29 +372,32 @@ namespace OpenSim.Services.HypergridService
385 m_log.DebugFormat("[USER AGENT SERVICE]: Verifying Client session {0} with reported IP {1}.", 372 m_log.DebugFormat("[USER AGENT SERVICE]: Verifying Client session {0} with reported IP {1}.",
386 sessionID, reportedIP); 373 sessionID, reportedIP);
387 374
388 if (m_TravelingAgents.ContainsKey(sessionID)) 375 HGTravelingData hgt = m_Database.Get(sessionID);
389 { 376 if (hgt == null)
390 m_log.DebugFormat("[USER AGENT SERVICE]: Comparing with login IP {0} and MyIP {1}", 377 return false;
391 m_TravelingAgents[sessionID].ClientIPAddress, m_TravelingAgents[sessionID].MyIpAddress);
392 378
393 return m_TravelingAgents[sessionID].ClientIPAddress == reportedIP || 379 TravelingAgentInfo travel = new TravelingAgentInfo(hgt);
394 m_TravelingAgents[sessionID].MyIpAddress == reportedIP; // NATed 380
395 } 381 bool result = travel.ClientIPAddress == reportedIP || travel.MyIpAddress == reportedIP; // NATed
396 382
397 return false; 383 m_log.DebugFormat("[USER AGENT SERVICE]: Comparing {0} with login IP {1} and MyIP {1}; result is {3}",
384 reportedIP, travel.ClientIPAddress, travel.MyIpAddress, result);
385
386 return result;
398 } 387 }
399 388
400 public bool VerifyAgent(UUID sessionID, string token) 389 public bool VerifyAgent(UUID sessionID, string token)
401 { 390 {
402 if (m_TravelingAgents.ContainsKey(sessionID)) 391 HGTravelingData hgt = m_Database.Get(sessionID);
392 if (hgt == null)
403 { 393 {
404 m_log.DebugFormat("[USER AGENT SERVICE]: Verifying agent token {0} against {1}", token, m_TravelingAgents[sessionID].ServiceToken); 394 m_log.DebugFormat("[USER AGENT SERVICE]: Token verification for session {0}: no such session", sessionID);
405 return m_TravelingAgents[sessionID].ServiceToken == token; 395 return false;
406 } 396 }
407 397
408 m_log.DebugFormat("[USER AGENT SERVICE]: Token verification for session {0}: no such session", sessionID); 398 TravelingAgentInfo travel = new TravelingAgentInfo(hgt);
409 399 m_log.DebugFormat("[USER AGENT SERVICE]: Verifying agent token {0} against {1}", token, travel.ServiceToken);
410 return false; 400 return travel.ServiceToken == token;
411 } 401 }
412 402
413 [Obsolete] 403 [Obsolete]
@@ -470,17 +460,17 @@ namespace OpenSim.Services.HypergridService
470 } 460 }
471 } 461 }
472 462
473 // Lastly, let's notify the rest who may be online somewhere else 463 //// Lastly, let's notify the rest who may be online somewhere else
474 foreach (string user in usersToBeNotified) 464 //foreach (string user in usersToBeNotified)
475 { 465 //{
476 UUID id = new UUID(user); 466 // UUID id = new UUID(user);
477 if (m_TravelingAgents.ContainsKey(id) && m_TravelingAgents[id].GridExternalName != m_GridName) 467 // if (m_Database.ContainsKey(id) && m_Database[id].GridExternalName != m_GridName)
478 { 468 // {
479 string url = m_TravelingAgents[id].GridExternalName; 469 // string url = m_Database[id].GridExternalName;
480 // forward 470 // // forward
481 m_log.WarnFormat("[USER AGENT SERVICE]: User {0} is visiting {1}. HG Status notifications still not implemented.", user, url); 471 // m_log.WarnFormat("[USER AGENT SERVICE]: User {0} is visiting {1}. HG Status notifications still not implemented.", user, url);
482 } 472 // }
483 } 473 //}
484 474
485 // and finally, let's send the online friends 475 // and finally, let's send the online friends
486 if (online) 476 if (online)
@@ -607,16 +597,13 @@ namespace OpenSim.Services.HypergridService
607 597
608 public string LocateUser(UUID userID) 598 public string LocateUser(UUID userID)
609 { 599 {
610 foreach (TravelingAgentInfo t in m_TravelingAgents.Values) 600 HGTravelingData[] hgts = m_Database.GetSessions(userID);
611 { 601 if (hgts == null)
612 if (t == null) 602 return string.Empty;
613 { 603
614 m_log.ErrorFormat("[USER AGENT SERVICE]: Oops! Null TravelingAgentInfo. Please report this on mantis"); 604 foreach (HGTravelingData t in hgts)
615 continue; 605 if (t.Data.ContainsKey("GridExternalName") && !m_GridName.Equals(t.Data["GridExternalName"]))
616 } 606 return t.Data["GridExternalName"];
617 if (t.UserID == userID && !m_GridName.Equals(t.GridExternalName))
618 return t.GridExternalName;
619 }
620 607
621 return string.Empty; 608 return string.Empty;
622 } 609 }
@@ -687,17 +674,60 @@ namespace OpenSim.Services.HypergridService
687 return exception; 674 return exception;
688 } 675 }
689 676
677 private void StoreTravelInfo(TravelingAgentInfo travel)
678 {
679 if (travel == null)
680 return;
681
682 HGTravelingData hgt = new HGTravelingData();
683 hgt.SessionID = travel.SessionID;
684 hgt.UserID = travel.UserID;
685 hgt.Data = new Dictionary<string, string>();
686 hgt.Data["GridExternalName"] = travel.GridExternalName;
687 hgt.Data["ServiceToken"] = travel.ServiceToken;
688 hgt.Data["ClientIPAddress"] = travel.ClientIPAddress;
689 hgt.Data["MyIPAddress"] = travel.MyIpAddress;
690
691 m_Database.Store(hgt);
692 }
690 #endregion 693 #endregion
691 694
692 } 695 }
693 696
694 class TravelingAgentInfo 697 class TravelingAgentInfo
695 { 698 {
699 public UUID SessionID;
696 public UUID UserID; 700 public UUID UserID;
697 public string GridExternalName = string.Empty; 701 public string GridExternalName = string.Empty;
698 public string ServiceToken = string.Empty; 702 public string ServiceToken = string.Empty;
699 public string ClientIPAddress = string.Empty; // as seen from this user agent service 703 public string ClientIPAddress = string.Empty; // as seen from this user agent service
700 public string MyIpAddress = string.Empty; // the user agent service's external IP, as seen from the next gatekeeper 704 public string MyIpAddress = string.Empty; // the user agent service's external IP, as seen from the next gatekeeper
705
706 public TravelingAgentInfo(HGTravelingData t)
707 {
708 if (t.Data != null)
709 {
710 SessionID = new UUID(t.SessionID);
711 UserID = new UUID(t.UserID);
712 GridExternalName = t.Data["GridExternalName"];
713 ServiceToken = t.Data["ServiceToken"];
714 ClientIPAddress = t.Data["ClientIPAddress"];
715 MyIpAddress = t.Data["MyIPAddress"];
716 }
717 }
718
719 public TravelingAgentInfo(TravelingAgentInfo old)
720 {
721 if (old != null)
722 {
723 SessionID = old.SessionID;
724 UserID = old.UserID;
725 GridExternalName = old.GridExternalName;
726 ServiceToken = old.ServiceToken;
727 ClientIPAddress = old.ClientIPAddress;
728 MyIpAddress = old.MyIpAddress;
729 }
730 }
701 } 731 }
702 732
703} 733}
diff --git a/OpenSim/Services/HypergridService/UserAgentServiceBase.cs b/OpenSim/Services/HypergridService/UserAgentServiceBase.cs
new file mode 100644
index 0000000..a00e5a6
--- /dev/null
+++ b/OpenSim/Services/HypergridService/UserAgentServiceBase.cs
@@ -0,0 +1,84 @@
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.Reflection;
30using Nini.Config;
31using OpenSim.Framework;
32using OpenSim.Data;
33using OpenSim.Services.Interfaces;
34using OpenSim.Services.Base;
35
36namespace OpenSim.Services.HypergridService
37{
38 public class UserAgentServiceBase : ServiceBase
39 {
40 protected IHGTravelingData m_Database = null;
41
42 public UserAgentServiceBase(IConfigSource config)
43 : base(config)
44 {
45 string dllName = String.Empty;
46 string connString = String.Empty;
47 string realm = "hg_traveling_data";
48
49 //
50 // Try reading the [DatabaseService] section, if it exists
51 //
52 IConfig dbConfig = config.Configs["DatabaseService"];
53 if (dbConfig != null)
54 {
55 if (dllName == String.Empty)
56 dllName = dbConfig.GetString("StorageProvider", String.Empty);
57 if (connString == String.Empty)
58 connString = dbConfig.GetString("ConnectionString", String.Empty);
59 }
60
61 //
62 // [UserAgentService] section overrides [DatabaseService], if it exists
63 //
64 IConfig gridConfig = config.Configs["UserAgentService"];
65 if (gridConfig != null)
66 {
67 dllName = gridConfig.GetString("StorageProvider", dllName);
68 connString = gridConfig.GetString("ConnectionString", connString);
69 realm = gridConfig.GetString("Realm", realm);
70 }
71
72 //
73 // We tried, but this doesn't exist. We can't proceed.
74 //
75 if (dllName.Equals(String.Empty))
76 throw new Exception("No StorageProvider configured");
77
78 m_Database = LoadPlugin<IHGTravelingData>(dllName, new Object[] { connString, realm });
79 if (m_Database == null)
80 throw new Exception("Could not find a storage interface in the given module");
81
82 }
83 }
84}
diff --git a/OpenSim/Services/Interfaces/IBansService.cs b/OpenSim/Services/Interfaces/IBansService.cs
new file mode 100644
index 0000000..8fd3521
--- /dev/null
+++ b/OpenSim/Services/Interfaces/IBansService.cs
@@ -0,0 +1,48 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections.Generic;
29
30using OpenSim.Framework;
31using OpenMetaverse;
32
33namespace OpenSim.Services.Interfaces
34{
35 public interface IBansService
36 {
37 /// <summary>
38 /// Are any of the given arguments banned from the grid?
39 /// </summary>
40 /// <param name="userID"></param>
41 /// <param name="ip"></param>
42 /// <param name="id0"></param>
43 /// <param name="origin"></param>
44 /// <returns></returns>
45 bool IsBanned(string userID, string ip, string id0, string origin);
46 }
47
48}
diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs
index 3f4c958..4466222 100644
--- a/OpenSim/Services/Interfaces/IGridService.cs
+++ b/OpenSim/Services/Interfaces/IGridService.cs
@@ -29,9 +29,13 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Net; 30using System.Net;
31using System.Net.Sockets; 31using System.Net.Sockets;
32using System.Reflection;
33
32using OpenSim.Framework; 34using OpenSim.Framework;
33using OpenMetaverse; 35using OpenMetaverse;
34 36
37using log4net;
38
35namespace OpenSim.Services.Interfaces 39namespace OpenSim.Services.Interfaces
36{ 40{
37 public interface IGridService 41 public interface IGridService
@@ -97,6 +101,7 @@ namespace OpenSim.Services.Interfaces
97 List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax); 101 List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax);
98 102
99 List<GridRegion> GetDefaultRegions(UUID scopeID); 103 List<GridRegion> GetDefaultRegions(UUID scopeID);
104 List<GridRegion> GetDefaultHypergridRegions(UUID scopeID);
100 List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y); 105 List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y);
101 List<GridRegion> GetHyperlinks(UUID scopeID); 106 List<GridRegion> GetHyperlinks(UUID scopeID);
102 107
@@ -118,6 +123,9 @@ namespace OpenSim.Services.Interfaces
118 123
119 public class GridRegion 124 public class GridRegion
120 { 125 {
126 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
127 private static readonly string LogHeader = "[GRID REGION]";
128
121 /// <summary> 129 /// <summary>
122 /// The port by which http communication occurs with the region 130 /// The port by which http communication occurs with the region
123 /// </summary> 131 /// </summary>
@@ -137,7 +145,10 @@ namespace OpenSim.Services.Interfaces
137 if ( m_serverURI != string.Empty ) { 145 if ( m_serverURI != string.Empty ) {
138 return m_serverURI; 146 return m_serverURI;
139 } else { 147 } else {
140 return "http://" + m_externalHostName + ":" + m_httpPort + "/"; 148 if (m_httpPort == 0)
149 return "http://" + m_externalHostName + "/";
150 else
151 return "http://" + m_externalHostName + ":" + m_httpPort + "/";
141 } 152 }
142 } 153 }
143 set { 154 set {
@@ -173,6 +184,7 @@ namespace OpenSim.Services.Interfaces
173 184
174 /// <summary> 185 /// <summary>
175 /// The location of this region in meters. 186 /// The location of this region in meters.
187 /// DANGER DANGER! Note that this name means something different in RegionInfo.
176 /// </summary> 188 /// </summary>
177 public int RegionLocX 189 public int RegionLocX
178 { 190 {
@@ -181,8 +193,12 @@ namespace OpenSim.Services.Interfaces
181 } 193 }
182 protected int m_regionLocX; 194 protected int m_regionLocX;
183 195
196 public int RegionSizeX { get; set; }
197 public int RegionSizeY { get; set; }
198
184 /// <summary> 199 /// <summary>
185 /// The location of this region in meters. 200 /// The location of this region in meters.
201 /// DANGER DANGER! Note that this name means something different in RegionInfo.
186 /// </summary> 202 /// </summary>
187 public int RegionLocY 203 public int RegionLocY
188 { 204 {
@@ -211,13 +227,18 @@ namespace OpenSim.Services.Interfaces
211 227
212 public GridRegion() 228 public GridRegion()
213 { 229 {
230 RegionSizeX = (int)Constants.RegionSize;
231 RegionSizeY = (int)Constants.RegionSize;
214 m_serverURI = string.Empty; 232 m_serverURI = string.Empty;
215 } 233 }
216 234
235 /*
217 public GridRegion(int regionLocX, int regionLocY, IPEndPoint internalEndPoint, string externalUri) 236 public GridRegion(int regionLocX, int regionLocY, IPEndPoint internalEndPoint, string externalUri)
218 { 237 {
219 m_regionLocX = regionLocX; 238 m_regionLocX = regionLocX;
220 m_regionLocY = regionLocY; 239 m_regionLocY = regionLocY;
240 RegionSizeX = (int)Constants.RegionSize;
241 RegionSizeY = (int)Constants.RegionSize;
221 242
222 m_internalEndPoint = internalEndPoint; 243 m_internalEndPoint = internalEndPoint;
223 m_externalHostName = externalUri; 244 m_externalHostName = externalUri;
@@ -227,16 +248,21 @@ namespace OpenSim.Services.Interfaces
227 { 248 {
228 m_regionLocX = regionLocX; 249 m_regionLocX = regionLocX;
229 m_regionLocY = regionLocY; 250 m_regionLocY = regionLocY;
251 RegionSizeX = (int)Constants.RegionSize;
252 RegionSizeY = (int)Constants.RegionSize;
230 253
231 m_externalHostName = externalUri; 254 m_externalHostName = externalUri;
232 255
233 m_internalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int)port); 256 m_internalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int)port);
234 } 257 }
258 */
235 259
236 public GridRegion(uint xcell, uint ycell) 260 public GridRegion(uint xcell, uint ycell)
237 { 261 {
238 m_regionLocX = (int)(xcell * Constants.RegionSize); 262 m_regionLocX = (int)(xcell * Constants.RegionSize);
239 m_regionLocY = (int)(ycell * Constants.RegionSize); 263 m_regionLocY = (int)(ycell * Constants.RegionSize);
264 RegionSizeX = (int)Constants.RegionSize;
265 RegionSizeY = (int)Constants.RegionSize;
240 } 266 }
241 267
242 public GridRegion(RegionInfo ConvertFrom) 268 public GridRegion(RegionInfo ConvertFrom)
@@ -244,6 +270,8 @@ namespace OpenSim.Services.Interfaces
244 m_regionName = ConvertFrom.RegionName; 270 m_regionName = ConvertFrom.RegionName;
245 m_regionLocX = (int)(ConvertFrom.RegionLocX * Constants.RegionSize); 271 m_regionLocX = (int)(ConvertFrom.RegionLocX * Constants.RegionSize);
246 m_regionLocY = (int)(ConvertFrom.RegionLocY * Constants.RegionSize); 272 m_regionLocY = (int)(ConvertFrom.RegionLocY * Constants.RegionSize);
273 RegionSizeX = (int)ConvertFrom.RegionSizeX;
274 RegionSizeY = (int)ConvertFrom.RegionSizeY;
247 m_internalEndPoint = ConvertFrom.InternalEndPoint; 275 m_internalEndPoint = ConvertFrom.InternalEndPoint;
248 m_externalHostName = ConvertFrom.ExternalHostName; 276 m_externalHostName = ConvertFrom.ExternalHostName;
249 m_httpPort = ConvertFrom.HttpPort; 277 m_httpPort = ConvertFrom.HttpPort;
@@ -262,6 +290,8 @@ namespace OpenSim.Services.Interfaces
262 m_regionName = ConvertFrom.RegionName; 290 m_regionName = ConvertFrom.RegionName;
263 m_regionLocX = ConvertFrom.RegionLocX; 291 m_regionLocX = ConvertFrom.RegionLocX;
264 m_regionLocY = ConvertFrom.RegionLocY; 292 m_regionLocY = ConvertFrom.RegionLocY;
293 RegionSizeX = ConvertFrom.RegionSizeX;
294 RegionSizeY = ConvertFrom.RegionSizeY;
265 m_internalEndPoint = ConvertFrom.InternalEndPoint; 295 m_internalEndPoint = ConvertFrom.InternalEndPoint;
266 m_externalHostName = ConvertFrom.ExternalHostName; 296 m_externalHostName = ConvertFrom.ExternalHostName;
267 m_httpPort = ConvertFrom.HttpPort; 297 m_httpPort = ConvertFrom.HttpPort;
@@ -373,6 +403,8 @@ namespace OpenSim.Services.Interfaces
373 kvp["uuid"] = RegionID.ToString(); 403 kvp["uuid"] = RegionID.ToString();
374 kvp["locX"] = RegionLocX.ToString(); 404 kvp["locX"] = RegionLocX.ToString();
375 kvp["locY"] = RegionLocY.ToString(); 405 kvp["locY"] = RegionLocY.ToString();
406 kvp["sizeX"] = RegionSizeX.ToString();
407 kvp["sizeY"] = RegionSizeY.ToString();
376 kvp["regionName"] = RegionName; 408 kvp["regionName"] = RegionName;
377 kvp["serverIP"] = ExternalHostName; //ExternalEndPoint.Address.ToString(); 409 kvp["serverIP"] = ExternalHostName; //ExternalEndPoint.Address.ToString();
378 kvp["serverHttpPort"] = HttpPort.ToString(); 410 kvp["serverHttpPort"] = HttpPort.ToString();
@@ -399,6 +431,16 @@ namespace OpenSim.Services.Interfaces
399 if (kvp.ContainsKey("locY")) 431 if (kvp.ContainsKey("locY"))
400 RegionLocY = Convert.ToInt32((string)kvp["locY"]); 432 RegionLocY = Convert.ToInt32((string)kvp["locY"]);
401 433
434 if (kvp.ContainsKey("sizeX"))
435 RegionSizeX = Convert.ToInt32((string)kvp["sizeX"]);
436 else
437 RegionSizeX = (int)Constants.RegionSize;
438
439 if (kvp.ContainsKey("sizeY"))
440 RegionSizeY = Convert.ToInt32((string)kvp["sizeY"]);
441 else
442 RegionSizeX = (int)Constants.RegionSize;
443
402 if (kvp.ContainsKey("regionName")) 444 if (kvp.ContainsKey("regionName"))
403 RegionName = (string)kvp["regionName"]; 445 RegionName = (string)kvp["regionName"];
404 446
@@ -452,6 +494,9 @@ namespace OpenSim.Services.Interfaces
452 494
453 if (kvp.ContainsKey("Token")) 495 if (kvp.ContainsKey("Token"))
454 Token = kvp["Token"].ToString(); 496 Token = kvp["Token"].ToString();
497
498 // m_log.DebugFormat("{0} New GridRegion. id={1}, loc=<{2},{3}>, size=<{4},{5}>",
499 // LogHeader, RegionID, RegionLocX, RegionLocY, RegionSizeX, RegionSizeY);
455 } 500 }
456 } 501 }
457} 502}
diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs
index 3dc877a..05e175a 100644
--- a/OpenSim/Services/Interfaces/IHypergridServices.cs
+++ b/OpenSim/Services/Interfaces/IHypergridServices.cs
@@ -43,15 +43,9 @@ namespace OpenSim.Services.Interfaces
43 43
44 } 44 }
45 45
46 /// <summary>
47 /// HG1.5 only
48 /// </summary>
49 public interface IUserAgentService 46 public interface IUserAgentService
50 { 47 {
51 // called by login service only 48 bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason);
52 bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason);
53 // called by simulators
54 bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason);
55 void LogoutAgent(UUID userID, UUID sessionID); 49 void LogoutAgent(UUID userID, UUID sessionID);
56 GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); 50 GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt);
57 Dictionary<string, object> GetServerURLs(UUID userID); 51 Dictionary<string, object> GetServerURLs(UUID userID);
diff --git a/OpenSim/Services/Interfaces/IOfflineIMService.cs b/OpenSim/Services/Interfaces/IOfflineIMService.cs
index 2848967..588aaaf 100644
--- a/OpenSim/Services/Interfaces/IOfflineIMService.cs
+++ b/OpenSim/Services/Interfaces/IOfflineIMService.cs
@@ -35,7 +35,14 @@ namespace OpenSim.Services.Interfaces
35 public interface IOfflineIMService 35 public interface IOfflineIMService
36 { 36 {
37 List<GridInstantMessage> GetMessages(UUID principalID); 37 List<GridInstantMessage> GetMessages(UUID principalID);
38
38 bool StoreMessage(GridInstantMessage im, out string reason); 39 bool StoreMessage(GridInstantMessage im, out string reason);
40
41 /// <summary>
42 /// Delete messages to or from this user (or group).
43 /// </summary>
44 /// <param name="userID">A user or group ID</param>
45 void DeleteMessages(UUID userID);
39 } 46 }
40 47
41 public class OfflineIMDataUtils 48 public class OfflineIMDataUtils
diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs
index a963b8e..1c82b3e 100644
--- a/OpenSim/Services/Interfaces/ISimulationService.cs
+++ b/OpenSim/Services/Interfaces/ISimulationService.cs
@@ -75,8 +75,6 @@ namespace OpenSim.Services.Interfaces
75 /// <returns></returns> 75 /// <returns></returns>
76 bool UpdateAgent(GridRegion destination, AgentPosition data); 76 bool UpdateAgent(GridRegion destination, AgentPosition data);
77 77
78 bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent);
79
80 bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason); 78 bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason);
81 79
82 /// <summary> 80 /// <summary>
@@ -90,20 +88,12 @@ namespace OpenSim.Services.Interfaces
90 bool ReleaseAgent(UUID originRegion, UUID id, string uri); 88 bool ReleaseAgent(UUID originRegion, UUID id, string uri);
91 89
92 /// <summary> 90 /// <summary>
93 /// Close child agent.
94 /// </summary>
95 /// <param name="regionHandle"></param>
96 /// <param name="id"></param>
97 /// <returns></returns>
98 bool CloseChildAgent(GridRegion destination, UUID id);
99
100 /// <summary>
101 /// Close agent. 91 /// Close agent.
102 /// </summary> 92 /// </summary>
103 /// <param name="regionHandle"></param> 93 /// <param name="regionHandle"></param>
104 /// <param name="id"></param> 94 /// <param name="id"></param>
105 /// <returns></returns> 95 /// <returns></returns>
106 bool CloseAgent(GridRegion destination, UUID id); 96 bool CloseAgent(GridRegion destination, UUID id, string auth_token);
107 97
108 #endregion Agents 98 #endregion Agents
109 99
diff --git a/OpenSim/Services/Interfaces/IUserProfilesService.cs b/OpenSim/Services/Interfaces/IUserProfilesService.cs
new file mode 100644
index 0000000..319d307
--- /dev/null
+++ b/OpenSim/Services/Interfaces/IUserProfilesService.cs
@@ -0,0 +1,75 @@
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 OpenSim.Framework;
30using OpenMetaverse;
31using OpenMetaverse.StructuredData;
32
33namespace OpenSim.Services.Interfaces
34{
35 public interface IUserProfilesService
36 {
37 #region Classifieds
38 OSD AvatarClassifiedsRequest(UUID creatorId);
39 bool ClassifiedUpdate(UserClassifiedAdd ad, ref string result);
40 bool ClassifiedInfoRequest(ref UserClassifiedAdd ad, ref string result);
41 bool ClassifiedDelete(UUID recordId);
42 #endregion Classifieds
43
44 #region Picks
45 OSD AvatarPicksRequest(UUID creatorId);
46 bool PickInfoRequest(ref UserProfilePick pick, ref string result);
47 bool PicksUpdate(ref UserProfilePick pick, ref string result);
48 bool PicksDelete(UUID pickId);
49 #endregion Picks
50
51 #region Notes
52 bool AvatarNotesRequest(ref UserProfileNotes note);
53 bool NotesUpdate(ref UserProfileNotes note, ref string result);
54 #endregion Notes
55
56 #region Profile Properties
57 bool AvatarPropertiesRequest(ref UserProfileProperties prop, ref string result);
58 bool AvatarPropertiesUpdate(ref UserProfileProperties prop, ref string result);
59 #endregion Profile Properties
60
61 #region Interests
62 bool AvatarInterestsUpdate(UserProfileProperties prop, ref string result);
63 #endregion Interests
64
65 #region Utility
66 OSD AvatarImageAssetsRequest(UUID avatarId);
67 #endregion Utility
68
69 #region UserData
70 bool RequestUserAppData(ref UserAppData prop, ref string result);
71 bool SetUserAppData(UserAppData prop, ref string result);
72 #endregion UserData
73 }
74}
75
diff --git a/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs b/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs
index 47ece75..f7c8cc1 100644
--- a/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/Interfaces/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
index bfae81f..fd8707b 100644
--- a/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs
index e2f947c..f641955 100644
--- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs
@@ -196,6 +196,7 @@ namespace OpenSim.Services.LLLoginService
196 private BuddyList m_buddyList = null; 196 private BuddyList m_buddyList = null;
197 197
198 private string currency; 198 private string currency;
199 private string classifiedFee;
199 200
200 static LLLoginResponse() 201 static LLLoginResponse()
201 { 202 {
@@ -233,7 +234,7 @@ namespace OpenSim.Services.LLLoginService
233 GridRegion destination, List<InventoryFolderBase> invSkel, FriendInfo[] friendsList, ILibraryService libService, 234 GridRegion destination, List<InventoryFolderBase> invSkel, FriendInfo[] friendsList, ILibraryService libService,
234 string where, string startlocation, Vector3 position, Vector3 lookAt, List<InventoryItemBase> gestures, string message, 235 string where, string startlocation, Vector3 position, Vector3 lookAt, List<InventoryItemBase> gestures, string message,
235 GridRegion home, IPEndPoint clientIP, string mapTileURL, string profileURL, string openIDURL, string searchURL, string currency, 236 GridRegion home, IPEndPoint clientIP, string mapTileURL, string profileURL, string openIDURL, string searchURL, string currency,
236 string DSTZone, UUID realID) 237 string DSTZone, string destinationsURL, string avatarsURL, UUID realID, string classifiedFee)
237 : this() 238 : this()
238 { 239 {
239 FillOutInventoryData(invSkel, libService); 240 FillOutInventoryData(invSkel, libService);
@@ -253,14 +254,18 @@ namespace OpenSim.Services.LLLoginService
253 MapTileURL = mapTileURL; 254 MapTileURL = mapTileURL;
254 ProfileURL = profileURL; 255 ProfileURL = profileURL;
255 OpenIDURL = openIDURL; 256 OpenIDURL = openIDURL;
257 DestinationsURL = destinationsURL;
258 AvatarsURL = avatarsURL;
256 259
257 SearchURL = searchURL; 260 SearchURL = searchURL;
258 Currency = currency; 261 Currency = currency;
262 ClassifiedFee = classifiedFee;
259 263
260 FillOutHomeData(pinfo, home); 264 FillOutHomeData(pinfo, home);
261 LookAt = String.Format("[r{0},r{1},r{2}]", lookAt.X, lookAt.Y, lookAt.Z); 265 LookAt = String.Format("[r{0},r{1},r{2}]", lookAt.X, lookAt.Y, lookAt.Z);
262 266
263 FillOutRegionData(destination); 267 FillOutRegionData(destination);
268 // m_log.DebugFormat("[LOGIN RESPONSE] LLLoginResponse create. sizeX=<{0},{1}>", RegionSizeX, RegionSizeY);
264 269
265 FillOutSeedCap(aCircuit, destination, clientIP); 270 FillOutSeedCap(aCircuit, destination, clientIP);
266 271
@@ -387,6 +392,8 @@ namespace OpenSim.Services.LLLoginService
387 SimPort = (uint)endPoint.Port; 392 SimPort = (uint)endPoint.Port;
388 RegionX = (uint)destination.RegionLocX; 393 RegionX = (uint)destination.RegionLocX;
389 RegionY = (uint)destination.RegionLocY; 394 RegionY = (uint)destination.RegionLocY;
395 RegionSizeX = destination.RegionSizeX;
396 RegionSizeY = destination.RegionSizeY;
390 } 397 }
391 398
392 private void FillOutSeedCap(AgentCircuitData aCircuit, GridRegion destination, IPEndPoint ipepClient) 399 private void FillOutSeedCap(AgentCircuitData aCircuit, GridRegion destination, IPEndPoint ipepClient)
@@ -470,6 +477,7 @@ namespace OpenSim.Services.LLLoginService
470 searchURL = String.Empty; 477 searchURL = String.Empty;
471 478
472 currency = String.Empty; 479 currency = String.Empty;
480 ClassifiedFee = "0";
473 } 481 }
474 482
475 483
@@ -533,6 +541,9 @@ namespace OpenSim.Services.LLLoginService
533 responseData["message"] = welcomeMessage; 541 responseData["message"] = welcomeMessage;
534 responseData["region_x"] = (Int32)(RegionX); 542 responseData["region_x"] = (Int32)(RegionX);
535 responseData["region_y"] = (Int32)(RegionY); 543 responseData["region_y"] = (Int32)(RegionY);
544 responseData["region_size_x"] = (Int32)RegionSizeX;
545 responseData["region_size_y"] = (Int32)RegionSizeY;
546 // m_log.DebugFormat("[LOGIN RESPONSE] returning sizeX=<{0},{1}>", RegionSizeX, RegionSizeY);
536 547
537 if (searchURL != String.Empty) 548 if (searchURL != String.Empty)
538 responseData["search"] = searchURL; 549 responseData["search"] = searchURL;
@@ -543,6 +554,12 @@ namespace OpenSim.Services.LLLoginService
543 if (profileURL != String.Empty) 554 if (profileURL != String.Empty)
544 responseData["profile-server-url"] = profileURL; 555 responseData["profile-server-url"] = profileURL;
545 556
557 if (DestinationsURL != String.Empty)
558 responseData["destination_guide_url"] = DestinationsURL;
559
560 if (AvatarsURL != String.Empty)
561 responseData["avatar_picker_url"] = AvatarsURL;
562
546 // We need to send an openid_token back in the response too 563 // We need to send an openid_token back in the response too
547 if (openIDURL != String.Empty) 564 if (openIDURL != String.Empty)
548 responseData["openid_url"] = openIDURL; 565 responseData["openid_url"] = openIDURL;
@@ -557,6 +574,9 @@ namespace OpenSim.Services.LLLoginService
557 // responseData["real_currency"] = currency; 574 // responseData["real_currency"] = currency;
558 responseData["currency"] = currency; 575 responseData["currency"] = currency;
559 } 576 }
577
578 if (ClassifiedFee != String.Empty)
579 responseData["classified_fee"] = ClassifiedFee;
560 580
561 responseData["login"] = "true"; 581 responseData["login"] = "true";
562 582
@@ -662,6 +682,9 @@ namespace OpenSim.Services.LLLoginService
662 if (searchURL != String.Empty) 682 if (searchURL != String.Empty)
663 map["search"] = OSD.FromString(searchURL); 683 map["search"] = OSD.FromString(searchURL);
664 684
685 if (ClassifiedFee != String.Empty)
686 map["classified_fee"] = OSD.FromString(ClassifiedFee);
687
665 if (m_buddyList != null) 688 if (m_buddyList != null)
666 { 689 {
667 map["buddy-list"] = ArrayListToOSDArray(m_buddyList.ToArray()); 690 map["buddy-list"] = ArrayListToOSDArray(m_buddyList.ToArray());
@@ -917,6 +940,9 @@ namespace OpenSim.Services.LLLoginService
917 set { regionY = value; } 940 set { regionY = value; }
918 } 941 }
919 942
943 public int RegionSizeX { get; private set; }
944 public int RegionSizeY { get; private set; }
945
920 public string SunTexture 946 public string SunTexture
921 { 947 {
922 get { return sunTexture; } 948 get { return sunTexture; }
@@ -1073,6 +1099,22 @@ namespace OpenSim.Services.LLLoginService
1073 set { currency = value; } 1099 set { currency = value; }
1074 } 1100 }
1075 1101
1102 public string ClassifiedFee
1103 {
1104 get { return classifiedFee; }
1105 set { classifiedFee = value; }
1106 }
1107
1108 public string DestinationsURL
1109 {
1110 get; set;
1111 }
1112
1113 public string AvatarsURL
1114 {
1115 get; set;
1116 }
1117
1076 #endregion 1118 #endregion
1077 1119
1078 public class UserInfo 1120 public class UserInfo
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index ede2353..ed62c43 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -50,6 +50,8 @@ namespace OpenSim.Services.LLLoginService
50 public class LLLoginService : ILoginService 50 public class LLLoginService : ILoginService
51 { 51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 private static readonly string LogHeader = "[LLOGIN SERVICE]";
54
53 private static bool Initialized = false; 55 private static bool Initialized = false;
54 56
55 protected IUserAccountService m_UserAccountService; 57 protected IUserAccountService m_UserAccountService;
@@ -78,6 +80,9 @@ namespace OpenSim.Services.LLLoginService
78 protected string m_OpenIDURL; 80 protected string m_OpenIDURL;
79 protected string m_SearchURL; 81 protected string m_SearchURL;
80 protected string m_Currency; 82 protected string m_Currency;
83 protected string m_ClassifiedFee;
84 protected string m_DestinationGuide;
85 protected string m_AvatarPicker;
81 86
82 protected string m_AllowedClients; 87 protected string m_AllowedClients;
83 protected string m_DeniedClients; 88 protected string m_DeniedClients;
@@ -117,6 +122,9 @@ namespace OpenSim.Services.LLLoginService
117 m_OpenIDURL = m_LoginServerConfig.GetString("OpenIDServerURL", String.Empty); 122 m_OpenIDURL = m_LoginServerConfig.GetString("OpenIDServerURL", String.Empty);
118 m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty); 123 m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty);
119 m_Currency = m_LoginServerConfig.GetString("Currency", string.Empty); 124 m_Currency = m_LoginServerConfig.GetString("Currency", string.Empty);
125 m_ClassifiedFee = m_LoginServerConfig.GetString("ClassifiedFee", string.Empty);
126 m_DestinationGuide = m_LoginServerConfig.GetString ("DestinationGuide", string.Empty);
127 m_AvatarPicker = m_LoginServerConfig.GetString ("AvatarPicker", string.Empty);
120 128
121 m_AllowedClients = m_LoginServerConfig.GetString("AllowedClients", string.Empty); 129 m_AllowedClients = m_LoginServerConfig.GetString("AllowedClients", string.Empty);
122 m_DeniedClients = m_LoginServerConfig.GetString("DeniedClients", string.Empty); 130 m_DeniedClients = m_LoginServerConfig.GetString("DeniedClients", string.Empty);
@@ -391,6 +399,7 @@ namespace OpenSim.Services.LLLoginService
391 if (guinfo == null) 399 if (guinfo == null)
392 { 400 {
393 // something went wrong, make something up, so that we don't have to test this anywhere else 401 // something went wrong, make something up, so that we don't have to test this anywhere else
402 m_log.DebugFormat("{0} Failed to fetch GridUserInfo. Creating empty GridUserInfo as home", LogHeader);
394 guinfo = new GridUserInfo(); 403 guinfo = new GridUserInfo();
395 guinfo.LastPosition = guinfo.HomePosition = new Vector3(128, 128, 30); 404 guinfo.LastPosition = guinfo.HomePosition = new Vector3(128, 128, 30);
396 } 405 }
@@ -461,7 +470,8 @@ namespace OpenSim.Services.LLLoginService
461 = new LLLoginResponse( 470 = new LLLoginResponse(
462 account, aCircuit, guinfo, destination, inventorySkel, friendsList, m_LibraryService, 471 account, aCircuit, guinfo, destination, inventorySkel, friendsList, m_LibraryService,
463 where, startLocation, position, lookAt, gestures, m_WelcomeMessage, home, clientIP, 472 where, startLocation, position, lookAt, gestures, m_WelcomeMessage, home, clientIP,
464 m_MapTileURL, m_ProfileURL, m_OpenIDURL, m_SearchURL, m_Currency, m_DSTZone, realID); 473 m_MapTileURL, m_ProfileURL, m_OpenIDURL, m_SearchURL, m_Currency, m_DSTZone,
474 m_DestinationGuide, m_AvatarPicker, realID, m_ClassifiedFee);
465 475
466 m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to {0} {1}", firstName, lastName); 476 m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to {0} {1}", firstName, lastName);
467 477
@@ -934,7 +944,7 @@ namespace OpenSim.Services.LLLoginService
934 private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason) 944 private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason)
935 { 945 {
936 m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName); 946 m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName);
937 if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, clientIP, out reason)) 947 if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, true, out reason))
938 return true; 948 return true;
939 return false; 949 return false;
940 } 950 }
diff --git a/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs b/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs
index 0a6daee..c373351 100644
--- a/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/LLLoginService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs
index e2f256f..31e147b 100644
--- a/OpenSim/Services/MapImageService/MapImageService.cs
+++ b/OpenSim/Services/MapImageService/MapImageService.cs
@@ -86,7 +86,7 @@ namespace OpenSim.Services.MapImageService
86 { 86 {
87 Bitmap waterTile = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH); 87 Bitmap waterTile = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH);
88 FillImage(waterTile, m_Watercolor); 88 FillImage(waterTile, m_Watercolor);
89 waterTile.Save(m_WaterTileFile); 89 waterTile.Save(m_WaterTileFile, ImageFormat.Jpeg);
90 } 90 }
91 } 91 }
92 } 92 }
diff --git a/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs b/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs
index 19936e5..edadb26 100644
--- a/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/MapImageService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs b/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs
index 5d433df..3bfd1fc 100644
--- a/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/PresenceService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/UserAccountService/GridUserService.cs b/OpenSim/Services/UserAccountService/GridUserService.cs
index 43fa04b..bef1691 100644
--- a/OpenSim/Services/UserAccountService/GridUserService.cs
+++ b/OpenSim/Services/UserAccountService/GridUserService.cs
@@ -46,12 +46,66 @@ namespace OpenSim.Services.UserAccountService
46 46
47 public GridUserService(IConfigSource config) : base(config) 47 public GridUserService(IConfigSource config) : base(config)
48 { 48 {
49 m_log.Debug("[USER GRID SERVICE]: Starting user grid service"); 49 m_log.Debug("[GRID USER SERVICE]: Starting user grid service");
50
51 MainConsole.Instance.Commands.AddCommand(
52 "Users", false,
53 "show grid users online",
54 "show grid users online",
55 "Show number of grid users registered as online.",
56 "This number may not be accurate as a region may crash or not be cleanly shutdown and leave grid users shown as online\n."
57 + "For this reason, users online for more than 5 days are not currently counted",
58 HandleShowGridUsersOnline);
59 }
60
61 protected void HandleShowGridUsersOnline(string module, string[] cmdparams)
62 {
63// if (cmdparams.Length != 4)
64// {
65// MainConsole.Instance.Output("Usage: show grid users online");
66// return;
67// }
68
69// int onlineCount;
70 int onlineRecentlyCount = 0;
71
72 DateTime now = DateTime.UtcNow;
73
74 foreach (GridUserData gu in m_Database.GetAll(""))
75 {
76 if (bool.Parse(gu.Data["Online"]))
77 {
78// onlineCount++;
79
80 int unixLoginTime = int.Parse(gu.Data["Login"]);
81
82 if ((now - Util.ToDateTime(unixLoginTime)).Days < 5)
83 onlineRecentlyCount++;
84 }
85 }
86
87 MainConsole.Instance.OutputFormat("Users online: {0}", onlineRecentlyCount);
50 } 88 }
51 89
52 public virtual GridUserInfo GetGridUserInfo(string userID) 90 public virtual GridUserInfo GetGridUserInfo(string userID)
53 { 91 {
54 GridUserData d = m_Database.Get(userID); 92 GridUserData d = null;
93 if (userID.Length > 36) // it's a UUI
94 d = m_Database.Get(userID);
95 else // it's a UUID
96 {
97 GridUserData[] ds = m_Database.GetAll(userID);
98 if (ds == null)
99 return null;
100
101 if (ds.Length > 0)
102 {
103 d = ds[0];
104 foreach (GridUserData dd in ds)
105 if (dd.UserID.Length > d.UserID.Length) // find the longest
106 d = dd;
107 }
108 }
55 109
56 if (d == null) 110 if (d == null)
57 return null; 111 return null;
@@ -73,7 +127,7 @@ namespace OpenSim.Services.UserAccountService
73 return info; 127 return info;
74 } 128 }
75 129
76 public GridUserInfo[] GetGridUserInfo(string[] userIDs) 130 public virtual GridUserInfo[] GetGridUserInfo(string[] userIDs)
77 { 131 {
78 List<GridUserInfo> ret = new List<GridUserInfo>(); 132 List<GridUserInfo> ret = new List<GridUserInfo>();
79 133
@@ -140,7 +194,8 @@ namespace OpenSim.Services.UserAccountService
140 194
141 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) 195 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
142 { 196 {
143 //m_log.DebugFormat("[Grid User Service]: SetLastPosition for {0}", userID); 197// m_log.DebugFormat("[GRID USER SERVICE]: SetLastPosition for {0}", userID);
198
144 GridUserData d = m_Database.Get(userID); 199 GridUserData d = m_Database.Get(userID);
145 if (d == null) 200 if (d == null)
146 { 201 {
diff --git a/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs b/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs
index e7d2d6f..16ae6bd 100644
--- a/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs
+++ b/OpenSim/Services/UserAccountService/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Services/UserProfilesService/UserProfilesService.cs b/OpenSim/Services/UserProfilesService/UserProfilesService.cs
new file mode 100644
index 0000000..038e993
--- /dev/null
+++ b/OpenSim/Services/UserProfilesService/UserProfilesService.cs
@@ -0,0 +1,262 @@
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.Reflection;
30using System.Text;
31using Nini.Config;
32using log4net;
33using OpenSim.Server.Base;
34using OpenSim.Services.Interfaces;
35using OpenSim.Services.UserAccountService;
36using OpenSim.Data;
37using OpenMetaverse;
38using OpenMetaverse.StructuredData;
39using OpenSim.Framework;
40using OpenSim.Services.UserAccountService;
41
42namespace OpenSim.Services.ProfilesService
43{
44 public class UserProfilesService: UserProfilesServiceBase, IUserProfilesService
45 {
46 static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 IUserAccountService userAccounts;
51 IAuthenticationService authService;
52
53 public UserProfilesService(IConfigSource config, string configName):
54 base(config, configName)
55 {
56 IConfig Config = config.Configs[configName];
57 if (Config == null)
58 {
59 m_log.Warn("[PROFILES]: No configuration found!");
60 return;
61 }
62 Object[] args = null;
63
64 args = new Object[] { config };
65 string accountService = Config.GetString("UserAccountService", String.Empty);
66 if (accountService != string.Empty)
67 userAccounts = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args);
68
69 args = new Object[] { config };
70 string authServiceConfig = Config.GetString("AuthenticationServiceModule", String.Empty);
71 if (accountService != string.Empty)
72 authService = ServerUtils.LoadPlugin<IAuthenticationService>(authServiceConfig, args);
73 }
74
75 #region Classifieds
76 public OSD AvatarClassifiedsRequest(UUID creatorId)
77 {
78 OSDArray records = ProfilesData.GetClassifiedRecords(creatorId);
79
80 return records;
81 }
82
83 public bool ClassifiedUpdate(UserClassifiedAdd ad, ref string result)
84 {
85 if(!ProfilesData.UpdateClassifiedRecord(ad, ref result))
86 {
87 return false;
88 }
89 result = "success";
90 return true;
91 }
92
93 public bool ClassifiedDelete(UUID recordId)
94 {
95 if(ProfilesData.DeleteClassifiedRecord(recordId))
96 return true;
97
98 return false;
99 }
100
101 public bool ClassifiedInfoRequest(ref UserClassifiedAdd ad, ref string result)
102 {
103 if(ProfilesData.GetClassifiedInfo(ref ad, ref result))
104 return true;
105
106 return false;
107 }
108 #endregion Classifieds
109
110 #region Picks
111 public OSD AvatarPicksRequest(UUID creatorId)
112 {
113 OSDArray records = ProfilesData.GetAvatarPicks(creatorId);
114
115 return records;
116 }
117
118 public bool PickInfoRequest(ref UserProfilePick pick, ref string result)
119 {
120 pick = ProfilesData.GetPickInfo(pick.CreatorId, pick.PickId);
121 result = "OK";
122 return true;
123 }
124
125 public bool PicksUpdate(ref UserProfilePick pick, ref string result)
126 {
127 return ProfilesData.UpdatePicksRecord(pick);
128 }
129
130 public bool PicksDelete(UUID pickId)
131 {
132 return ProfilesData.DeletePicksRecord(pickId);
133 }
134 #endregion Picks
135
136 #region Notes
137 public bool AvatarNotesRequest(ref UserProfileNotes note)
138 {
139 return ProfilesData.GetAvatarNotes(ref note);
140 }
141
142 public bool NotesUpdate(ref UserProfileNotes note, ref string result)
143 {
144 return ProfilesData.UpdateAvatarNotes(ref note, ref result);
145 }
146 #endregion Notes
147
148 #region Profile Properties
149 public bool AvatarPropertiesRequest(ref UserProfileProperties prop, ref string result)
150 {
151 return ProfilesData.GetAvatarProperties(ref prop, ref result);
152 }
153
154 public bool AvatarPropertiesUpdate(ref UserProfileProperties prop, ref string result)
155 {
156 return ProfilesData.UpdateAvatarProperties(ref prop, ref result);
157 }
158 #endregion Profile Properties
159
160 #region Interests
161 public bool AvatarInterestsUpdate(UserProfileProperties prop, ref string result)
162 {
163 return ProfilesData.UpdateAvatarInterests(prop, ref result);
164 }
165 #endregion Interests
166
167 /*
168 #region User Preferences
169 public bool UserPreferencesUpdate(ref UserPreferences pref, ref string result)
170 {
171 if(string.IsNullOrEmpty(pref.EMail))
172 {
173 UserAccount account = new UserAccount();
174 if(userAccounts is UserAccountService.UserAccountService)
175 {
176 try
177 {
178 account = userAccounts.GetUserAccount(UUID.Zero, pref.UserId);
179 if(string.IsNullOrEmpty(account.Email))
180 {
181 result = "No Email address on record!";
182 return false;
183 }
184 else
185 pref.EMail = account.Email;
186 }
187 catch
188 {
189 m_log.Info ("[PROFILES]: UserAccountService Exception: Could not get user account");
190 result = "Missing Email address!";
191 return false;
192 }
193 }
194 else
195 {
196 m_log.Info ("[PROFILES]: UserAccountService: Could not get user account");
197 result = "Missing Email address!";
198 return false;
199 }
200 }
201 return ProfilesData.UpdateUserPreferences(ref pref, ref result);
202 }
203
204 public bool UserPreferencesRequest(ref UserPreferences pref, ref string result)
205 {
206 if(string.IsNullOrEmpty(pref.EMail))
207 {
208 UserAccount account = new UserAccount();
209 if(userAccounts is UserAccountService.UserAccountService)
210 {
211 try
212 {
213 account = userAccounts.GetUserAccount(UUID.Zero, pref.UserId);
214 if(string.IsNullOrEmpty(account.Email))
215 {
216 result = "No Email address on record!";
217 return false;
218 }
219 else
220 pref.EMail = account.Email;
221 }
222 catch
223 {
224 m_log.Info ("[PROFILES]: UserAccountService Exception: Could not get user account");
225 result = "Missing Email address!";
226 return false;
227 }
228 }
229 else
230 {
231 m_log.Info ("[PROFILES]: UserAccountService: Could not get user account");
232 result = "Missing Email address!";
233 return false;
234 }
235 }
236 return ProfilesData.GetUserPreferences(ref pref, ref result);
237 }
238 #endregion User Preferences
239 */
240
241 #region Utility
242 public OSD AvatarImageAssetsRequest(UUID avatarId)
243 {
244 OSDArray records = ProfilesData.GetUserImageAssets(avatarId);
245 return records;
246 }
247 #endregion Utility
248
249 #region UserData
250 public bool RequestUserAppData(ref UserAppData prop, ref string result)
251 {
252 return ProfilesData.GetUserAppData(ref prop, ref result);
253 }
254
255 public bool SetUserAppData(UserAppData prop, ref string result)
256 {
257 return true;
258 }
259 #endregion UserData
260 }
261}
262
diff --git a/OpenSim/Services/UserProfilesService/UserProfilesServiceBase.cs b/OpenSim/Services/UserProfilesService/UserProfilesServiceBase.cs
new file mode 100644
index 0000000..927f7c9
--- /dev/null
+++ b/OpenSim/Services/UserProfilesService/UserProfilesServiceBase.cs
@@ -0,0 +1,86 @@
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.Reflection;
30using Nini.Config;
31using log4net;
32using OpenSim.Services.Base;
33using OpenSim.Data;
34
35namespace OpenSim.Services.ProfilesService
36{
37 public class UserProfilesServiceBase: ServiceBase
38 {
39 static readonly ILog m_log =
40 LogManager.GetLogger(
41 MethodBase.GetCurrentMethod().DeclaringType);
42
43 public IProfilesData ProfilesData;
44
45 public string ConfigName
46 {
47 get; private set;
48 }
49
50 public UserProfilesServiceBase(IConfigSource config, string configName):
51 base(config)
52 {
53 if(string.IsNullOrEmpty(configName))
54 {
55 m_log.WarnFormat("[PROFILES]: Configuration section not given!");
56 return;
57 }
58
59 string dllName = String.Empty;
60 string connString = null;
61 string realm = String.Empty;
62
63 IConfig dbConfig = config.Configs["DatabaseService"];
64 if (dbConfig != null)
65 {
66 if (dllName == String.Empty)
67 dllName = dbConfig.GetString("StorageProvider", String.Empty);
68 if (string.IsNullOrEmpty(connString))
69 connString = dbConfig.GetString("ConnectionString", String.Empty);
70 }
71
72 IConfig ProfilesConfig = config.Configs[configName];
73 if (ProfilesConfig != null)
74 {
75 connString = ProfilesConfig.GetString("ConnectionString", connString);
76 realm = ProfilesConfig.GetString("Realm", realm);
77 }
78
79 ProfilesData = LoadPlugin<IProfilesData>(dllName, new Object[] { connString });
80 if (ProfilesData == null)
81 throw new Exception("Could not find a storage interface in the given module");
82
83 }
84 }
85}
86
diff --git a/OpenSim/Tests/Clients/Assets/AssetsClient.cs b/OpenSim/Tests/Clients/Assets/AssetsClient.cs
new file mode 100644
index 0000000..e988d0e
--- /dev/null
+++ b/OpenSim/Tests/Clients/Assets/AssetsClient.cs
@@ -0,0 +1,126 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Text;
32using System.Reflection;
33using System.Threading;
34
35using OpenMetaverse;
36using log4net;
37using log4net.Appender;
38using log4net.Layout;
39
40using OpenSim.Framework;
41using OpenSim.Services.Interfaces;
42using OpenSim.Services.Connectors;
43
44namespace OpenSim.Tests.Clients.AssetsClient
45{
46 public class AssetsClient
47 {
48 private static readonly ILog m_log =
49 LogManager.GetLogger(
50 MethodBase.GetCurrentMethod().DeclaringType);
51
52 private static int m_MaxThreadID = 0;
53 private static readonly int NREQS = 150;
54 private static int m_NReceived = 0;
55
56 public static void Main(string[] args)
57 {
58 ConsoleAppender consoleAppender = new ConsoleAppender();
59 consoleAppender.Layout =
60 new PatternLayout("[%thread] - %message%newline");
61 log4net.Config.BasicConfigurator.Configure(consoleAppender);
62
63 string serverURI = "http://127.0.0.1:8003";
64 if (args.Length > 1)
65 serverURI = args[1];
66 int max1, max2;
67 ThreadPool.GetMaxThreads(out max1, out max2);
68 m_log.InfoFormat("[ASSET CLIENT]: Connecting to {0} max threads = {1} - {2}", serverURI, max1, max2);
69 ThreadPool.GetMinThreads(out max1, out max2);
70 m_log.InfoFormat("[ASSET CLIENT]: Connecting to {0} min threads = {1} - {2}", serverURI, max1, max2);
71
72 if (!ThreadPool.SetMinThreads(1, 1))
73 m_log.WarnFormat("[ASSET CLIENT]: Failed to set min threads");
74
75 if (!ThreadPool.SetMaxThreads(10, 3))
76 m_log.WarnFormat("[ASSET CLIENT]: Failed to set max threads");
77
78 ThreadPool.GetMaxThreads(out max1, out max2);
79 m_log.InfoFormat("[ASSET CLIENT]: Post set max threads = {1} - {2}", serverURI, max1, max2);
80 ThreadPool.GetMinThreads(out max1, out max2);
81 m_log.InfoFormat("[ASSET CLIENT]: Post set min threads = {1} - {2}", serverURI, max1, max2);
82
83 ServicePointManager.DefaultConnectionLimit = 12;
84
85 AssetServicesConnector m_Connector = new AssetServicesConnector(serverURI);
86 m_Connector.MaxAssetRequestConcurrency = 30;
87
88 for (int i = 0; i < NREQS; i++)
89 {
90 UUID uuid = UUID.Random();
91 m_Connector.Get(uuid.ToString(), null, ResponseReceived);
92 m_log.InfoFormat("[ASSET CLIENT]: [{0}] requested asset {1}", i, uuid);
93 }
94
95 for (int i = 0; i < 500; i++)
96 {
97 var x = i;
98 ThreadPool.QueueUserWorkItem(delegate
99 {
100 Dummy(x);
101 });
102 }
103
104 Thread.Sleep(30 * 1000);
105 m_log.InfoFormat("[ASSET CLIENT]: Received responses {0}", m_NReceived);
106 }
107
108 private static void ResponseReceived(string id, Object sender, AssetBase asset)
109 {
110 if (Thread.CurrentThread.ManagedThreadId > m_MaxThreadID)
111 m_MaxThreadID = Thread.CurrentThread.ManagedThreadId;
112 int max1, max2;
113 ThreadPool.GetAvailableThreads(out max1, out max2);
114 m_log.InfoFormat("[ASSET CLIENT]: Received asset {0} ({1}) ({2}-{3}) {4}", id, m_MaxThreadID, max1, max2, DateTime.Now.ToString("hh:mm:ss"));
115 m_NReceived++;
116 }
117
118 private static void Dummy(int i)
119 {
120 int max1, max2;
121 ThreadPool.GetAvailableThreads(out max1, out max2);
122 m_log.InfoFormat("[ASSET CLIENT]: ({0}) Hello! {1} - {2} {3}", i, max1, max2, DateTime.Now.ToString("hh:mm:ss"));
123 Thread.Sleep(2000);
124 }
125 }
126}
diff --git a/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs b/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs
index 6cc7ff2..52a17e7 100644
--- a/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/EntityTransferHelpers.cs
@@ -31,6 +31,7 @@ using System.IO;
31using System.Net; 31using System.Net;
32using System.Reflection; 32using System.Reflection;
33using System.Text; 33using System.Text;
34using System.Threading;
34using log4net; 35using log4net;
35using Nini.Config; 36using Nini.Config;
36using NUnit.Framework; 37using NUnit.Framework;
@@ -59,7 +60,8 @@ namespace OpenSim.Tests.Common
59 /// A list that will be populated with any TestClients set up in response to 60 /// A list that will be populated with any TestClients set up in response to
60 /// being informed about a destination region. 61 /// being informed about a destination region.
61 /// </param> 62 /// </param>
62 public static void SetUpInformClientOfNeighbour(TestClient tc, List<TestClient> neighbourTcs) 63 public static void SetupInformClientOfNeighbourTriggersNeighbourClientCreate(
64 TestClient tc, List<TestClient> neighbourTcs)
63 { 65 {
64 // XXX: Confusingly, this is also used for non-neighbour notification (as in teleports that do not use the 66 // XXX: Confusingly, this is also used for non-neighbour notification (as in teleports that do not use the
65 // event queue). 67 // event queue).
@@ -75,16 +77,51 @@ namespace OpenSim.Tests.Common
75 "[TEST CLIENT]: Processing inform client of neighbour located at {0},{1} at {2}", 77 "[TEST CLIENT]: Processing inform client of neighbour located at {0},{1} at {2}",
76 x, y, neighbourExternalEndPoint); 78 x, y, neighbourExternalEndPoint);
77 79
78 // In response to this message, we are going to make a teleport to the scene we've previous been told
79 // about by test code (this needs to be improved).
80 AgentCircuitData newAgent = tc.RequestClientInfo(); 80 AgentCircuitData newAgent = tc.RequestClientInfo();
81 81
82 Scene neighbourScene; 82 Scene neighbourScene;
83 SceneManager.Instance.TryGetScene(x, y, out neighbourScene); 83 SceneManager.Instance.TryGetScene(x, y, out neighbourScene);
84 84
85 TestClient neighbourTc = new TestClient(newAgent, neighbourScene, SceneManager.Instance); 85 TestClient neighbourTc = new TestClient(newAgent, neighbourScene);
86 neighbourTcs.Add(neighbourTc); 86 neighbourTcs.Add(neighbourTc);
87 neighbourScene.AddNewClient(neighbourTc, PresenceType.User); 87 neighbourScene.AddNewAgent(neighbourTc, PresenceType.User);
88 };
89 }
90
91 /// <summary>
92 /// Set up correct handling of the InformClientOfNeighbour call from the source region that triggers the
93 /// viewer to setup a connection with the destination region.
94 /// </summary>
95 /// <param name='tc'></param>
96 /// <param name='neighbourTcs'>
97 /// A list that will be populated with any TestClients set up in response to
98 /// being informed about a destination region.
99 /// </param>
100 public static void SetupSendRegionTeleportTriggersDestinationClientCreateAndCompleteMovement(
101 TestClient client, List<TestClient> destinationClients)
102 {
103 client.OnTestClientSendRegionTeleport
104 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL) =>
105 {
106 uint x, y;
107 Utils.LongToUInts(regionHandle, out x, out y);
108 x /= Constants.RegionSize;
109 y /= Constants.RegionSize;
110
111 m_log.DebugFormat(
112 "[TEST CLIENT]: Processing send region teleport for destination at {0},{1} at {2}",
113 x, y, regionExternalEndPoint);
114
115 AgentCircuitData newAgent = client.RequestClientInfo();
116
117 Scene destinationScene;
118 SceneManager.Instance.TryGetScene(x, y, out destinationScene);
119
120 TestClient destinationClient = new TestClient(newAgent, destinationScene);
121 destinationClients.Add(destinationClient);
122 destinationScene.AddNewAgent(destinationClient, PresenceType.User);
123
124 ThreadPool.UnsafeQueueUserWorkItem(o => destinationClient.CompleteMovement(), null);
88 }; 125 };
89 } 126 }
90 } 127 }
diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
index bdd9093..4cdfe98 100644
--- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
@@ -447,9 +447,6 @@ namespace OpenSim.Tests.Common
447 /// Add a root agent where the details of the agent connection (apart from the id) are unimportant for the test 447 /// Add a root agent where the details of the agent connection (apart from the id) are unimportant for the test
448 /// </summary> 448 /// </summary>
449 /// <remarks> 449 /// <remarks>
450 /// This can be used for tests where there is only one region or where there are multiple non-neighbour regions
451 /// and teleport doesn't take place.
452 ///
453 /// XXX: Use the version of this method that takes the UserAccount structure wherever possible - this will 450 /// XXX: Use the version of this method that takes the UserAccount structure wherever possible - this will
454 /// make the agent circuit data (e.g. first, lastname) consistent with the user account data. 451 /// make the agent circuit data (e.g. first, lastname) consistent with the user account data.
455 /// </remarks> 452 /// </remarks>
@@ -462,22 +459,6 @@ namespace OpenSim.Tests.Common
462 } 459 }
463 460
464 /// <summary> 461 /// <summary>
465 /// Add a root agent where the details of the agent connection (apart from the id) are unimportant for the test
466 /// </summary>
467 /// <remarks>
468 /// XXX: Use the version of this method that takes the UserAccount structure wherever possible - this will
469 /// make the agent circuit data (e.g. first, lastname) consistent with the user account data.
470 /// </remarks>
471 /// <param name="scene"></param>
472 /// <param name="agentId"></param>
473 /// <param name="sceneManager"></param>
474 /// <returns></returns>
475 public static ScenePresence AddScenePresence(Scene scene, UUID agentId, SceneManager sceneManager)
476 {
477 return AddScenePresence(scene, GenerateAgentData(agentId), sceneManager);
478 }
479
480 /// <summary>
481 /// Add a root agent. 462 /// Add a root agent.
482 /// </summary> 463 /// </summary>
483 /// <param name="scene"></param> 464 /// <param name="scene"></param>
@@ -508,31 +489,7 @@ namespace OpenSim.Tests.Common
508 /// <returns></returns> 489 /// <returns></returns>
509 public static ScenePresence AddScenePresence(Scene scene, AgentCircuitData agentData) 490 public static ScenePresence AddScenePresence(Scene scene, AgentCircuitData agentData)
510 { 491 {
511 return AddScenePresence(scene, agentData, null); 492 return AddScenePresence(scene, new TestClient(agentData, scene), agentData);
512 }
513
514 /// <summary>
515 /// Add a root agent.
516 /// </summary>
517 /// <remarks>
518 /// This function
519 ///
520 /// 1) Tells the scene that an agent is coming. Normally, the login service (local if standalone, from the
521 /// userserver if grid) would give initial login data back to the client and separately tell the scene that the
522 /// agent was coming.
523 ///
524 /// 2) Connects the agent with the scene
525 ///
526 /// This function performs actions equivalent with notifying the scene that an agent is
527 /// coming and then actually connecting the agent to the scene. The one step missed out is the very first
528 /// </remarks>
529 /// <param name="scene"></param>
530 /// <param name="agentData"></param>
531 /// <param name="sceneManager"></param>
532 /// <returns></returns>
533 public static ScenePresence AddScenePresence(Scene scene, AgentCircuitData agentData, SceneManager sceneManager)
534 {
535 return AddScenePresence(scene, new TestClient(agentData, scene, sceneManager), agentData, sceneManager);
536 } 493 }
537 494
538 /// <summary> 495 /// <summary>
@@ -552,10 +509,9 @@ namespace OpenSim.Tests.Common
552 /// </remarks> 509 /// </remarks>
553 /// <param name="scene"></param> 510 /// <param name="scene"></param>
554 /// <param name="agentData"></param> 511 /// <param name="agentData"></param>
555 /// <param name="sceneManager"></param>
556 /// <returns></returns> 512 /// <returns></returns>
557 public static ScenePresence AddScenePresence( 513 public static ScenePresence AddScenePresence(
558 Scene scene, IClientAPI client, AgentCircuitData agentData, SceneManager sceneManager) 514 Scene scene, IClientAPI client, AgentCircuitData agentData)
559 { 515 {
560 // We emulate the proper login sequence here by doing things in four stages 516 // We emulate the proper login sequence here by doing things in four stages
561 517
@@ -578,10 +534,6 @@ namespace OpenSim.Tests.Common
578 /// Introduce an agent into the scene by adding a new client. 534 /// Introduce an agent into the scene by adding a new client.
579 /// </summary> 535 /// </summary>
580 /// <returns>The scene presence added</returns> 536 /// <returns>The scene presence added</returns>
581 /// <param name='sceneManager'>
582 /// Scene manager. Can be null if there is only one region in the test or multiple regions that are not
583 /// neighbours and where no teleporting takes place.
584 /// </param>
585 /// <param name='scene'></param> 537 /// <param name='scene'></param>
586 /// <param name='testClient'></param> 538 /// <param name='testClient'></param>
587 /// <param name='agentData'></param> 539 /// <param name='agentData'></param>
@@ -596,7 +548,7 @@ namespace OpenSim.Tests.Common
596 Console.WriteLine("NewUserConnection failed: " + reason); 548 Console.WriteLine("NewUserConnection failed: " + reason);
597 549
598 // Stage 2: add the new client as a child agent to the scene 550 // Stage 2: add the new client as a child agent to the scene
599 scene.AddNewClient(client, PresenceType.User); 551 scene.AddNewAgent(client, PresenceType.User);
600 552
601 return scene.GetScenePresence(client.AgentId); 553 return scene.GetScenePresence(client.AgentId);
602 } 554 }
@@ -607,7 +559,7 @@ namespace OpenSim.Tests.Common
607 acd.child = true; 559 acd.child = true;
608 560
609 // XXX: ViaLogin may not be correct for child agents 561 // XXX: ViaLogin may not be correct for child agents
610 TestClient client = new TestClient(acd, scene, null); 562 TestClient client = new TestClient(acd, scene);
611 return IntroduceClientToScene(scene, client, acd, TeleportFlags.ViaLogin); 563 return IntroduceClientToScene(scene, client, acd, TeleportFlags.ViaLogin);
612 } 564 }
613 565
diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
index a1794c9..b3b75af 100644
--- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
@@ -218,12 +218,37 @@ namespace OpenSim.Tests.Common
218 public static InventoryFolderBase CreateInventoryFolder( 218 public static InventoryFolderBase CreateInventoryFolder(
219 IInventoryService inventoryService, UUID userId, string path, bool useExistingFolders) 219 IInventoryService inventoryService, UUID userId, string path, bool useExistingFolders)
220 { 220 {
221 return CreateInventoryFolder(inventoryService, userId, UUID.Random(), path, useExistingFolders);
222 }
223
224 /// <summary>
225 /// Create inventory folders starting from the user's root folder.
226 /// </summary>
227 /// <param name="inventoryService"></param>
228 /// <param name="userId"></param>
229 /// <param name="folderId"></param>
230 /// <param name="path">
231 /// The folders to create. Multiple folders can be specified on a path delimited by the PATH_DELIMITER
232 /// </param>
233 /// <param name="useExistingFolders">
234 /// If true, then folders in the path which already the same name are
235 /// used. This applies to the terminal folder as well.
236 /// If false, then all folders in the path are created, even if there is already a folder at a particular
237 /// level with the same name.
238 /// </param>
239 /// <returns>
240 /// The folder created. If the path contains multiple folders then the last one created is returned.
241 /// Will return null if the root folder could not be found.
242 /// </returns>
243 public static InventoryFolderBase CreateInventoryFolder(
244 IInventoryService inventoryService, UUID userId, UUID folderId, string path, bool useExistingFolders)
245 {
221 InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId); 246 InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId);
222 247
223 if (null == rootFolder) 248 if (null == rootFolder)
224 return null; 249 return null;
225 250
226 return CreateInventoryFolder(inventoryService, rootFolder, path, useExistingFolders); 251 return CreateInventoryFolder(inventoryService, folderId, rootFolder, path, useExistingFolders);
227 } 252 }
228 253
229 /// <summary> 254 /// <summary>
@@ -235,6 +260,7 @@ namespace OpenSim.Tests.Common
235 /// TODO: May need to make it an option to create duplicate folders. 260 /// TODO: May need to make it an option to create duplicate folders.
236 /// </remarks> 261 /// </remarks>
237 /// <param name="inventoryService"></param> 262 /// <param name="inventoryService"></param>
263 /// <param name="folderId">ID of the folder to create</param>
238 /// <param name="parentFolder"></param> 264 /// <param name="parentFolder"></param>
239 /// <param name="path"> 265 /// <param name="path">
240 /// The folder to create. 266 /// The folder to create.
@@ -249,7 +275,7 @@ namespace OpenSim.Tests.Common
249 /// The folder created. If the path contains multiple folders then the last one created is returned. 275 /// The folder created. If the path contains multiple folders then the last one created is returned.
250 /// </returns> 276 /// </returns>
251 public static InventoryFolderBase CreateInventoryFolder( 277 public static InventoryFolderBase CreateInventoryFolder(
252 IInventoryService inventoryService, InventoryFolderBase parentFolder, string path, bool useExistingFolders) 278 IInventoryService inventoryService, UUID folderId, InventoryFolderBase parentFolder, string path, bool useExistingFolders)
253 { 279 {
254 string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); 280 string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
255 281
@@ -262,9 +288,16 @@ namespace OpenSim.Tests.Common
262 { 288 {
263// Console.WriteLine("Creating folder {0} at {1}", components[0], parentFolder.Name); 289// Console.WriteLine("Creating folder {0} at {1}", components[0], parentFolder.Name);
264 290
291 UUID folderIdForCreate;
292
293 if (components.Length > 1)
294 folderIdForCreate = UUID.Random();
295 else
296 folderIdForCreate = folderId;
297
265 folder 298 folder
266 = new InventoryFolderBase( 299 = new InventoryFolderBase(
267 UUID.Random(), components[0], parentFolder.Owner, (short)AssetType.Unknown, parentFolder.ID, 0); 300 folderIdForCreate, components[0], parentFolder.Owner, (short)AssetType.Unknown, parentFolder.ID, 0);
268 301
269 inventoryService.AddFolder(folder); 302 inventoryService.AddFolder(folder);
270 } 303 }
@@ -274,7 +307,7 @@ namespace OpenSim.Tests.Common
274// } 307// }
275 308
276 if (components.Length > 1) 309 if (components.Length > 1)
277 return CreateInventoryFolder(inventoryService, folder, components[1], useExistingFolders); 310 return CreateInventoryFolder(inventoryService, folderId, folder, components[1], useExistingFolders);
278 else 311 else
279 return folder; 312 return folder;
280 } 313 }
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index dce2fd7..52e0134 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -47,9 +47,9 @@ namespace OpenSim.Tests.Common.Mock
47 EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing"); 47 EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing");
48 48
49 private Scene m_scene; 49 private Scene m_scene;
50 private SceneManager m_sceneManager;
51 50
52 // Properties so that we can get at received data for test purposes 51 // Properties so that we can get at received data for test purposes
52 public List<uint> ReceivedKills { get; private set; }
53 public List<UUID> ReceivedOfflineNotifications { get; private set; } 53 public List<UUID> ReceivedOfflineNotifications { get; private set; }
54 public List<UUID> ReceivedOnlineNotifications { get; private set; } 54 public List<UUID> ReceivedOnlineNotifications { get; private set; }
55 public List<UUID> ReceivedFriendshipTerminations { get; private set; } 55 public List<UUID> ReceivedFriendshipTerminations { get; private set; }
@@ -61,6 +61,12 @@ namespace OpenSim.Tests.Common.Mock
61 // Test client specific events - for use by tests to implement some IClientAPI behaviour. 61 // Test client specific events - for use by tests to implement some IClientAPI behaviour.
62 public event Action<RegionInfo, Vector3, Vector3> OnReceivedMoveAgentIntoRegion; 62 public event Action<RegionInfo, Vector3, Vector3> OnReceivedMoveAgentIntoRegion;
63 public event Action<ulong, IPEndPoint> OnTestClientInformClientOfNeighbour; 63 public event Action<ulong, IPEndPoint> OnTestClientInformClientOfNeighbour;
64 public event TestClientOnSendRegionTeleportDelegate OnTestClientSendRegionTeleport;
65 public event Action<GridInstantMessage> OnReceivedInstantMessage;
66
67 public delegate void TestClientOnSendRegionTeleportDelegate(
68 ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
69 uint locationID, uint flags, string capsURL);
64 70
65// disable warning: public events, part of the public API 71// disable warning: public events, part of the public API
66#pragma warning disable 67 72#pragma warning disable 67
@@ -106,6 +112,7 @@ namespace OpenSim.Tests.Common.Mock
106 public event Action<IClientAPI, bool> OnCompleteMovementToRegion; 112 public event Action<IClientAPI, bool> OnCompleteMovementToRegion;
107 public event UpdateAgent OnPreAgentUpdate; 113 public event UpdateAgent OnPreAgentUpdate;
108 public event UpdateAgent OnAgentUpdate; 114 public event UpdateAgent OnAgentUpdate;
115 public event UpdateAgent OnAgentCameraUpdate;
109 public event AgentRequestSit OnAgentRequestSit; 116 public event AgentRequestSit OnAgentRequestSit;
110 public event AgentSit OnAgentSit; 117 public event AgentSit OnAgentSit;
111 public event AvatarPickerRequest OnAvatarPickerRequest; 118 public event AvatarPickerRequest OnAvatarPickerRequest;
@@ -197,6 +204,7 @@ namespace OpenSim.Tests.Common.Mock
197 public event EstateCovenantRequest OnEstateCovenantRequest; 204 public event EstateCovenantRequest OnEstateCovenantRequest;
198 public event EstateChangeInfo OnEstateChangeInfo; 205 public event EstateChangeInfo OnEstateChangeInfo;
199 public event EstateManageTelehub OnEstateManageTelehub; 206 public event EstateManageTelehub OnEstateManageTelehub;
207 public event CachedTextureRequest OnCachedTextureRequest;
200 208
201 public event ObjectDuplicateOnRay OnObjectDuplicateOnRay; 209 public event ObjectDuplicateOnRay OnObjectDuplicateOnRay;
202 210
@@ -435,33 +443,21 @@ namespace OpenSim.Tests.Common.Mock
435 /// <summary> 443 /// <summary>
436 /// Constructor 444 /// Constructor
437 /// </summary> 445 /// </summary>
438 /// <remarks>
439 /// Can be used for a test where there is only one region or where there are multiple regions that are not
440 /// neighbours and where no teleporting takes place. In other situations, the constructor that takes in a
441 /// scene manager should be used.
442 /// </remarks>
443 /// <param name="agentData"></param>
444 /// <param name="scene"></param>
445 public TestClient(AgentCircuitData agentData, Scene scene) : this(agentData, scene, null) {}
446
447 /// <summary>
448 /// Constructor
449 /// </summary>
450 /// <param name="agentData"></param> 446 /// <param name="agentData"></param>
451 /// <param name="scene"></param> 447 /// <param name="scene"></param>
452 /// <param name="sceneManager"></param> 448 /// <param name="sceneManager"></param>
453 public TestClient(AgentCircuitData agentData, Scene scene, SceneManager sceneManager) 449 public TestClient(AgentCircuitData agentData, Scene scene)
454 { 450 {
455 m_agentId = agentData.AgentID; 451 m_agentId = agentData.AgentID;
456 m_firstName = agentData.firstname; 452 m_firstName = agentData.firstname;
457 m_lastName = agentData.lastname; 453 m_lastName = agentData.lastname;
458 m_circuitCode = agentData.circuitcode; 454 m_circuitCode = agentData.circuitcode;
459 m_scene = scene; 455 m_scene = scene;
460 m_sceneManager = sceneManager;
461 SessionId = agentData.SessionID; 456 SessionId = agentData.SessionID;
462 SecureSessionId = agentData.SecureSessionID; 457 SecureSessionId = agentData.SecureSessionID;
463 CapsSeedUrl = agentData.CapsPath; 458 CapsSeedUrl = agentData.CapsPath;
464 459
460 ReceivedKills = new List<uint>();
465 ReceivedOfflineNotifications = new List<UUID>(); 461 ReceivedOfflineNotifications = new List<UUID>();
466 ReceivedOnlineNotifications = new List<UUID>(); 462 ReceivedOnlineNotifications = new List<UUID>();
467 ReceivedFriendshipTerminations = new List<UUID>(); 463 ReceivedFriendshipTerminations = new List<UUID>();
@@ -484,7 +480,20 @@ namespace OpenSim.Tests.Common.Mock
484 480
485 public void CompleteMovement() 481 public void CompleteMovement()
486 { 482 {
487 OnCompleteMovementToRegion(this, true); 483 if (OnCompleteMovementToRegion != null)
484 OnCompleteMovementToRegion(this, true);
485 }
486
487 /// <summary>
488 /// Emulate sending an IM from the viewer to the simulator.
489 /// </summary>
490 /// <param name='im'></param>
491 public void HandleImprovedInstantMessage(GridInstantMessage im)
492 {
493 ImprovedInstantMessage handlerInstantMessage = OnInstantMessage;
494
495 if (handlerInstantMessage != null)
496 handlerInstantMessage(this, im);
488 } 497 }
489 498
490 public virtual void ActivateGesture(UUID assetId, UUID gestureId) 499 public virtual void ActivateGesture(UUID assetId, UUID gestureId)
@@ -499,6 +508,11 @@ namespace OpenSim.Tests.Common.Mock
499 { 508 {
500 } 509 }
501 510
511 public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures)
512 {
513
514 }
515
502 public virtual void Kick(string message) 516 public virtual void Kick(string message)
503 { 517 {
504 } 518 }
@@ -513,11 +527,11 @@ namespace OpenSim.Tests.Common.Mock
513 527
514 public virtual void SendAgentDataUpdate(UUID agentid, UUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle) 528 public virtual void SendAgentDataUpdate(UUID agentid, UUID activegroupid, string firstname, string lastname, ulong grouppowers, string groupname, string grouptitle)
515 { 529 {
516
517 } 530 }
518 531
519 public virtual void SendKillObject(ulong regionHandle, List<uint> localID) 532 public virtual void SendKillObject(List<uint> localID)
520 { 533 {
534 ReceivedKills.AddRange(localID);
521 } 535 }
522 536
523 public virtual void SetChildAgentThrottle(byte[] throttle) 537 public virtual void SetChildAgentThrottle(byte[] throttle)
@@ -526,15 +540,13 @@ namespace OpenSim.Tests.Common.Mock
526 540
527 public void SetAgentThrottleSilent(int throttle, int setting) 541 public void SetAgentThrottleSilent(int throttle, int setting)
528 { 542 {
529
530
531 } 543 }
544
532 public byte[] GetThrottlesPacked(float multiplier) 545 public byte[] GetThrottlesPacked(float multiplier)
533 { 546 {
534 return new byte[0]; 547 return new byte[0];
535 } 548 }
536 549
537
538 public virtual void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 550 public virtual void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
539 { 551 {
540 } 552 }
@@ -547,7 +559,8 @@ namespace OpenSim.Tests.Common.Mock
547 559
548 public void SendInstantMessage(GridInstantMessage im) 560 public void SendInstantMessage(GridInstantMessage im)
549 { 561 {
550 562 if (OnReceivedInstantMessage != null)
563 OnReceivedInstantMessage(im);
551 } 564 }
552 565
553 public void SendGenericMessage(string method, UUID invoice, List<string> message) 566 public void SendGenericMessage(string method, UUID invoice, List<string> message)
@@ -585,7 +598,7 @@ namespace OpenSim.Tests.Common.Mock
585 { 598 {
586 AgentCircuitData agentData = new AgentCircuitData(); 599 AgentCircuitData agentData = new AgentCircuitData();
587 agentData.AgentID = AgentId; 600 agentData.AgentID = AgentId;
588 agentData.SessionID = UUID.Zero; 601 agentData.SessionID = SessionId;
589 agentData.SecureSessionID = UUID.Zero; 602 agentData.SecureSessionID = UUID.Zero;
590 agentData.circuitcode = m_circuitCode; 603 agentData.circuitcode = m_circuitCode;
591 agentData.child = false; 604 agentData.child = false;
@@ -608,21 +621,25 @@ namespace OpenSim.Tests.Common.Mock
608 OnTestClientInformClientOfNeighbour(neighbourHandle, neighbourExternalEndPoint); 621 OnTestClientInformClientOfNeighbour(neighbourHandle, neighbourExternalEndPoint);
609 } 622 }
610 623
611 public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, 624 public virtual void SendRegionTeleport(
612 uint locationID, uint flags, string capsURL) 625 ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
626 uint locationID, uint flags, string capsURL)
613 { 627 {
614 m_log.DebugFormat("[TEST CLIENT]: Received SendRegionTeleport"); 628 m_log.DebugFormat(
629 "[TEST CLIENT]: Received SendRegionTeleport for {0} {1} on {2}", m_firstName, m_lastName, m_scene.Name);
615 630
616 CapsSeedUrl = capsURL; 631 CapsSeedUrl = capsURL;
617 632
618 // We don't do this here so that the source region can complete processing first in a single-threaded 633 if (OnTestClientSendRegionTeleport != null)
619 // regression test scenario. The test itself will have to call CompleteTeleportClientSide() after a teleport 634 OnTestClientSendRegionTeleport(
620 // CompleteTeleportClientSide(); 635 regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL);
621 } 636 }
622 637
623 public virtual void SendTeleportFailed(string reason) 638 public virtual void SendTeleportFailed(string reason)
624 { 639 {
625 m_log.DebugFormat("[TEST CLIENT]: Teleport failed with reason {0}", reason); 640 m_log.DebugFormat(
641 "[TEST CLIENT]: Teleport failed for {0} {1} on {2} with reason {3}",
642 m_firstName, m_lastName, m_scene.Name, reason);
626 } 643 }
627 644
628 public virtual void CrossRegion(ulong newRegionHandle, Vector3 pos, Vector3 lookAt, 645 public virtual void CrossRegion(ulong newRegionHandle, Vector3 pos, Vector3 lookAt,
@@ -782,11 +799,6 @@ namespace OpenSim.Tests.Common.Mock
782 { 799 {
783 OnRegionHandShakeReply(this); 800 OnRegionHandShakeReply(this);
784 } 801 }
785
786 if (OnCompleteMovementToRegion != null)
787 {
788 OnCompleteMovementToRegion(this, true);
789 }
790 } 802 }
791 803
792 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) 804 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
@@ -1260,7 +1272,7 @@ namespace OpenSim.Tests.Common.Mock
1260 { 1272 {
1261 } 1273 }
1262 1274
1263 public void StopFlying(ISceneEntity presence) 1275 public void SendAgentTerseUpdate(ISceneEntity presence)
1264 { 1276 {
1265 } 1277 }
1266 1278
diff --git a/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs b/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs
index 6707019..f2bae58 100644
--- a/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs
+++ b/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs
@@ -38,6 +38,7 @@ using OpenMetaverse;
38using OpenMetaverse.StructuredData; 38using OpenMetaverse.StructuredData;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Servers; 40using OpenSim.Framework.Servers;
41using OpenSim.Region.ClientStack.Linden;
41using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
43 44
@@ -113,22 +114,25 @@ namespace OpenSim.Tests.Common
113 AddEvent(avatarID, "DisableSimulator", handle); 114 AddEvent(avatarID, "DisableSimulator", handle);
114 } 115 }
115 116
116 public void EnableSimulator (ulong handle, IPEndPoint endPoint, UUID avatarID) 117 public void EnableSimulator (ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY)
117 { 118 {
118 AddEvent(avatarID, "EnableSimulator", handle); 119 AddEvent(avatarID, "EnableSimulator", handle);
119 } 120 }
120 121
121 public void EstablishAgentCommunication (UUID avatarID, IPEndPoint endPoint, string capsPath) 122 public void EstablishAgentCommunication (UUID avatarID, IPEndPoint endPoint, string capsPath,
123 ulong regionHandle, int regionSizeX, int regionSizeY)
122 { 124 {
123 AddEvent(avatarID, "EstablishAgentCommunication", endPoint, capsPath); 125 AddEvent(avatarID, "EstablishAgentCommunication", endPoint, capsPath);
124 } 126 }
125 127
126 public void TeleportFinishEvent (ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, uint locationID, uint flags, string capsURL, UUID agentID) 128 public void TeleportFinishEvent (ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
129 uint locationID, uint flags, string capsURL, UUID agentID, int regionSizeX, int regionSizeY)
127 { 130 {
128 AddEvent(agentID, "TeleportFinishEvent", regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL); 131 AddEvent(agentID, "TeleportFinishEvent", regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL);
129 } 132 }
130 133
131 public void CrossRegion (ulong handle, Vector3 pos, Vector3 lookAt, IPEndPoint newRegionExternalEndPoint, string capsURL, UUID avatarID, UUID sessionID) 134 public void CrossRegion (ulong handle, Vector3 pos, Vector3 lookAt, IPEndPoint newRegionExternalEndPoint,
135 string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY)
132 { 136 {
133 AddEvent(avatarID, "CrossRegion", handle, pos, lookAt, newRegionExternalEndPoint, capsURL, sessionID); 137 AddEvent(avatarID, "CrossRegion", handle, pos, lookAt, newRegionExternalEndPoint, capsURL, sessionID);
134 } 138 }
@@ -164,7 +168,7 @@ namespace OpenSim.Tests.Common
164 throw new System.NotImplementedException (); 168 throw new System.NotImplementedException ();
165 } 169 }
166 170
167 public OSD BuildEvent (string eventName, OSD eventBody) 171 public OSD BuildEvent(string eventName, OSD eventBody)
168 { 172 {
169 Console.WriteLine("TWO"); 173 Console.WriteLine("TWO");
170 throw new System.NotImplementedException (); 174 throw new System.NotImplementedException ();
diff --git a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
index ccbdf81..2be5524 100644
--- a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
+++ b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
@@ -53,6 +53,9 @@ namespace OpenSim.Tests.Common.Mock
53 53
54 public XInventoryFolder[] GetFolders(string[] fields, string[] vals) 54 public XInventoryFolder[] GetFolders(string[] fields, string[] vals)
55 { 55 {
56// Console.WriteLine(
57// "Requesting folders, fields {0}, vals {1}", string.Join(",", fields), string.Join(",", vals));
58
56 List<XInventoryFolder> origFolders 59 List<XInventoryFolder> origFolders
57 = Get<XInventoryFolder>(fields, vals, m_allFolders.Values.ToList()); 60 = Get<XInventoryFolder>(fields, vals, m_allFolders.Values.ToList());
58 61
@@ -104,7 +107,30 @@ namespace OpenSim.Tests.Common.Mock
104 } 107 }
105 108
106 public bool MoveItem(string id, string newParent) { throw new NotImplementedException(); } 109 public bool MoveItem(string id, string newParent) { throw new NotImplementedException(); }
107 public bool MoveFolder(string id, string newParent) { throw new NotImplementedException(); } 110
111 public bool MoveFolder(string id, string newParent)
112 {
113 // Don't use GetFolders() here - it takes a clone!
114 XInventoryFolder folder = m_allFolders[new UUID(id)];
115
116 if (folder == null)
117 return false;
118
119 folder.parentFolderID = new UUID(newParent);
120
121// XInventoryFolder[] newParentFolders
122// = GetFolders(new string[] { "folderID" }, new string[] { folder.parentFolderID.ToString() });
123
124// Console.WriteLine(
125// "Moved folder {0} {1}, to {2} {3}",
126// folder.folderName, folder.folderID, newParentFolders[0].folderName, folder.parentFolderID);
127
128 // TODO: Really need to implement folder version incrementing, though this should be common code anyway,
129 // not reimplemented in each db plugin.
130
131 return true;
132 }
133
108 public XInventoryItem[] GetActiveGestures(UUID principalID) { throw new NotImplementedException(); } 134 public XInventoryItem[] GetActiveGestures(UUID principalID) { throw new NotImplementedException(); }
109 public int GetAssetPermissions(UUID principalID, UUID assetID) { throw new NotImplementedException(); } 135 public int GetAssetPermissions(UUID principalID, UUID assetID) { throw new NotImplementedException(); }
110 } 136 }
diff --git a/OpenSim/Tests/Common/OpenSimTestCase.cs b/OpenSim/Tests/Common/OpenSimTestCase.cs
index 8c40923..3c47faa 100644
--- a/OpenSim/Tests/Common/OpenSimTestCase.cs
+++ b/OpenSim/Tests/Common/OpenSimTestCase.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using NUnit.Framework; 29using NUnit.Framework;
30using OpenSim.Framework.Servers;
30 31
31namespace OpenSim.Tests.Common 32namespace OpenSim.Tests.Common
32{ 33{
@@ -40,7 +41,14 @@ namespace OpenSim.Tests.Common
40 // Disable logging for each test so that one where logging is enabled doesn't cause all subsequent tests 41 // Disable logging for each test so that one where logging is enabled doesn't cause all subsequent tests
41 // to have logging on if it failed with an exception. 42 // to have logging on if it failed with an exception.
42 TestHelpers.DisableLogging(); 43 TestHelpers.DisableLogging();
44
45 // This is an unfortunate bit of clean up we have to do because MainServer manages things through static
46 // variables and the VM is not restarted between tests.
47 if (MainServer.Instance != null)
48 {
49 MainServer.RemoveHttpServer(MainServer.Instance.Port);
50// MainServer.Instance = null;
51 }
43 } 52 }
44 } 53 }
45} 54} \ No newline at end of file
46
diff --git a/OpenSim/Tests/Common/TestHelpers.cs b/OpenSim/Tests/Common/TestHelpers.cs
index a684d72..6bf23f8 100644
--- a/OpenSim/Tests/Common/TestHelpers.cs
+++ b/OpenSim/Tests/Common/TestHelpers.cs
@@ -117,8 +117,6 @@ namespace OpenSim.Tests.Common
117 /// Parse a UUID stem into a full UUID. 117 /// Parse a UUID stem into a full UUID.
118 /// </summary> 118 /// </summary>
119 /// <remarks> 119 /// <remarks>
120 /// Yes, this is completely inconsistent with ParseTail but this is probably a better way to do it,
121 /// UUIDs are conceptually not hexadecmial numbers.
122 /// The fragment will come at the start of the UUID. The rest will be 0s 120 /// The fragment will come at the start of the UUID. The rest will be 0s
123 /// </remarks> 121 /// </remarks>
124 /// <returns></returns> 122 /// <returns></returns>
@@ -143,5 +141,24 @@ namespace OpenSim.Tests.Common
143 { 141 {
144 return new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", tail)); 142 return new UUID(string.Format("00000000-0000-0000-0000-{0:X12}", tail));
145 } 143 }
144
145 /// <summary>
146 /// Parse a UUID tail section into a full UUID.
147 /// </summary>
148 /// <remarks>
149 /// The fragment will come at the end of the UUID. The rest will be 0s
150 /// </remarks>
151 /// <returns></returns>
152 /// <param name='frag'>
153 /// A UUID fragment that will be parsed into a full UUID. Therefore, it can only contain
154 /// cahracters which are valid in a UUID, except for "-" which is currently only allowed if a full UUID is
155 /// given as the 'fragment'.
156 /// </param>
157 public static UUID ParseTail(string stem)
158 {
159 string rawUuid = stem.PadLeft(32, '0');
160
161 return UUID.Parse(rawUuid);
162 }
146 } 163 }
147} 164}
diff --git a/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs b/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs
index 088be45..7006211 100644
--- a/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs
+++ b/OpenSim/Tools/Compiler/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Tools/Configger/ConfigurationLoader.cs b/OpenSim/Tools/Configger/ConfigurationLoader.cs
index 28bcc99..0b6ee9c 100644
--- a/OpenSim/Tools/Configger/ConfigurationLoader.cs
+++ b/OpenSim/Tools/Configger/ConfigurationLoader.cs
@@ -239,10 +239,7 @@ namespace OpenSim.Tools.Configger
239 config.Set("physics", "OpenDynamicsEngine"); 239 config.Set("physics", "OpenDynamicsEngine");
240 config.Set("meshing", "Meshmerizer"); 240 config.Set("meshing", "Meshmerizer");
241 config.Set("physical_prim", true); 241 config.Set("physical_prim", true);
242 config.Set("see_into_this_sim_from_neighbor", true);
243 config.Set("serverside_object_permissions", true); 242 config.Set("serverside_object_permissions", true);
244 config.Set("storage_plugin", "OpenSim.Data.SQLite.dll");
245 config.Set("storage_connection_string", "URI=file:OpenSim.db,version=3");
246 config.Set("storage_prim_inventories", true); 243 config.Set("storage_prim_inventories", true);
247 config.Set("startup_console_commands_file", String.Empty); 244 config.Set("startup_console_commands_file", String.Empty);
248 config.Set("shutdown_console_commands_file", String.Empty); 245 config.Set("shutdown_console_commands_file", String.Empty);
@@ -254,6 +251,5 @@ namespace OpenSim.Tools.Configger
254 251
255 return defaultConfig; 252 return defaultConfig;
256 } 253 }
257
258 } 254 }
259} 255} \ No newline at end of file
diff --git a/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs b/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs
index 0348628..bfcd4fb 100644
--- a/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs
+++ b/OpenSim/Tools/Configger/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Tools/OpenSim.32BitLaunch/OpenSim.32BitLaunch.csproj b/OpenSim/Tools/OpenSim.32BitLaunch/OpenSim.32BitLaunch.csproj
index d829e69..4625c33 100644
--- a/OpenSim/Tools/OpenSim.32BitLaunch/OpenSim.32BitLaunch.csproj
+++ b/OpenSim/Tools/OpenSim.32BitLaunch/OpenSim.32BitLaunch.csproj
@@ -1,58 +1,97 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 2<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup> 3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> 4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> 5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProductVersion>9.0.30729</ProductVersion> 6 <ProductVersion>9.0.30729</ProductVersion>
7 <SchemaVersion>2.0</SchemaVersion> 7 <SchemaVersion>2.0</SchemaVersion>
8 <ProjectGuid>{595D67F3-B413-4A43-8568-5B5930E3B31D}</ProjectGuid> 8 <ProjectGuid>{595D67F3-B413-4A43-8568-5B5930E3B31D}</ProjectGuid>
9 <OutputType>Exe</OutputType> 9 <OutputType>Exe</OutputType>
10 <AppDesignerFolder>Properties</AppDesignerFolder> 10 <AppDesignerFolder>Properties</AppDesignerFolder>
11 <RootNamespace>OpenSim._32BitLaunch</RootNamespace> 11 <RootNamespace>OpenSim._32BitLaunch</RootNamespace>
12 <AssemblyName>OpenSim.32BitLaunch</AssemblyName> 12 <AssemblyName>OpenSim.32BitLaunch</AssemblyName>
13 <TargetFrameworkVersion>v2.0</TargetFrameworkVersion> 13 <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
14 <FileAlignment>512</FileAlignment> 14 <FileAlignment>512</FileAlignment>
15 </PropertyGroup> 15 <FileUpgradeFlags>
16 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> 16 </FileUpgradeFlags>
17 <DebugSymbols>true</DebugSymbols> 17 <UpgradeBackupLocation>
18 <DebugType>full</DebugType> 18 </UpgradeBackupLocation>
19 <Optimize>false</Optimize> 19 <OldToolsVersion>3.5</OldToolsVersion>
20 <OutputPath>..\..\..\bin\</OutputPath> 20 <PublishUrl>publish\</PublishUrl>
21 <DefineConstants>DEBUG;TRACE</DefineConstants> 21 <Install>true</Install>
22 <ErrorReport>prompt</ErrorReport> 22 <InstallFrom>Disk</InstallFrom>
23 <WarningLevel>4</WarningLevel> 23 <UpdateEnabled>false</UpdateEnabled>
24 <PlatformTarget>x86</PlatformTarget> 24 <UpdateMode>Foreground</UpdateMode>
25 </PropertyGroup> 25 <UpdateInterval>7</UpdateInterval>
26 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> 26 <UpdateIntervalUnits>Days</UpdateIntervalUnits>
27 <DebugType>pdbonly</DebugType> 27 <UpdatePeriodically>false</UpdatePeriodically>
28 <Optimize>true</Optimize> 28 <UpdateRequired>false</UpdateRequired>
29 <OutputPath>bin\Release\</OutputPath> 29 <MapFileExtensions>true</MapFileExtensions>
30 <DefineConstants>TRACE</DefineConstants> 30 <ApplicationRevision>0</ApplicationRevision>
31 <ErrorReport>prompt</ErrorReport> 31 <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
32 <WarningLevel>4</WarningLevel> 32 <IsWebBootstrapper>false</IsWebBootstrapper>
33 </PropertyGroup> 33 <UseApplicationTrust>false</UseApplicationTrust>
34 <ItemGroup> 34 <BootstrapperEnabled>true</BootstrapperEnabled>
35 <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL" /> 35 </PropertyGroup>
36 <Reference Include="System" /> 36 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
37 <Reference Include="System.Data" /> 37 <DebugSymbols>true</DebugSymbols>
38 <Reference Include="System.Xml" /> 38 <DebugType>full</DebugType>
39 </ItemGroup> 39 <Optimize>false</Optimize>
40 <ItemGroup> 40 <OutputPath>..\..\..\bin\</OutputPath>
41 <Compile Include="Program.cs" /> 41 <DefineConstants>DEBUG;TRACE</DefineConstants>
42 <Compile Include="Properties\AssemblyInfo.cs" /> 42 <ErrorReport>prompt</ErrorReport>
43 </ItemGroup> 43 <WarningLevel>4</WarningLevel>
44 <ItemGroup> 44 <PlatformTarget>x86</PlatformTarget>
45 <ProjectReference Include="..\..\Region\Application\OpenSim.csproj"> 45 </PropertyGroup>
46 <Project>{438A9556-0000-0000-0000-000000000000}</Project> 46 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
47 <Name>OpenSim</Name> 47 <DebugType>pdbonly</DebugType>
48 </ProjectReference> 48 <Optimize>true</Optimize>
49 </ItemGroup> 49 <OutputPath>bin\Release\</OutputPath>
50 <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> 50 <DefineConstants>TRACE</DefineConstants>
51 <ErrorReport>prompt</ErrorReport>
52 <WarningLevel>4</WarningLevel>
53 </PropertyGroup>
54 <ItemGroup>
55 <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL" />
56 <Reference Include="OpenSim, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
57 <SpecificVersion>False</SpecificVersion>
58 <ExecutableExtension>.exe</ExecutableExtension>
59 <HintPath>..\..\..\bin\OpenSim.exe</HintPath>
60 </Reference>
61 <Reference Include="System" />
62 </ItemGroup>
63 <ItemGroup>
64 <Compile Include="Program.cs" />
65 <Compile Include="Properties\AssemblyInfo.cs" />
66 </ItemGroup>
67 <ItemGroup>
68 <BootstrapperPackage Include=".NETFramework,Version=v4.0">
69 <Visible>False</Visible>
70 <ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
71 <Install>true</Install>
72 </BootstrapperPackage>
73 <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
74 <Visible>False</Visible>
75 <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
76 <Install>false</Install>
77 </BootstrapperPackage>
78 <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
79 <Visible>False</Visible>
80 <ProductName>.NET Framework 3.5 SP1</ProductName>
81 <Install>false</Install>
82 </BootstrapperPackage>
83 <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
84 <Visible>False</Visible>
85 <ProductName>Windows Installer 3.1</ProductName>
86 <Install>true</Install>
87 </BootstrapperPackage>
88 </ItemGroup>
89 <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
51 <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 90 <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
52 Other similar extension points exist, see Microsoft.Common.targets. 91 Other similar extension points exist, see Microsoft.Common.targets.
53 <Target Name="BeforeBuild"> 92 <Target Name="BeforeBuild">
54 </Target> 93 </Target>
55 <Target Name="AfterBuild"> 94 <Target Name="AfterBuild">
56 </Target> 95 </Target>
57 --> 96 -->
58</Project> \ No newline at end of file 97</Project> \ No newline at end of file
diff --git a/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.csproj b/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.csproj
index 481b3f8..9618c08 100644
--- a/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.csproj
+++ b/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.csproj
@@ -1,62 +1,99 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 2<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup> 3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> 4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> 5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProductVersion>9.0.30729</ProductVersion> 6 <ProductVersion>9.0.30729</ProductVersion>
7 <SchemaVersion>2.0</SchemaVersion> 7 <SchemaVersion>2.0</SchemaVersion>
8 <ProjectGuid>{595D67F3-B413-4A43-8568-5B5930E3B31D}</ProjectGuid> 8 <ProjectGuid>{595D67F3-B413-4A43-8568-5B5930E3B31D}</ProjectGuid>
9 <OutputType>Exe</OutputType> 9 <OutputType>Exe</OutputType>
10 <AppDesignerFolder>Properties</AppDesignerFolder> 10 <AppDesignerFolder>Properties</AppDesignerFolder>
11 <RootNamespace>Robust._32BitLaunch</RootNamespace> 11 <RootNamespace>Robust._32BitLaunch</RootNamespace>
12 <AssemblyName>Robust.32BitLaunch</AssemblyName> 12 <AssemblyName>Robust.32BitLaunch</AssemblyName>
13 <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> 13 <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
14 <FileAlignment>512</FileAlignment> 14 <FileAlignment>512</FileAlignment>
15 </PropertyGroup> 15 <FileUpgradeFlags>
16 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> 16 </FileUpgradeFlags>
17 <DebugSymbols>true</DebugSymbols> 17 <UpgradeBackupLocation>
18 <DebugType>full</DebugType> 18 </UpgradeBackupLocation>
19 <Optimize>false</Optimize> 19 <OldToolsVersion>3.5</OldToolsVersion>
20 <OutputPath>..\..\..\bin\</OutputPath> 20 <PublishUrl>publish\</PublishUrl>
21 <DefineConstants>DEBUG;TRACE</DefineConstants> 21 <Install>true</Install>
22 <ErrorReport>prompt</ErrorReport> 22 <InstallFrom>Disk</InstallFrom>
23 <WarningLevel>4</WarningLevel> 23 <UpdateEnabled>false</UpdateEnabled>
24 <PlatformTarget>x86</PlatformTarget> 24 <UpdateMode>Foreground</UpdateMode>
25 </PropertyGroup> 25 <UpdateInterval>7</UpdateInterval>
26 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> 26 <UpdateIntervalUnits>Days</UpdateIntervalUnits>
27 <DebugType>pdbonly</DebugType> 27 <UpdatePeriodically>false</UpdatePeriodically>
28 <Optimize>true</Optimize> 28 <UpdateRequired>false</UpdateRequired>
29 <OutputPath>bin\Release\</OutputPath> 29 <MapFileExtensions>true</MapFileExtensions>
30 <DefineConstants>TRACE</DefineConstants> 30 <ApplicationRevision>0</ApplicationRevision>
31 <ErrorReport>prompt</ErrorReport> 31 <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
32 <WarningLevel>4</WarningLevel> 32 <IsWebBootstrapper>false</IsWebBootstrapper>
33 </PropertyGroup> 33 <UseApplicationTrust>false</UseApplicationTrust>
34 <ItemGroup> 34 <BootstrapperEnabled>true</BootstrapperEnabled>
35 <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL"> 35 </PropertyGroup>
36 <SpecificVersion>False</SpecificVersion> 36 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
37 <HintPath>..\..\..\bin\log4net.dll</HintPath> 37 <DebugSymbols>true</DebugSymbols>
38 </Reference> 38 <DebugType>full</DebugType>
39 <Reference Include="Robust, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL"> 39 <Optimize>false</Optimize>
40 <SpecificVersion>False</SpecificVersion> 40 <OutputPath>..\..\..\bin\</OutputPath>
41 <HintPath>..\..\..\bin\Robust.exe</HintPath> 41 <DefineConstants>DEBUG;TRACE</DefineConstants>
42 </Reference> 42 <ErrorReport>prompt</ErrorReport>
43 <Reference Include="System" /> 43 <WarningLevel>4</WarningLevel>
44 <Reference Include="System.Core"> 44 <PlatformTarget>x86</PlatformTarget>
45 <RequiredTargetFramework>3.5</RequiredTargetFramework> 45 </PropertyGroup>
46 </Reference> 46 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
47 <Reference Include="System.Data" /> 47 <DebugType>pdbonly</DebugType>
48 <Reference Include="System.Xml" /> 48 <Optimize>true</Optimize>
49 </ItemGroup> 49 <OutputPath>bin\Release\</OutputPath>
50 <ItemGroup> 50 <DefineConstants>TRACE</DefineConstants>
51 <Compile Include="Program.cs" /> 51 <ErrorReport>prompt</ErrorReport>
52 <Compile Include="Properties\AssemblyInfo.cs" /> 52 <WarningLevel>4</WarningLevel>
53 </ItemGroup> 53 </PropertyGroup>
54 <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> 54 <ItemGroup>
55 <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
56 <SpecificVersion>False</SpecificVersion>
57 <HintPath>..\..\..\bin\log4net.dll</HintPath>
58 </Reference>
59 <Reference Include="Robust, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
60 <SpecificVersion>False</SpecificVersion>
61 <HintPath>..\..\..\bin\Robust.exe</HintPath>
62 </Reference>
63 <Reference Include="System" />
64 </ItemGroup>
65 <ItemGroup>
66 <Compile Include="Program.cs" />
67 <Compile Include="Properties\AssemblyInfo.cs" />
68 </ItemGroup>
69 <ItemGroup>
70 <BootstrapperPackage Include=".NETFramework,Version=v4.0">
71 <Visible>False</Visible>
72 <ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
73 <Install>true</Install>
74 </BootstrapperPackage>
75 <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
76 <Visible>False</Visible>
77 <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
78 <Install>false</Install>
79 </BootstrapperPackage>
80 <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
81 <Visible>False</Visible>
82 <ProductName>.NET Framework 3.5 SP1</ProductName>
83 <Install>false</Install>
84 </BootstrapperPackage>
85 <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
86 <Visible>False</Visible>
87 <ProductName>Windows Installer 3.1</ProductName>
88 <Install>true</Install>
89 </BootstrapperPackage>
90 </ItemGroup>
91 <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
55 <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 92 <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
56 Other similar extension points exist, see Microsoft.Common.targets. 93 Other similar extension points exist, see Microsoft.Common.targets.
57 <Target Name="BeforeBuild"> 94 <Target Name="BeforeBuild">
58 </Target> 95 </Target>
59 <Target Name="AfterBuild"> 96 <Target Name="AfterBuild">
60 </Target> 97 </Target>
61 --> 98 -->
62</Project> \ No newline at end of file 99</Project> \ No newline at end of file
diff --git a/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.sln b/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.sln
index c7c97b1..a48a2d3 100644
--- a/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.sln
+++ b/OpenSim/Tools/Robust.32BitLaunch/Robust.32BitLaunch.sln
@@ -1,20 +1,20 @@
1 1
2Microsoft Visual Studio Solution File, Format Version 10.00 2Microsoft Visual Studio Solution File, Format Version 11.00
3# Visual C# Express 2008 3# Visual C# Express 2010
4Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Robust.32BitLaunch", "Robust.32BitLaunch.csproj", "{595D67F3-B413-4A43-8568-5B5930E3B31D}" 4Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Robust.32BitLaunch", "Robust.32BitLaunch.csproj", "{595D67F3-B413-4A43-8568-5B5930E3B31D}"
5EndProject 5EndProject
6Global 6Global
7 GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 Debug|Any CPU = Debug|Any CPU 8 Debug|Any CPU = Debug|Any CPU
9 Release|Any CPU = Release|Any CPU 9 Release|Any CPU = Release|Any CPU
10 EndGlobalSection 10 EndGlobalSection
11 GlobalSection(ProjectConfigurationPlatforms) = postSolution 11 GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 {595D67F3-B413-4A43-8568-5B5930E3B31D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 12 {595D67F3-B413-4A43-8568-5B5930E3B31D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 {595D67F3-B413-4A43-8568-5B5930E3B31D}.Debug|Any CPU.Build.0 = Debug|Any CPU 13 {595D67F3-B413-4A43-8568-5B5930E3B31D}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 {595D67F3-B413-4A43-8568-5B5930E3B31D}.Release|Any CPU.ActiveCfg = Release|Any CPU 14 {595D67F3-B413-4A43-8568-5B5930E3B31D}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 {595D67F3-B413-4A43-8568-5B5930E3B31D}.Release|Any CPU.Build.0 = Release|Any CPU 15 {595D67F3-B413-4A43-8568-5B5930E3B31D}.Release|Any CPU.Build.0 = Release|Any CPU
16 EndGlobalSection 16 EndGlobalSection
17 GlobalSection(SolutionProperties) = preSolution 17 GlobalSection(SolutionProperties) = preSolution
18 HideSolutionNode = FALSE 18 HideSolutionNode = FALSE
19 EndGlobalSection 19 EndGlobalSection
20EndGlobal 20EndGlobal
diff --git a/OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs
index 9a9371d..9bc8512 100644
--- a/OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs
@@ -35,6 +35,11 @@ namespace pCampBot
35{ 35{
36 public class AbstractBehaviour : IBehaviour 36 public class AbstractBehaviour : IBehaviour
37 { 37 {
38 /// <summary>
39 /// Abbreviated name of this behaviour.
40 /// </summary>
41 public string AbbreviatedName { get; protected set; }
42
38 public string Name { get; protected set; } 43 public string Name { get; protected set; }
39 44
40 public Bot Bot { get; protected set; } 45 public Bot Bot { get; protected set; }
@@ -45,5 +50,7 @@ namespace pCampBot
45 { 50 {
46 Bot = bot; 51 Bot = bot;
47 } 52 }
53
54 public virtual void Close() {}
48 } 55 }
49} 56}
diff --git a/OpenSim/Tools/pCampBot/Behaviours/CrossBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/CrossBehaviour.cs
index 1e01c64..4d806fc 100644
--- a/OpenSim/Tools/pCampBot/Behaviours/CrossBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Behaviours/CrossBehaviour.cs
@@ -47,7 +47,11 @@ namespace pCampBot
47 47
48 public const int m_regionCrossingTimeout = 1000 * 60; 48 public const int m_regionCrossingTimeout = 1000 * 60;
49 49
50 public CrossBehaviour() { Name = "Cross"; } 50 public CrossBehaviour()
51 {
52 AbbreviatedName = "c";
53 Name = "Cross";
54 }
51 55
52 public override void Action() 56 public override void Action()
53 { 57 {
diff --git a/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs
index 66a336a..59f6244 100644
--- a/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs
@@ -29,6 +29,7 @@ using OpenMetaverse;
29using System; 29using System;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Linq; 31using System.Linq;
32using System.Threading;
32using pCampBot.Interfaces; 33using pCampBot.Interfaces;
33 34
34namespace pCampBot 35namespace pCampBot
@@ -41,7 +42,11 @@ namespace pCampBot
41 /// </remarks> 42 /// </remarks>
42 public class GrabbingBehaviour : AbstractBehaviour 43 public class GrabbingBehaviour : AbstractBehaviour
43 { 44 {
44 public GrabbingBehaviour() { Name = "Grabbing"; } 45 public GrabbingBehaviour()
46 {
47 AbbreviatedName = "g";
48 Name = "Grabbing";
49 }
45 50
46 public override void Action() 51 public override void Action()
47 { 52 {
@@ -56,6 +61,8 @@ namespace pCampBot
56 Bot.Client.Self.Grab(prim.LocalID); 61 Bot.Client.Self.Grab(prim.LocalID);
57 Bot.Client.Self.GrabUpdate(prim.ID, Vector3.Zero); 62 Bot.Client.Self.GrabUpdate(prim.ID, Vector3.Zero);
58 Bot.Client.Self.DeGrab(prim.LocalID); 63 Bot.Client.Self.DeGrab(prim.LocalID);
64
65 Thread.Sleep(1000);
59 } 66 }
60 } 67 }
61} \ No newline at end of file 68} \ No newline at end of file
diff --git a/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs
new file mode 100644
index 0000000..9a3075c
--- /dev/null
+++ b/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs
@@ -0,0 +1,47 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenMetaverse;
29using System;
30using System.Collections.Generic;
31using System.Linq;
32using pCampBot.Interfaces;
33
34namespace pCampBot
35{
36 /// <summary>
37 /// Do nothing
38 /// </summary>
39 public class NoneBehaviour : AbstractBehaviour
40 {
41 public NoneBehaviour()
42 {
43 AbbreviatedName = "n";
44 Name = "None";
45 }
46 }
47} \ No newline at end of file
diff --git a/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs
index daa7485..6fd2b7c 100644
--- a/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs
@@ -46,6 +46,7 @@ namespace pCampBot
46 46
47 public PhysicsBehaviour() 47 public PhysicsBehaviour()
48 { 48 {
49 AbbreviatedName = "p";
49 Name = "Physics"; 50 Name = "Physics";
50 talkarray = readexcuses(); 51 talkarray = readexcuses();
51 } 52 }
@@ -77,6 +78,12 @@ namespace pCampBot
77 Bot.Client.Self.Chat(randomf, 0, ChatType.Normal); 78 Bot.Client.Self.Chat(randomf, 0, ChatType.Normal);
78 } 79 }
79 80
81 public override void Close()
82 {
83 if (Bot.ConnectionState == ConnectionState.Connected)
84 Bot.Client.Self.Jump(false);
85 }
86
80 private string[] readexcuses() 87 private string[] readexcuses()
81 { 88 {
82 string allexcuses = ""; 89 string allexcuses = "";
diff --git a/OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs
index fbb4e96..81f250d 100644
--- a/OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq; 30using System.Linq;
31using System.Reflection; 31using System.Reflection;
32using System.Threading;
32using log4net; 33using log4net;
33using OpenMetaverse; 34using OpenMetaverse;
34using pCampBot.Interfaces; 35using pCampBot.Interfaces;
@@ -42,7 +43,11 @@ namespace pCampBot
42 { 43 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 45
45 public TeleportBehaviour() { Name = "Teleport"; } 46 public TeleportBehaviour()
47 {
48 AbbreviatedName = "t";
49 Name = "Teleport";
50 }
46 51
47 public override void Action() 52 public override void Action()
48 { 53 {
@@ -70,6 +75,8 @@ namespace pCampBot
70 Bot.Name, sourceRegion.Name, Bot.Client.Self.SimPosition, destRegion.Name, destPosition); 75 Bot.Name, sourceRegion.Name, Bot.Client.Self.SimPosition, destRegion.Name, destPosition);
71 76
72 Bot.Client.Self.Teleport(destRegion.RegionHandle, destPosition); 77 Bot.Client.Self.Teleport(destRegion.RegionHandle, destPosition);
78
79 Thread.Sleep(Bot.Random.Next(3000, 10000));
73 } 80 }
74 } 81 }
75} \ No newline at end of file 82} \ No newline at end of file
diff --git a/OpenSim/Tools/pCampBot/Bot.cs b/OpenSim/Tools/pCampBot/Bot.cs
index 9821180..de464ab 100644
--- a/OpenSim/Tools/pCampBot/Bot.cs
+++ b/OpenSim/Tools/pCampBot/Bot.cs
@@ -59,22 +59,23 @@ namespace pCampBot
59 public delegate void AnEvent(Bot callbot, EventType someevent); // event delegate for bot events 59 public delegate void AnEvent(Bot callbot, EventType someevent); // event delegate for bot events
60 60
61 /// <summary> 61 /// <summary>
62 /// Bot manager. 62 /// Controls whether bots request textures for the object information they receive
63 /// </summary> 63 /// </summary>
64 public BotManager Manager { get; private set; } 64 public bool RequestObjectTextures { get; set; }
65 65
66 /// <summary> 66 /// <summary>
67 /// Bot config, passed from BotManager. 67 /// Bot manager.
68 /// </summary> 68 /// </summary>
69 private IConfig startupConfig; 69 public BotManager Manager { get; private set; }
70 70
71 /// <summary> 71 /// <summary>
72 /// Behaviours implemented by this bot. 72 /// Behaviours implemented by this bot.
73 /// </summary> 73 /// </summary>
74 /// <remarks> 74 /// <remarks>
75 /// Lock this list before manipulating it. 75 /// Indexed by abbreviated name. There can only be one instance of a particular behaviour.
76 /// Lock this structure before manipulating it.
76 /// </remarks> 77 /// </remarks>
77 public List<IBehaviour> Behaviours { get; private set; } 78 public Dictionary<string, IBehaviour> Behaviours { get; private set; }
78 79
79 /// <summary> 80 /// <summary>
80 /// Objects that the bot has discovered. 81 /// Objects that the bot has discovered.
@@ -97,11 +98,35 @@ namespace pCampBot
97 /// </summary> 98 /// </summary>
98 public ConnectionState ConnectionState { get; private set; } 99 public ConnectionState ConnectionState { get; private set; }
99 100
101 public List<Simulator> Simulators
102 {
103 get
104 {
105 lock (Client.Network.Simulators)
106 return new List<Simulator>(Client.Network.Simulators);
107 }
108 }
109
110 /// <summary>
111 /// The number of connections that this bot has to different simulators.
112 /// </summary>
113 /// <value>Includes both root and child connections.</value>
114 public int SimulatorsCount
115 {
116 get
117 {
118 lock (Client.Network.Simulators)
119 return Client.Network.Simulators.Count;
120 }
121 }
122
100 public string FirstName { get; private set; } 123 public string FirstName { get; private set; }
101 public string LastName { get; private set; } 124 public string LastName { get; private set; }
102 public string Name { get; private set; } 125 public string Name { get; private set; }
103 public string Password { get; private set; } 126 public string Password { get; private set; }
104 public string LoginUri { get; private set; } 127 public string LoginUri { get; private set; }
128 public string StartLocation { get; private set; }
129
105 public string saveDir; 130 public string saveDir;
106 public string wear; 131 public string wear;
107 132
@@ -137,94 +162,178 @@ namespace pCampBot
137 /// <param name="behaviours"></param> 162 /// <param name="behaviours"></param>
138 public Bot( 163 public Bot(
139 BotManager bm, List<IBehaviour> behaviours, 164 BotManager bm, List<IBehaviour> behaviours,
140 string firstName, string lastName, string password, string loginUri) 165 string firstName, string lastName, string password, string startLocation, string loginUri)
141 { 166 {
142 ConnectionState = ConnectionState.Disconnected; 167 ConnectionState = ConnectionState.Disconnected;
143 168
144 behaviours.ForEach(b => b.Initialize(this)); 169 Random = new Random(bm.Rng.Next());
145
146 Client = new GridClient();
147
148 Random = new Random(Environment.TickCount);// We do stuff randomly here
149 FirstName = firstName; 170 FirstName = firstName;
150 LastName = lastName; 171 LastName = lastName;
151 Name = string.Format("{0} {1}", FirstName, LastName); 172 Name = string.Format("{0} {1}", FirstName, LastName);
152 Password = password; 173 Password = password;
153 LoginUri = loginUri; 174 LoginUri = loginUri;
175 StartLocation = startLocation;
154 176
155 Manager = bm; 177 Manager = bm;
156 startupConfig = bm.Config;
157 readconfig();
158 178
159 Behaviours = behaviours; 179 Behaviours = new Dictionary<string, IBehaviour>();
180 foreach (IBehaviour behaviour in behaviours)
181 AddBehaviour(behaviour);
182
183 // Only calling for use as a template.
184 CreateLibOmvClient();
185 }
186
187 public bool TryGetBehaviour(string abbreviatedName, out IBehaviour behaviour)
188 {
189 lock (Behaviours)
190 return Behaviours.TryGetValue(abbreviatedName, out behaviour);
191 }
192
193 public bool AddBehaviour(IBehaviour behaviour)
194 {
195 lock (Behaviours)
196 {
197 if (!Behaviours.ContainsKey(behaviour.AbbreviatedName))
198 {
199 behaviour.Initialize(this);
200 Behaviours.Add(behaviour.AbbreviatedName, behaviour);
201
202 return true;
203 }
204 }
205
206 return false;
207 }
208
209 public bool RemoveBehaviour(string abbreviatedName)
210 {
211 lock (Behaviours)
212 {
213 IBehaviour behaviour;
214
215 if (!Behaviours.TryGetValue(abbreviatedName, out behaviour))
216 return false;
217
218 behaviour.Close();
219 Behaviours.Remove(abbreviatedName);
220
221 return true;
222 }
223 }
224
225 private void CreateLibOmvClient()
226 {
227 GridClient newClient = new GridClient();
228
229 if (Client != null)
230 {
231 newClient.Settings.LOGIN_SERVER = Client.Settings.LOGIN_SERVER;
232 newClient.Settings.ALWAYS_DECODE_OBJECTS = Client.Settings.ALWAYS_DECODE_OBJECTS;
233 newClient.Settings.AVATAR_TRACKING = Client.Settings.AVATAR_TRACKING;
234 newClient.Settings.OBJECT_TRACKING = Client.Settings.OBJECT_TRACKING;
235 newClient.Settings.SEND_AGENT_THROTTLE = Client.Settings.SEND_AGENT_THROTTLE;
236 newClient.Settings.SEND_AGENT_UPDATES = Client.Settings.SEND_AGENT_UPDATES;
237 newClient.Settings.SEND_PINGS = Client.Settings.SEND_PINGS;
238 newClient.Settings.STORE_LAND_PATCHES = Client.Settings.STORE_LAND_PATCHES;
239 newClient.Settings.USE_ASSET_CACHE = Client.Settings.USE_ASSET_CACHE;
240 newClient.Settings.MULTIPLE_SIMS = Client.Settings.MULTIPLE_SIMS;
241 newClient.Throttle.Asset = Client.Throttle.Asset;
242 newClient.Throttle.Land = Client.Throttle.Land;
243 newClient.Throttle.Task = Client.Throttle.Task;
244 newClient.Throttle.Texture = Client.Throttle.Texture;
245 newClient.Throttle.Wind = Client.Throttle.Wind;
246 newClient.Throttle.Total = Client.Throttle.Total;
247 }
248 else
249 {
250 newClient.Settings.LOGIN_SERVER = LoginUri;
251 newClient.Settings.ALWAYS_DECODE_OBJECTS = false;
252 newClient.Settings.AVATAR_TRACKING = false;
253 newClient.Settings.OBJECT_TRACKING = false;
254 newClient.Settings.SEND_AGENT_THROTTLE = true;
255 newClient.Settings.SEND_PINGS = true;
256 newClient.Settings.STORE_LAND_PATCHES = false;
257 newClient.Settings.USE_ASSET_CACHE = false;
258 newClient.Settings.MULTIPLE_SIMS = true;
259 newClient.Throttle.Asset = 100000;
260 newClient.Throttle.Land = 100000;
261 newClient.Throttle.Task = 100000;
262 newClient.Throttle.Texture = 100000;
263 newClient.Throttle.Wind = 100000;
264 newClient.Throttle.Total = 400000;
265 }
266
267 newClient.Network.LoginProgress += Network_LoginProgress;
268 newClient.Network.SimConnected += Network_SimConnected;
269 newClient.Network.SimDisconnected += Network_SimDisconnected;
270 newClient.Network.Disconnected += Network_OnDisconnected;
271 newClient.Objects.ObjectUpdate += Objects_NewPrim;
272
273 Client = newClient;
160 } 274 }
161 275
162 //We do our actions here. This is where one would 276 //We do our actions here. This is where one would
163 //add additional steps and/or things the bot should do 277 //add additional steps and/or things the bot should do
164 private void Action() 278 private void Action()
165 { 279 {
166 while (true) 280 while (ConnectionState == ConnectionState.Connected)
281 {
167 lock (Behaviours) 282 lock (Behaviours)
168 Behaviours.ForEach( 283 {
169 b => 284 foreach (IBehaviour behaviour in Behaviours.Values)
170 { 285 {
171 Thread.Sleep(Random.Next(3000, 10000)); 286// Thread.Sleep(Random.Next(3000, 10000));
172 287
173 // m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType()); 288 // m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType());
174 b.Action(); 289 behaviour.Action();
175 } 290 }
176 ); 291 }
177 }
178 292
179 /// <summary> 293 // XXX: This is a really shitty way of yielding so that behaviours can be added/removed
180 /// Read the Nini config and initialize 294 Thread.Sleep(100);
181 /// </summary> 295 }
182 public void readconfig() 296
183 { 297 lock (Behaviours)
184 wear = startupConfig.GetString("wear", "no"); 298 foreach (IBehaviour b in Behaviours.Values)
299 b.Close();
185 } 300 }
186 301
187 /// <summary> 302 /// <summary>
188 /// Tells LibSecondLife to logout and disconnect. Raises the disconnect events once it finishes. 303 /// Tells LibSecondLife to logout and disconnect. Raises the disconnect events once it finishes.
189 /// </summary> 304 /// </summary>
190 public void shutdown() 305 public void Disconnect()
191 { 306 {
192 ConnectionState = ConnectionState.Disconnecting; 307 ConnectionState = ConnectionState.Disconnecting;
193 308
194 if (m_actionThread != null) 309// if (m_actionThread != null)
195 m_actionThread.Abort(); 310// m_actionThread.Abort();
196 311
197 Client.Network.Logout(); 312 Client.Network.Logout();
198 } 313 }
199 314
315 public void Connect()
316 {
317 Thread connectThread = new Thread(ConnectInternal);
318 connectThread.Name = Name;
319 connectThread.IsBackground = true;
320
321 connectThread.Start();
322 }
323
200 /// <summary> 324 /// <summary>
201 /// This is the bot startup loop. 325 /// This is the bot startup loop.
202 /// </summary> 326 /// </summary>
203 public void startup() 327 private void ConnectInternal()
204 { 328 {
205 Client.Settings.LOGIN_SERVER = LoginUri;
206 Client.Settings.ALWAYS_DECODE_OBJECTS = false;
207 Client.Settings.AVATAR_TRACKING = false;
208 Client.Settings.OBJECT_TRACKING = false;
209 Client.Settings.SEND_AGENT_THROTTLE = true;
210 Client.Settings.SEND_PINGS = true;
211 Client.Settings.STORE_LAND_PATCHES = false;
212 Client.Settings.USE_ASSET_CACHE = false;
213 Client.Settings.MULTIPLE_SIMS = true;
214 Client.Throttle.Asset = 100000;
215 Client.Throttle.Land = 100000;
216 Client.Throttle.Task = 100000;
217 Client.Throttle.Texture = 100000;
218 Client.Throttle.Wind = 100000;
219 Client.Throttle.Total = 400000;
220 Client.Network.LoginProgress += this.Network_LoginProgress;
221 Client.Network.SimConnected += this.Network_SimConnected;
222 Client.Network.Disconnected += this.Network_OnDisconnected;
223 Client.Objects.ObjectUpdate += Objects_NewPrim;
224
225 ConnectionState = ConnectionState.Connecting; 329 ConnectionState = ConnectionState.Connecting;
226 330
227 if (Client.Network.Login(FirstName, LastName, Password, "pCampBot", "Your name")) 331 // Current create a new client on each connect. libomv doesn't seem to process new sim
332 // information (e.g. EstablishAgentCommunication events) if connecting after a disceonnect with the same
333 // client
334 CreateLibOmvClient();
335
336 if (Client.Network.Login(FirstName, LastName, Password, "pCampBot", StartLocation, "Your name"))
228 { 337 {
229 ConnectionState = ConnectionState.Connected; 338 ConnectionState = ConnectionState.Connected;
230 339
@@ -268,6 +377,30 @@ namespace pCampBot
268 } 377 }
269 } 378 }
270 379
380 /// <summary>
381 /// Sit this bot on the ground.
382 /// </summary>
383 public void SitOnGround()
384 {
385 if (ConnectionState == ConnectionState.Connected)
386 Client.Self.SitOnGround();
387 }
388
389 /// <summary>
390 /// Stand this bot
391 /// </summary>
392 public void Stand()
393 {
394 if (ConnectionState == ConnectionState.Connected)
395 {
396 // Unlike sit on ground, here libomv checks whether we have SEND_AGENT_UPDATES enabled.
397 bool prevUpdatesSetting = Client.Settings.SEND_AGENT_UPDATES;
398 Client.Settings.SEND_AGENT_UPDATES = true;
399 Client.Self.Stand();
400 Client.Settings.SEND_AGENT_UPDATES = prevUpdatesSetting;
401 }
402 }
403
271 public void SaveDefaultAppearance() 404 public void SaveDefaultAppearance()
272 { 405 {
273 saveDir = "MyAppearance/" + FirstName + "_" + LastName; 406 saveDir = "MyAppearance/" + FirstName + "_" + LastName;
@@ -451,7 +584,13 @@ namespace pCampBot
451 public void Network_SimConnected(object sender, SimConnectedEventArgs args) 584 public void Network_SimConnected(object sender, SimConnectedEventArgs args)
452 { 585 {
453 m_log.DebugFormat( 586 m_log.DebugFormat(
454 "[BOT]: Bot {0} connected to {1} at {2}", Name, args.Simulator.Name, args.Simulator.IPEndPoint); 587 "[BOT]: Bot {0} connected to region {1} at {2}", Name, args.Simulator.Name, args.Simulator.IPEndPoint);
588 }
589
590 public void Network_SimDisconnected(object sender, SimDisconnectedEventArgs args)
591 {
592 m_log.DebugFormat(
593 "[BOT]: Bot {0} disconnected from region {1} at {2}", Name, args.Simulator.Name, args.Simulator.IPEndPoint);
455 } 594 }
456 595
457 public void Network_OnDisconnected(object sender, DisconnectedEventArgs args) 596 public void Network_OnDisconnected(object sender, DisconnectedEventArgs args)
@@ -459,7 +598,7 @@ namespace pCampBot
459 ConnectionState = ConnectionState.Disconnected; 598 ConnectionState = ConnectionState.Disconnected;
460 599
461 m_log.DebugFormat( 600 m_log.DebugFormat(
462 "[BOT]: Bot {0} disconnected reason {1}, message {2}", Name, args.Reason, args.Message); 601 "[BOT]: Bot {0} disconnected from grid, reason {1}, message {2}", Name, args.Reason, args.Message);
463 602
464// m_log.ErrorFormat("Fired Network_OnDisconnected"); 603// m_log.ErrorFormat("Fired Network_OnDisconnected");
465 604
@@ -468,6 +607,8 @@ namespace pCampBot
468// || args.Reason == NetworkManager.DisconnectType.NetworkTimeout) 607// || args.Reason == NetworkManager.DisconnectType.NetworkTimeout)
469// && OnDisconnected != null) 608// && OnDisconnected != null)
470 609
610
611
471 if ( 612 if (
472 (args.Reason == NetworkManager.DisconnectType.ClientInitiated 613 (args.Reason == NetworkManager.DisconnectType.ClientInitiated
473 || args.Reason == NetworkManager.DisconnectType.ServerInitiated 614 || args.Reason == NetworkManager.DisconnectType.ServerInitiated
@@ -481,8 +622,8 @@ namespace pCampBot
481 622
482 public void Objects_NewPrim(object sender, PrimEventArgs args) 623 public void Objects_NewPrim(object sender, PrimEventArgs args)
483 { 624 {
484// if (Name.EndsWith("4")) 625 if (!RequestObjectTextures)
485// throw new Exception("Aaargh"); 626 return;
486 627
487 Primitive prim = args.Prim; 628 Primitive prim = args.Prim;
488 629
diff --git a/OpenSim/Tools/pCampBot/BotManager.cs b/OpenSim/Tools/pCampBot/BotManager.cs
index d615b3f..abc71cb 100644
--- a/OpenSim/Tools/pCampBot/BotManager.cs
+++ b/OpenSim/Tools/pCampBot/BotManager.cs
@@ -52,6 +52,16 @@ namespace pCampBot
52 public const int DefaultLoginDelay = 5000; 52 public const int DefaultLoginDelay = 5000;
53 53
54 /// <summary> 54 /// <summary>
55 /// Is pCampbot in the process of connecting bots?
56 /// </summary>
57 public bool ConnectingBots { get; private set; }
58
59 /// <summary>
60 /// Is pCampbot in the process of disconnecting bots?
61 /// </summary>
62 public bool DisconnectingBots { get; private set; }
63
64 /// <summary>
55 /// Delay between logins of multiple bots. 65 /// Delay between logins of multiple bots.
56 /// </summary> 66 /// </summary>
57 /// <remarks>TODO: This value needs to be configurable by a command line argument.</remarks> 67 /// <remarks>TODO: This value needs to be configurable by a command line argument.</remarks>
@@ -63,19 +73,24 @@ namespace pCampBot
63 protected CommandConsole m_console; 73 protected CommandConsole m_console;
64 74
65 /// <summary> 75 /// <summary>
66 /// Created bots, whether active or inactive. 76 /// Controls whether bots start out sending agent updates on connection.
67 /// </summary> 77 /// </summary>
68 protected List<Bot> m_lBot; 78 public bool InitBotSendAgentUpdates { get; set; }
69 79
70 /// <summary> 80 /// <summary>
71 /// Random number generator. 81 /// Controls whether bots request textures for the object information they receive
72 /// </summary> 82 /// </summary>
73 public Random Rng { get; private set; } 83 public bool InitBotRequestObjectTextures { get; set; }
74 84
75 /// <summary> 85 /// <summary>
76 /// Overall configuration. 86 /// Created bots, whether active or inactive.
77 /// </summary> 87 /// </summary>
78 public IConfig Config { get; private set; } 88 protected List<Bot> m_bots;
89
90 /// <summary>
91 /// Random number generator.
92 /// </summary>
93 public Random Rng { get; private set; }
79 94
80 /// <summary> 95 /// <summary>
81 /// Track the assets we have and have not received so we don't endlessly repeat requests. 96 /// Track the assets we have and have not received so we don't endlessly repeat requests.
@@ -88,10 +103,53 @@ namespace pCampBot
88 public Dictionary<ulong, GridRegion> RegionsKnown { get; private set; } 103 public Dictionary<ulong, GridRegion> RegionsKnown { get; private set; }
89 104
90 /// <summary> 105 /// <summary>
106 /// First name for bots
107 /// </summary>
108 private string m_firstName;
109
110 /// <summary>
111 /// Last name stem for bots
112 /// </summary>
113 private string m_lastNameStem;
114
115 /// <summary>
116 /// Password for bots
117 /// </summary>
118 private string m_password;
119
120 /// <summary>
121 /// Login URI for bots.
122 /// </summary>
123 private string m_loginUri;
124
125 /// <summary>
126 /// Start location for bots.
127 /// </summary>
128 private string m_startUri;
129
130 /// <summary>
131 /// Postfix bot number at which bot sequence starts.
132 /// </summary>
133 private int m_fromBotNumber;
134
135 /// <summary>
136 /// Wear setting for bots.
137 /// </summary>
138 private string m_wearSetting;
139
140 /// <summary>
141 /// Behaviour switches for bots.
142 /// </summary>
143 private HashSet<string> m_defaultBehaviourSwitches = new HashSet<string>();
144
145 /// <summary>
91 /// Constructor Creates MainConsole.Instance to take commands and provide the place to write data 146 /// Constructor Creates MainConsole.Instance to take commands and provide the place to write data
92 /// </summary> 147 /// </summary>
93 public BotManager() 148 public BotManager()
94 { 149 {
150 InitBotSendAgentUpdates = true;
151 InitBotRequestObjectTextures = true;
152
95 LoginDelay = DefaultLoginDelay; 153 LoginDelay = DefaultLoginDelay;
96 154
97 Rng = new Random(Environment.TickCount); 155 Rng = new Random(Environment.TickCount);
@@ -117,30 +175,61 @@ namespace pCampBot
117 } 175 }
118 } 176 }
119 177
120 m_console.Commands.AddCommand("bot", false, "shutdown", 178 m_console.Commands.AddCommand(
121 "shutdown", 179 "Bots", false, "shutdown", "shutdown", "Shutdown bots and exit", HandleShutdown);
122 "Shutdown bots and exit", HandleShutdown); 180
123 181 m_console.Commands.AddCommand(
124 m_console.Commands.AddCommand("bot", false, "quit", 182 "Bots", false, "quit", "quit", "Shutdown bots and exit", HandleShutdown);
125 "quit", 183
126 "Shutdown bots and exit", 184 m_console.Commands.AddCommand(
127 HandleShutdown); 185 "Bots", false, "connect", "connect [<n>]", "Connect bots",
128 186 "If an <n> is given, then the first <n> disconnected bots by postfix number are connected.\n"
129 m_console.Commands.AddCommand("bot", false, "show regions", 187 + "If no <n> is given, then all currently disconnected bots are connected.",
130 "show regions", 188 HandleConnect);
131 "Show regions known to bots", 189
132 HandleShowRegions); 190 m_console.Commands.AddCommand(
133 191 "Bots", false, "disconnect", "disconnect [<n>]", "Disconnect bots",
134 m_console.Commands.AddCommand("bot", false, "show bots", 192 "Disconnecting bots will interupt any bot connection process, including connection on startup.\n"
135 "show bots", 193 + "If an <n> is given, then the last <n> connected bots by postfix number are disconnected.\n"
136 "Shows the status of all bots", 194 + "If no <n> is given, then all currently connected bots are disconnected.",
137 HandleShowStatus); 195 HandleDisconnect);
138 196
139// m_console.Commands.AddCommand("bot", false, "add bots", 197 m_console.Commands.AddCommand(
140// "add bots <number>", 198 "Bots", false, "add behaviour", "add behaviour <abbreviated-name> [<bot-number>]",
141// "Add more bots", HandleAddBots); 199 "Add a behaviour to a bot",
142 200 "If no bot number is specified then behaviour is added to all bots.\n"
143 m_lBot = new List<Bot>(); 201 + "Can be performed on connected or disconnected bots.",
202 HandleAddBehaviour);
203
204 m_console.Commands.AddCommand(
205 "Bots", false, "remove behaviour", "remove behaviour <abbreviated-name> [<bot-number>]",
206 "Remove a behaviour from a bot",
207 "If no bot number is specified then behaviour is added to all bots.\n"
208 + "Can be performed on connected or disconnected bots.",
209 HandleRemoveBehaviour);
210
211 m_console.Commands.AddCommand(
212 "Bots", false, "sit", "sit", "Sit all bots on the ground.",
213 HandleSit);
214
215 m_console.Commands.AddCommand(
216 "Bots", false, "stand", "stand", "Stand all bots.",
217 HandleStand);
218
219 m_console.Commands.AddCommand(
220 "Bots", false, "set bots", "set bots <key> <value>", "Set a setting for all bots.", HandleSetBots);
221
222 m_console.Commands.AddCommand(
223 "Bots", false, "show regions", "show regions", "Show regions known to bots", HandleShowRegions);
224
225 m_console.Commands.AddCommand(
226 "Bots", false, "show bots", "show bots", "Shows the status of all bots", HandleShowBotsStatus);
227
228 m_console.Commands.AddCommand(
229 "Bots", false, "show bot", "show bot <bot-number>",
230 "Shows the detailed status and settings of a particular bot.", HandleShowBotStatus);
231
232 m_bots = new List<Bot>();
144 } 233 }
145 234
146 /// <summary> 235 /// <summary>
@@ -148,74 +237,167 @@ namespace pCampBot
148 /// </summary> 237 /// </summary>
149 /// <param name="botcount">How many bots to start up</param> 238 /// <param name="botcount">How many bots to start up</param>
150 /// <param name="cs">The configuration for the bots to use</param> 239 /// <param name="cs">The configuration for the bots to use</param>
151 public void dobotStartup(int botcount, IConfig cs) 240 public void CreateBots(int botcount, IConfig startupConfig)
152 { 241 {
153 Config = cs; 242 m_firstName = startupConfig.GetString("firstname");
243 m_lastNameStem = startupConfig.GetString("lastname");
244 m_password = startupConfig.GetString("password");
245 m_loginUri = startupConfig.GetString("loginuri");
246 m_fromBotNumber = startupConfig.GetInt("from", 0);
247 m_wearSetting = startupConfig.GetString("wear", "no");
154 248
155 string firstName = cs.GetString("firstname"); 249 m_startUri = ParseInputStartLocationToUri(startupConfig.GetString("start", "last"));
156 string lastNameStem = cs.GetString("lastname");
157 string password = cs.GetString("password");
158 string loginUri = cs.GetString("loginuri");
159 250
160 HashSet<string> behaviourSwitches = new HashSet<string>();
161 Array.ForEach<string>( 251 Array.ForEach<string>(
162 cs.GetString("behaviours", "p").Split(new char[] { ',' }), b => behaviourSwitches.Add(b)); 252 startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => m_defaultBehaviourSwitches.Add(b));
253
254 for (int i = 0; i < botcount; i++)
255 {
256 lock (m_bots)
257 {
258 string lastName = string.Format("{0}_{1}", m_lastNameStem, i + m_fromBotNumber);
259
260 CreateBot(
261 this,
262 CreateBehavioursFromAbbreviatedNames(m_defaultBehaviourSwitches),
263 m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting);
264 }
265 }
266 }
267
268 private List<IBehaviour> CreateBehavioursFromAbbreviatedNames(HashSet<string> abbreviatedNames)
269 {
270 // We must give each bot its own list of instantiated behaviours since they store state.
271 List<IBehaviour> behaviours = new List<IBehaviour>();
272
273 // Hard-coded for now
274 foreach (string abName in abbreviatedNames)
275 {
276 IBehaviour newBehaviour = null;
277
278 if (abName == "c")
279 newBehaviour = new CrossBehaviour();
280
281 if (abName == "g")
282 newBehaviour = new GrabbingBehaviour();
283
284 if (abName == "n")
285 newBehaviour = new NoneBehaviour();
286
287 if (abName == "p")
288 newBehaviour = new PhysicsBehaviour();
289
290 if (abName == "t")
291 newBehaviour = new TeleportBehaviour();
292
293 if (newBehaviour != null)
294 {
295 behaviours.Add(newBehaviour);
296 }
297 else
298 {
299 MainConsole.Instance.OutputFormat("No behaviour with abbreviated name {0} found", abName);
300 }
301 }
302
303 return behaviours;
304 }
163 305
306 public void ConnectBots(int botcount)
307 {
308 ConnectingBots = true;
309
310 Thread connectBotThread = new Thread(o => ConnectBotsInternal(botcount));
311
312 connectBotThread.Name = "Bots connection thread";
313 connectBotThread.Start();
314 }
315
316 private void ConnectBotsInternal(int botCount)
317 {
164 MainConsole.Instance.OutputFormat( 318 MainConsole.Instance.OutputFormat(
165 "[BOT MANAGER]: Starting {0} bots connecting to {1}, named {2} {3}_<n>", 319 "[BOT MANAGER]: Starting {0} bots connecting to {1}, location {2}, named {3} {4}_<n>",
166 botcount, 320 botCount,
167 loginUri, 321 m_loginUri,
168 firstName, 322 m_startUri,
169 lastNameStem); 323 m_firstName,
324 m_lastNameStem);
170 325
171 MainConsole.Instance.OutputFormat("[BOT MANAGER]: Delay between logins is {0}ms", LoginDelay); 326 MainConsole.Instance.OutputFormat("[BOT MANAGER]: Delay between logins is {0}ms", LoginDelay);
327 MainConsole.Instance.OutputFormat("[BOT MANAGER]: BotsSendAgentUpdates is {0}", InitBotSendAgentUpdates);
328 MainConsole.Instance.OutputFormat("[BOT MANAGER]: InitBotRequestObjectTextures is {0}", InitBotRequestObjectTextures);
172 329
173 for (int i = 0; i < botcount; i++) 330 int connectedBots = 0;
331
332 for (int i = 0; i < m_bots.Count; i++)
174 { 333 {
175 string lastName = string.Format("{0}_{1}", lastNameStem, i); 334 lock (m_bots)
176 335 {
177 // We must give each bot its own list of instantiated behaviours since they store state. 336 if (DisconnectingBots)
178 List<IBehaviour> behaviours = new List<IBehaviour>(); 337 {
179 338 MainConsole.Instance.Output(
180 // Hard-coded for now 339 "[BOT MANAGER]: Aborting bot connection due to user-initiated disconnection");
181 if (behaviourSwitches.Contains("p")) 340 break;
182 behaviours.Add(new PhysicsBehaviour()); 341 }
183 342
184 if (behaviourSwitches.Contains("g")) 343 if (m_bots[i].ConnectionState == ConnectionState.Disconnected)
185 behaviours.Add(new GrabbingBehaviour()); 344 {
186 345 m_bots[i].Connect();
187 if (behaviourSwitches.Contains("t")) 346 connectedBots++;
188 behaviours.Add(new TeleportBehaviour()); 347
189 348 if (connectedBots >= botCount)
190 if (behaviourSwitches.Contains("c")) 349 break;
191 behaviours.Add(new CrossBehaviour()); 350
192 351 // Stagger logins
193 StartBot(this, behaviours, firstName, lastName, password, loginUri); 352 Thread.Sleep(LoginDelay);
353 }
354 }
194 } 355 }
356
357 ConnectingBots = false;
195 } 358 }
196 359
197// /// <summary> 360 /// <summary>
198// /// Add additional bots (and threads) to our bot pool 361 /// Parses the command line start location to a start string/uri that the login mechanism will recognize.
199// /// </summary> 362 /// </summary>
200// /// <param name="botcount">How Many of them to add</param> 363 /// <returns>
201// public void addbots(int botcount) 364 /// The input start location to URI.
202// { 365 /// </returns>
203// int len = m_td.Length; 366 /// <param name='startLocation'>
204// Thread[] m_td2 = new Thread[len + botcount]; 367 /// Start location.
205// for (int i = 0; i < len; i++) 368 /// </param>
206// { 369 private string ParseInputStartLocationToUri(string startLocation)
207// m_td2[i] = m_td[i]; 370 {
208// } 371 if (startLocation == "home" || startLocation == "last")
209// m_td = m_td2; 372 return startLocation;
210// int newlen = len + botcount; 373
211// for (int i = len; i < newlen; i++) 374 string regionName;
212// { 375
213// startupBot(Config); 376 // Just a region name or only one (!) extra component. Like a viewer, we will stick 128/128/0 on the end
214// } 377 Vector3 startPos = new Vector3(128, 128, 0);
215// } 378
379 string[] startLocationComponents = startLocation.Split('/');
380
381 regionName = startLocationComponents[0];
382
383 if (startLocationComponents.Length >= 2)
384 {
385 float.TryParse(startLocationComponents[1], out startPos.X);
386
387 if (startLocationComponents.Length >= 3)
388 {
389 float.TryParse(startLocationComponents[2], out startPos.Y);
390
391 if (startLocationComponents.Length >= 4)
392 float.TryParse(startLocationComponents[3], out startPos.Z);
393 }
394 }
395
396 return string.Format("uri:{0}&{1}&{2}&{3}", regionName, startPos.X, startPos.Y, startPos.Z);
397 }
216 398
217 /// <summary> 399 /// <summary>
218 /// This starts up the bot and stores the thread for the bot in the thread array 400 /// This creates a bot but does not start it.
219 /// </summary> 401 /// </summary>
220 /// <param name="bm"></param> 402 /// <param name="bm"></param>
221 /// <param name="behaviours">Behaviours for this bot to perform.</param> 403 /// <param name="behaviours">Behaviours for this bot to perform.</param>
@@ -223,30 +405,25 @@ namespace pCampBot
223 /// <param name="lastName">Last name</param> 405 /// <param name="lastName">Last name</param>
224 /// <param name="password">Password</param> 406 /// <param name="password">Password</param>
225 /// <param name="loginUri">Login URI</param> 407 /// <param name="loginUri">Login URI</param>
226 public void StartBot( 408 /// <param name="startLocation">Location to start the bot. Can be "last", "home" or a specific sim name.</param>
409 /// <param name="wearSetting"></param>
410 public void CreateBot(
227 BotManager bm, List<IBehaviour> behaviours, 411 BotManager bm, List<IBehaviour> behaviours,
228 string firstName, string lastName, string password, string loginUri) 412 string firstName, string lastName, string password, string loginUri, string startLocation, string wearSetting)
229 { 413 {
230 MainConsole.Instance.OutputFormat( 414 MainConsole.Instance.OutputFormat(
231 "[BOT MANAGER]: Starting bot {0} {1}, behaviours are {2}", 415 "[BOT MANAGER]: Creating bot {0} {1}, behaviours are {2}",
232 firstName, lastName, string.Join(",", behaviours.ConvertAll<string>(b => b.Name).ToArray())); 416 firstName, lastName, string.Join(",", behaviours.ConvertAll<string>(b => b.Name).ToArray()));
233 417
234 Bot pb = new Bot(bm, behaviours, firstName, lastName, password, loginUri); 418 Bot pb = new Bot(bm, behaviours, firstName, lastName, password, startLocation, loginUri);
419 pb.wear = wearSetting;
420 pb.Client.Settings.SEND_AGENT_UPDATES = InitBotSendAgentUpdates;
421 pb.RequestObjectTextures = InitBotRequestObjectTextures;
235 422
236 pb.OnConnected += handlebotEvent; 423 pb.OnConnected += handlebotEvent;
237 pb.OnDisconnected += handlebotEvent; 424 pb.OnDisconnected += handlebotEvent;
238 425
239 lock (m_lBot) 426 m_bots.Add(pb);
240 m_lBot.Add(pb);
241
242 Thread pbThread = new Thread(pb.startup);
243 pbThread.Name = pb.Name;
244 pbThread.IsBackground = true;
245
246 pbThread.Start();
247
248 // Stagger logins
249 Thread.Sleep(LoginDelay);
250 } 427 }
251 428
252 /// <summary> 429 /// <summary>
@@ -259,52 +436,270 @@ namespace pCampBot
259 switch (eventt) 436 switch (eventt)
260 { 437 {
261 case EventType.CONNECTED: 438 case EventType.CONNECTED:
439 {
262 m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Connected"); 440 m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Connected");
263 break; 441 break;
442 }
443
264 case EventType.DISCONNECTED: 444 case EventType.DISCONNECTED:
445 {
265 m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Disconnected"); 446 m_log.Info("[" + callbot.FirstName + " " + callbot.LastName + "]: Disconnected");
447 break;
448 }
449 }
450 }
266 451
267 lock (m_lBot) 452 /// <summary>
268 { 453 /// Standard CreateConsole routine
269 if (m_lBot.TrueForAll(b => b.ConnectionState == ConnectionState.Disconnected)) 454 /// </summary>
270 Environment.Exit(0); 455 /// <returns></returns>
456 protected CommandConsole CreateConsole()
457 {
458 return new LocalConsole("pCampbot");
459 }
271 460
272 break; 461 private void HandleConnect(string module, string[] cmd)
462 {
463 if (ConnectingBots)
464 {
465 MainConsole.Instance.Output("Still connecting bots. Please wait for previous process to complete.");
466 return;
467 }
468
469 lock (m_bots)
470 {
471 int botsToConnect;
472 int disconnectedBots = m_bots.Count(b => b.ConnectionState == ConnectionState.Disconnected);
473
474 if (cmd.Length == 1)
475 {
476 botsToConnect = disconnectedBots;
477 }
478 else
479 {
480 if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[1], out botsToConnect))
481 return;
482
483 botsToConnect = Math.Min(botsToConnect, disconnectedBots);
484 }
485
486 MainConsole.Instance.OutputFormat("Connecting {0} bots", botsToConnect);
487
488 ConnectBots(botsToConnect);
489 }
490 }
491
492 private void HandleAddBehaviour(string module, string[] cmd)
493 {
494 if (cmd.Length < 3 || cmd.Length > 4)
495 {
496 MainConsole.Instance.OutputFormat("Usage: add behaviour <abbreviated-behaviour> [<bot-number>]");
497 return;
498 }
499
500 string rawBehaviours = cmd[2];
501
502 List<Bot> botsToEffect = new List<Bot>();
503
504 if (cmd.Length == 3)
505 {
506 lock (m_bots)
507 botsToEffect.AddRange(m_bots);
508 }
509 else
510 {
511 int botNumber;
512 if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[3], out botNumber))
513 return;
514
515 Bot bot = GetBotFromNumber(botNumber);
516
517 if (bot == null)
518 {
519 MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber);
520 return;
521 }
522
523 botsToEffect.Add(bot);
524 }
525
526
527 HashSet<string> rawAbbreviatedSwitchesToAdd = new HashSet<string>();
528 Array.ForEach<string>(rawBehaviours.Split(new char[] { ',' }), b => rawAbbreviatedSwitchesToAdd.Add(b));
529
530 foreach (Bot bot in botsToEffect)
531 {
532 List<IBehaviour> behavioursAdded = new List<IBehaviour>();
533
534 foreach (IBehaviour behaviour in CreateBehavioursFromAbbreviatedNames(rawAbbreviatedSwitchesToAdd))
535 {
536 if (bot.AddBehaviour(behaviour))
537 behavioursAdded.Add(behaviour);
538 }
539
540 MainConsole.Instance.OutputFormat(
541 "Added behaviours {0} to bot {1}",
542 string.Join(", ", behavioursAdded.ConvertAll<string>(b => b.Name).ToArray()), bot.Name);
543 }
544 }
545
546 private void HandleRemoveBehaviour(string module, string[] cmd)
547 {
548 if (cmd.Length < 3 || cmd.Length > 4)
549 {
550 MainConsole.Instance.OutputFormat("Usage: remove behaviour <abbreviated-behaviour> [<bot-number>]");
551 return;
552 }
553
554 string rawBehaviours = cmd[2];
555
556 List<Bot> botsToEffect = new List<Bot>();
557
558 if (cmd.Length == 3)
559 {
560 lock (m_bots)
561 botsToEffect.AddRange(m_bots);
562 }
563 else
564 {
565 int botNumber;
566 if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[3], out botNumber))
567 return;
568
569 Bot bot = GetBotFromNumber(botNumber);
570
571 if (bot == null)
572 {
573 MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber);
574 return;
575 }
576
577 botsToEffect.Add(bot);
578 }
579
580 HashSet<string> abbreviatedBehavioursToRemove = new HashSet<string>();
581 Array.ForEach<string>(rawBehaviours.Split(new char[] { ',' }), b => abbreviatedBehavioursToRemove.Add(b));
582
583 foreach (Bot bot in botsToEffect)
584 {
585 List<IBehaviour> behavioursRemoved = new List<IBehaviour>();
586
587 foreach (string b in abbreviatedBehavioursToRemove)
588 {
589 IBehaviour behaviour;
590
591 if (bot.TryGetBehaviour(b, out behaviour))
592 {
593 bot.RemoveBehaviour(b);
594 behavioursRemoved.Add(behaviour);
273 } 595 }
596 }
597
598 MainConsole.Instance.OutputFormat(
599 "Removed behaviours {0} to bot {1}",
600 string.Join(", ", behavioursRemoved.ConvertAll<string>(b => b.Name).ToArray()), bot.Name);
274 } 601 }
275 } 602 }
276 603
277 /// <summary> 604 private void HandleDisconnect(string module, string[] cmd)
278 /// Shut down all bots
279 /// </summary>
280 /// <remarks>
281 /// We launch each shutdown on its own thread so that a slow shutting down bot doesn't hold up all the others.
282 /// </remarks>
283 public void doBotShutdown()
284 { 605 {
285 lock (m_lBot) 606 lock (m_bots)
286 { 607 {
287 foreach (Bot bot in m_lBot) 608 int botsToDisconnect;
609 int connectedBots = m_bots.Count(b => b.ConnectionState == ConnectionState.Connected);
610
611 if (cmd.Length == 1)
288 { 612 {
289 Bot thisBot = bot; 613 botsToDisconnect = connectedBots;
290 Util.FireAndForget(o => thisBot.shutdown());
291 } 614 }
615 else
616 {
617 if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[1], out botsToDisconnect))
618 return;
619
620 botsToDisconnect = Math.Min(botsToDisconnect, connectedBots);
621 }
622
623 DisconnectingBots = true;
624
625 MainConsole.Instance.OutputFormat("Disconnecting {0} bots", botsToDisconnect);
626
627 int disconnectedBots = 0;
628
629 for (int i = m_bots.Count - 1; i >= 0; i--)
630 {
631 if (disconnectedBots >= botsToDisconnect)
632 break;
633
634 Bot thisBot = m_bots[i];
635
636 if (thisBot.ConnectionState == ConnectionState.Connected)
637 {
638 Util.FireAndForget(o => thisBot.Disconnect());
639 disconnectedBots++;
640 }
641 }
642
643 DisconnectingBots = false;
292 } 644 }
293 } 645 }
294 646
295 /// <summary> 647 private void HandleSit(string module, string[] cmd)
296 /// Standard CreateConsole routine
297 /// </summary>
298 /// <returns></returns>
299 protected CommandConsole CreateConsole()
300 { 648 {
301 return new LocalConsole("pCampbot"); 649 lock (m_bots)
650 {
651 m_bots.ForEach(b => b.SitOnGround());
652 }
653 }
654
655 private void HandleStand(string module, string[] cmd)
656 {
657 lock (m_bots)
658 {
659 m_bots.ForEach(b => b.Stand());
660 }
302 } 661 }
303 662
304 private void HandleShutdown(string module, string[] cmd) 663 private void HandleShutdown(string module, string[] cmd)
305 { 664 {
306 m_log.Info("[BOTMANAGER]: Shutting down bots"); 665 lock (m_bots)
307 doBotShutdown(); 666 {
667 int connectedBots = m_bots.Count(b => b.ConnectionState == ConnectionState.Connected);
668
669 if (connectedBots > 0)
670 {
671 MainConsole.Instance.OutputFormat("Please disconnect {0} connected bots first", connectedBots);
672 return;
673 }
674 }
675
676 MainConsole.Instance.Output("Shutting down");
677
678 Environment.Exit(0);
679 }
680
681 private void HandleSetBots(string module, string[] cmd)
682 {
683 string key = cmd[2];
684 string rawValue = cmd[3];
685
686 if (key == "SEND_AGENT_UPDATES")
687 {
688 bool newSendAgentUpdatesSetting;
689
690 if (!ConsoleUtil.TryParseConsoleBool(MainConsole.Instance, rawValue, out newSendAgentUpdatesSetting))
691 return;
692
693 MainConsole.Instance.OutputFormat(
694 "Setting SEND_AGENT_UPDATES to {0} for all bots", newSendAgentUpdatesSetting);
695
696 lock (m_bots)
697 m_bots.ForEach(b => b.Client.Settings.SEND_AGENT_UPDATES = newSendAgentUpdatesSetting);
698 }
699 else
700 {
701 MainConsole.Instance.Output("Error: Only setting currently available is SEND_AGENT_UPDATES");
702 }
308 } 703 }
309 704
310 private void HandleShowRegions(string module, string[] cmd) 705 private void HandleShowRegions(string module, string[] cmd)
@@ -322,43 +717,114 @@ namespace pCampBot
322 } 717 }
323 } 718 }
324 719
325 private void HandleShowStatus(string module, string[] cmd) 720 private void HandleShowBotsStatus(string module, string[] cmd)
326 { 721 {
327 string outputFormat = "{0,-30} {1, -30} {2,-14}"; 722 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
328 MainConsole.Instance.OutputFormat(outputFormat, "Name", "Region", "Status"); 723 cdt.AddColumn("Name", 24);
329 724 cdt.AddColumn("Region", 24);
330 lock (m_lBot) 725 cdt.AddColumn("Status", 13);
726 cdt.AddColumn("Conns", 5);
727 cdt.AddColumn("Behaviours", 20);
728
729 Dictionary<ConnectionState, int> totals = new Dictionary<ConnectionState, int>();
730 foreach (object o in Enum.GetValues(typeof(ConnectionState)))
731 totals[(ConnectionState)o] = 0;
732
733 lock (m_bots)
331 { 734 {
332 foreach (Bot pb in m_lBot) 735 foreach (Bot bot in m_bots)
333 { 736 {
334 Simulator currentSim = pb.Client.Network.CurrentSim; 737 Simulator currentSim = bot.Client.Network.CurrentSim;
335 738 totals[bot.ConnectionState]++;
336 MainConsole.Instance.OutputFormat( 739
337 outputFormat, 740 cdt.AddRow(
338 pb.Name, currentSim != null ? currentSim.Name : "(none)", pb.ConnectionState); 741 bot.Name,
742 currentSim != null ? currentSim.Name : "(none)",
743 bot.ConnectionState,
744 bot.SimulatorsCount,
745 string.Join(",", bot.Behaviours.Keys.ToArray()));
339 } 746 }
340 } 747 }
748
749 MainConsole.Instance.Output(cdt.ToString());
750
751 ConsoleDisplayList cdl = new ConsoleDisplayList();
752
753 foreach (KeyValuePair<ConnectionState, int> kvp in totals)
754 cdl.AddRow(kvp.Key, kvp.Value);
755
756 MainConsole.Instance.Output(cdl.ToString());
341 } 757 }
342 758
343 /* 759 private void HandleShowBotStatus(string module, string[] cmd)
344 private void HandleQuit(string module, string[] cmd)
345 { 760 {
346 m_console.Warn("DANGER", "This should only be used to quit the program if you've already used the shutdown command and the program hasn't quit"); 761 if (cmd.Length != 3)
347 Environment.Exit(0); 762 {
763 MainConsole.Instance.Output("Usage: show bot <n>");
764 return;
765 }
766
767 int botNumber;
768
769 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, cmd[2], out botNumber))
770 return;
771
772 Bot bot = GetBotFromNumber(botNumber);
773
774 if (bot == null)
775 {
776 MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber);
777 return;
778 }
779
780 ConsoleDisplayList cdl = new ConsoleDisplayList();
781 cdl.AddRow("Name", bot.Name);
782 cdl.AddRow("Status", bot.ConnectionState);
783
784 Simulator currentSim = bot.Client.Network.CurrentSim;
785 cdl.AddRow("Region", currentSim != null ? currentSim.Name : "(none)");
786
787 List<Simulator> connectedSimulators = bot.Simulators;
788 List<string> simulatorNames = connectedSimulators.ConvertAll<string>(cs => cs.Name);
789 cdl.AddRow("Connections", string.Join(", ", simulatorNames.ToArray()));
790
791 MainConsole.Instance.Output(cdl.ToString());
792
793 MainConsole.Instance.Output("Settings");
794
795 ConsoleDisplayList statusCdl = new ConsoleDisplayList();
796
797 statusCdl.AddRow(
798 "Behaviours",
799 string.Join(", ", bot.Behaviours.Values.ToList().ConvertAll<string>(b => b.Name).ToArray()));
800
801 GridClient botClient = bot.Client;
802 statusCdl.AddRow("SEND_AGENT_UPDATES", botClient.Settings.SEND_AGENT_UPDATES);
803
804 MainConsole.Instance.Output(statusCdl.ToString());
805 }
806
807 /// <summary>
808 /// Get a specific bot from its number.
809 /// </summary>
810 /// <returns>null if no bot was found</returns>
811 /// <param name='botNumber'></param>
812 private Bot GetBotFromNumber(int botNumber)
813 {
814 string name = GenerateBotNameFromNumber(botNumber);
815
816 Bot bot;
817
818 lock (m_bots)
819 bot = m_bots.Find(b => b.Name == name);
820
821 return bot;
822 }
823
824 private string GenerateBotNameFromNumber(int botNumber)
825 {
826 return string.Format("{0} {1}_{2}", m_firstName, m_lastNameStem, botNumber);
348 } 827 }
349 */
350//
351// private void HandleAddBots(string module, string[] cmd)
352// {
353// int newbots = 0;
354//
355// if (cmd.Length > 2)
356// {
357// Int32.TryParse(cmd[2], out newbots);
358// }
359// if (newbots > 0)
360// addbots(newbots);
361// }
362 828
363 internal void Grid_GridRegion(object o, GridRegionEventArgs args) 829 internal void Grid_GridRegion(object o, GridRegionEventArgs args)
364 { 830 {
@@ -379,4 +845,4 @@ namespace pCampBot
379 } 845 }
380 } 846 }
381 } 847 }
382} 848} \ No newline at end of file
diff --git a/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs b/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs
index 9c984be..0ed4825 100644
--- a/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs
@@ -32,6 +32,11 @@ namespace pCampBot.Interfaces
32 public interface IBehaviour 32 public interface IBehaviour
33 { 33 {
34 /// <summary> 34 /// <summary>
35 /// Abbreviated name of this behaviour.
36 /// </summary>
37 string AbbreviatedName { get; }
38
39 /// <summary>
35 /// Name of this behaviour. 40 /// Name of this behaviour.
36 /// </summary> 41 /// </summary>
37 string Name { get; } 42 string Name { get; }
@@ -46,6 +51,14 @@ namespace pCampBot.Interfaces
46 void Initialize(Bot bot); 51 void Initialize(Bot bot);
47 52
48 /// <summary> 53 /// <summary>
54 /// Close down this behaviour.
55 /// </summary>
56 /// <remarks>
57 /// This is triggered if a behaviour is removed via explicit command and when a bot is disconnected
58 /// </remarks>
59 void Close();
60
61 /// <summary>
49 /// Action to take when this behaviour is invoked. 62 /// Action to take when this behaviour is invoked.
50 /// </summary> 63 /// </summary>
51 /// <param name="bot"></param> 64 /// <param name="bot"></param>
diff --git a/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs b/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs
index 78f3603..731e2c3 100644
--- a/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs
+++ b/OpenSim/Tools/pCampBot/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.6.*")] 32[assembly: AssemblyVersion("0.8.0.*")]
33 33
diff --git a/OpenSim/Tools/pCampBot/pCampBot.cs b/OpenSim/Tools/pCampBot/pCampBot.cs
index 9e82577..1fb0e03 100644
--- a/OpenSim/Tools/pCampBot/pCampBot.cs
+++ b/OpenSim/Tools/pCampBot/pCampBot.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.IO;
29using System.Reflection; 30using System.Reflection;
30using System.Threading; 31using System.Threading;
31using log4net; 32using log4net;
@@ -50,30 +51,62 @@ namespace pCampBot
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);
52 53
54 public const string ConfigFileName = "pCampBot.ini";
55
53 [STAThread] 56 [STAThread]
54 public static void Main(string[] args) 57 public static void Main(string[] args)
55 { 58 {
56 XmlConfigurator.Configure(); 59 XmlConfigurator.Configure();
57 60
58 IConfig config = ParseConfig(args); 61 IConfig commandLineConfig = ParseConfig(args);
59 if (config.Get("help") != null || config.Get("loginuri") == null) 62 if (commandLineConfig.Get("help") != null || commandLineConfig.Get("loginuri") == null)
60 { 63 {
61 Help(); 64 Help();
62 } 65 }
63 else if (config.Get("firstname") == null || config.Get("lastname") == null || config.Get("password") == null) 66 else if (
67 commandLineConfig.Get("firstname") == null
68 || commandLineConfig.Get("lastname") == null
69 || commandLineConfig.Get("password") == null)
64 { 70 {
65 Console.WriteLine("ERROR: You must supply a firstname, lastname and password for the bots."); 71 Console.WriteLine("ERROR: You must supply a firstname, lastname and password for the bots.");
66 } 72 }
67 else 73 else
68 { 74 {
69 int botcount = config.GetInt("botcount", 1);
70
71 BotManager bm = new BotManager(); 75 BotManager bm = new BotManager();
72 76
73 //startup specified number of bots. 1 is the default 77 string iniFilePath = Path.GetFullPath(Path.Combine(Util.configDir(), ConfigFileName));
74 Thread startBotThread = new Thread(o => bm.dobotStartup(botcount, config)); 78
75 startBotThread.Name = "Initial start bots thread"; 79 if (File.Exists(iniFilePath))
76 startBotThread.Start(); 80 {
81 m_log.InfoFormat("[PCAMPBOT]: Reading configuration settings from {0}", iniFilePath);
82
83 IConfigSource configSource = new IniConfigSource(iniFilePath);
84
85 IConfig botManagerConfig = configSource.Configs["BotManager"];
86
87 if (botManagerConfig != null)
88 {
89 bm.LoginDelay = botManagerConfig.GetInt("LoginDelay", bm.LoginDelay);
90 }
91
92 IConfig botConfig = configSource.Configs["Bot"];
93
94 if (botConfig != null)
95 {
96 bm.InitBotSendAgentUpdates
97 = botConfig.GetBoolean("SendAgentUpdates", bm.InitBotSendAgentUpdates);
98 bm.InitBotRequestObjectTextures
99 = botConfig.GetBoolean("RequestObjectTextures", bm.InitBotRequestObjectTextures);
100 }
101 }
102
103 int botcount = commandLineConfig.GetInt("botcount", 1);
104 bool startConnected = commandLineConfig.Get("connect") != null;
105
106 bm.CreateBots(botcount, commandLineConfig);
107
108 if (startConnected)
109 bm.ConnectBots(botcount);
77 110
78 while (true) 111 while (true)
79 { 112 {
@@ -94,8 +127,11 @@ namespace pCampBot
94 //Set up our nifty config.. thanks to nini 127 //Set up our nifty config.. thanks to nini
95 ArgvConfigSource cs = new ArgvConfigSource(args); 128 ArgvConfigSource cs = new ArgvConfigSource(args);
96 129
130 cs.AddSwitch("Startup", "connect", "c");
97 cs.AddSwitch("Startup", "botcount", "n"); 131 cs.AddSwitch("Startup", "botcount", "n");
132 cs.AddSwitch("Startup", "from", "f");
98 cs.AddSwitch("Startup", "loginuri", "l"); 133 cs.AddSwitch("Startup", "loginuri", "l");
134 cs.AddSwitch("Startup", "start", "s");
99 cs.AddSwitch("Startup", "firstname"); 135 cs.AddSwitch("Startup", "firstname");
100 cs.AddSwitch("Startup", "lastname"); 136 cs.AddSwitch("Startup", "lastname");
101 cs.AddSwitch("Startup", "password"); 137 cs.AddSwitch("Startup", "password");
@@ -113,22 +149,27 @@ namespace pCampBot
113 // You can either say no, to not load anything, yes, to load one of the default wearables, a folder 149 // You can either say no, to not load anything, yes, to load one of the default wearables, a folder
114 // name, to load an specific folder, or save, to save an avatar with some already existing wearables 150 // name, to load an specific folder, or save, to save an avatar with some already existing wearables
115 // worn to the folder MyAppearance/FirstName_LastName, and the load it. 151 // worn to the folder MyAppearance/FirstName_LastName, and the load it.
152
116 Console.WriteLine( 153 Console.WriteLine(
117 "usage: pCampBot <-loginuri loginuri> [OPTIONS]\n" + 154 "Usage: pCampBot -loginuri <loginuri> -firstname <first-name> -lastname <last-name> -password <password> [OPTIONS]\n"
118 "Spawns a set of bots to test an OpenSim region\n\n" + 155 + "Spawns a set of bots to test an OpenSim region\n\n"
119 " -l, -loginuri loginuri for sim to log into (required)\n" + 156 + " -l, -loginuri loginuri for grid/standalone (required)\n"
120 " -n, -botcount number of bots to start (default: 1)\n" + 157 + " -s, -start start location for bots (default: last) (optional). Can be \"last\", \"home\" or a specific location with or without co-ords (e.g. \"region1\" or \"region2/50/30/90\"\n"
121 " -firstname first name for the bots\n" + 158 + " -firstname first name for the bots (required)\n"
122 " -lastname lastname for the bots. Each lastname will have _<bot-number> appended, e.g. Ima Bot_0\n" + 159 + " -lastname lastname for the bots (required). Each lastname will have _<bot-number> appended, e.g. Ima Bot_0\n"
123 " -password password for the bots\n" + 160 + " -password password for the bots (required)\n"
124 " -b, behaviours behaviours for bots. Comma separated, e.g. p,g. Default is p\n" + 161 + " -n, -botcount number of bots to start (default: 1) (optional)\n"
125 " current options are:\n" + 162 + " -f, -from starting number for login bot names, e.g. 25 will login Ima Bot_25, Ima Bot_26, etc. (default: 0) (optional)\n"
126 " p (physics)\n" + 163 + " -c, -connect connect all bots at startup (optional)\n"
127 " g (grab)\n" + 164 + " -b, behaviours behaviours for bots. Comma separated, e.g. p,g (default: p) (optional)\n"
128 " t (teleport)\n" + 165 + " current options are:\n"
129// " c (cross)" + 166 + " p (physics - bots constantly move and jump around)\n"
130 " -wear set appearance folder to load from (default: no)\n" + 167 + " g (grab - bots randomly click prims whether set clickable or not)\n"
131 " -h, -help show this message"); 168 + " n (none - bots do nothing)\n"
169 + " t (teleport - bots regularly teleport between regions on the grid)\n"
170// " c (cross)\n" +
171 + " -wear folder from which to load appearance data, \"no\" if there is no such folder (default: no) (optional)\n"
172 + " -h, -help show this message.\n");
132 } 173 }
133 } 174 }
134} 175}